Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Unix domain socket (local) forwarding #31

Merged
merged 1 commit into from
Mar 8, 2016

Conversation

RasterBurn
Copy link
Contributor

My goal is to support socket forwarding similar to what OpenSSH 6.7 supports. In my case, I am only supporting forwarding to a Unix domain socket on the local side of the forward, not on the remote end.

The benefit I'm gaining out of this patch is that I can forward a remote port to a local Unix domain socket, so only users on the system that have read permissions on socket file can connect to the tunnel. This, I believe, will be more secure on a multiuser system.

To use socket forwarding, just replace your local_bind_address tuple with a string that represents the unix socket path:

from sshtunnel.sshtunnel import SSHTunnelForwarder
from time import sleep
import os
os.umask(077)
with SSHTunnelForwarder(
    ('remotehost',22),
    ssh_username='myusername',
    ssh_password='mysecretpassword',
    local_bind_address='/tmp/foo.sock') as server:
    while True:
        # press Ctrl-C for stopping
        sleep(1)
print "FINISH!"

To implement this functionality, I created two new ForwardServer classes:

  • _UnixStreamFowardServer
  • _ThreadingUnixStreamForwardServer

These are no different than their _ForwardServer counterparts except that they use TCPServer's subclass: UnixStreamServer (see docs). UnixStreamServer uses Unix domain sockets, so it's not usable on Windows.

When local_bind_address is a tuple, the code will use the existing _ForwardServer, and otherwise it will select the _UnixStreamForwardServer.

I am a little concerned about the _ForwardHandler code where I have to pass paramiko's open_channel a fake source address. First off, paramiko doesn't support the socket forwarding protocol yet (paramiko/paramiko#544 seeks to implement this). Even so, this code still seems to work with "direct-tcpip".

Second, when using the AF_UNIX address family, getpeername returns a a string instead of an address tuple like AF_INET (ref docs). When I detect that getpeername doesn't return a tuple, I assume it's AF_UNIX, and then generate a dummy address tuple.

check_host(address[0])
check_port(address[1])
return
assert isinstance(address, basestring),\
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this python 3.x compatible?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use string_types

@pahaz
Copy link
Owner

pahaz commented Dec 22, 2015

This is realy cool reature. But do you have any time for merge you changes with master? Can you write test for check this functionality?

@pahaz
Copy link
Owner

pahaz commented Feb 11, 2016

Is this feature interesting for anyone else?

@fernandezcuesta
Copy link
Collaborator

Yes, looks like an interesting enhancement, maybe for 0.0.8?

@fernandezcuesta fernandezcuesta added this to the 0.0.8 milestone Feb 24, 2016
fernandezcuesta added a commit that referenced this pull request Feb 24, 2016
@fernandezcuesta fernandezcuesta merged commit ac5ba79 into pahaz:master Mar 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants