Transparent proxy server that works as a poor man's VPN. Forwards over ssh. Doesn't require admin. Works with Linux and MacOS. Supports DNS tunneling.
Go to file
Avery Pennarun 4fde980f46 firewall.py: MacOS: permanently set the net.inet.ip.scopedroute sysctl.
If this sysctl isn't set to 0 at the time your network interface is brought
up, and we later change it, then the MacOS (10.6.6 at least) ARP table gets
totally confused and networking stops working about 15 minutes later, until
you down and re-up the interface.  The symptom is that pings outside your
LAN would give results like this:

    ping: sendto: no route to host

and "arp -a -n" would show *two* entries for your default gateway instead of
just one.

sshuttle was helpfully putting the sysctl back the way it was when it shuts
down, so you would fix your network by downing the interface, so sshuttle
would abort and change the sysctl back, then you would re-up the interface,
then restart sshuttle, and sshuttle would change the sysctl back and restart
the cycle: it would break again a few minutes later.

That's annoying, and it gives sshuttle a bad reputation for being the thing
that breaks your network.  I can't find a *really* good workaround for the
bug, so barring that, let's just permanently set the sysctl to 0 and not
change it back on exit.  That should just leave your computer back how it
worked in MacOS 10.5, as far as I know, which seems harmless.  At least I've
been running my Mac that way for a few days and I haven't seen any
weirdness.

Now, doing *that* would still mean that the first sshuttle session after a
reboot would still break the network, since sysctl changes are lost on
reboot.  Thus, let's be extra hardcore and write it to /etc/sysctl.conf so
that it goes the way we want it after a reboot.  Thus, sshuttle should break
your network at most once.  Which still sucks, but hopefully nobody will
notice.
2011-02-04 21:55:40 -08:00
compat compat/ssubprocess.py: some python versions don't have os.closerange(). 2010-10-01 19:26:56 -07:00
ui-macos ui-macos: move the noLatencyControl setting to a per-connection setting. 2011-02-04 21:40:44 -08:00
.gitignore Add a sshuttle.8 manpage. 2010-11-09 01:59:51 -08:00
assembler.py Implement the optional fullness checking a bit more like I like it. 2011-01-25 21:07:39 -08:00
client.py Add --wrap option to force channel number wrapping at a lower number. 2011-02-02 02:32:46 -08:00
firewall.py firewall.py: MacOS: permanently set the net.inet.ip.scopedroute sysctl. 2011-02-04 21:55:40 -08:00
helpers.py Move client._islocal() to helpers.islocal() in preparation for sharing. 2011-01-26 05:25:26 -08:00
hostwatch.py import and use subprocess.py from python 2.6. 2010-10-01 12:11:48 -07:00
LICENSE Initial commit. 2010-05-01 16:15:37 -04:00
main.py Add --wrap option to force channel number wrapping at a lower number. 2011-02-02 02:32:46 -08:00
Makefile Add a sshuttle.8 manpage. 2010-11-09 01:59:51 -08:00
options.py options: remove unused 'exe' parameter 2011-01-25 21:19:28 -08:00
README.md Make password prompting more clear. 2010-11-08 23:35:16 -08:00
server.py dns: trim DNS channel handlers after a response, or after a timeout. 2011-01-26 02:34:46 -08:00
ssh.py Implement the optional fullness checking a bit more like I like it. 2011-01-25 21:07:39 -08:00
sshuttle Initial commit. 2010-05-01 16:15:37 -04:00
sshuttle.md man page for the --no-latency-control option. 2011-01-25 21:30:29 -08:00
ssnet.py Add --wrap option to force channel number wrapping at a lower number. 2011-02-02 02:32:46 -08:00
ssyslog.py ssyslog.py: use daemon.notice instead of daemon.info 2011-01-01 00:28:31 -08:00
stresstest.py stresstest.py: a program to create lots and lots of TCP connections. 2011-02-04 21:37:22 -08:00

sshuttle: where transparent proxy meets VPN meets ssh

As far as I know, sshuttle is the only program that solves the following common case:

  • Your client machine (or router) is Linux, FreeBSD, or MacOS.

  • You have access to a remote network via ssh.

  • You don't necessarily have admin access on the remote network.

  • The remote network has no VPN, or only stupid/complex VPN protocols (IPsec, PPTP, etc). Or maybe you are the admin and you just got frustrated with the awful state of VPN tools.

  • You don't want to create an ssh port forward for every single host/port on the remote network.

  • You hate openssh's port forwarding because it's randomly slow and/or stupid.

  • You can't use openssh's PermitTunnel feature because it's disabled by default on openssh servers; plus it does TCP-over-TCP, which has terrible performance (see below).

Prerequisites

  • sudo, su, or logged in as root on your client machine. (The server doesn't need admin access.)

  • If you use Linux on your client machine: iptables installed on the client, including at least the iptables DNAT, REDIRECT, and ttl modules. These are installed by default on most Linux distributions. (The server doesn't need iptables and doesn't need to be Linux.)

  • If you use MacOS or BSD on your client machine: Your kernel needs to be compiled with IPFIREWALL_FORWARD (MacOS has this by default) and you need to have ipfw available. (The server doesn't need to be MacOS or BSD.)

This is how you use it:

  • git clone git://github.com/apenwarr/sshuttle on your client machine. You'll need root or sudo access, and python needs to be installed.

  • ./sshuttle -r username@sshserver 0.0.0.0/0 -vv

(You may be prompted for one or more passwords; first, the local password to become root using either sudo or su, and then the remote ssh password. Or you might have sudo and ssh set up to not require passwords, in which case you won't be prompted at all.)

That's it! Now your local machine can access the remote network as if you were right there. And if your "client" machine is a router, everyone on your local network can make connections to your remote network.

You don't need to install sshuttle on the remote server; the remote server just needs to have python available. sshuttle will automatically upload and run its source code to the remote python interpreter.

This creates a transparent proxy server on your local machine for all IP addresses that match 0.0.0.0/0. (You can use more specific IP addresses if you want; use any number of IP addresses or subnets to change which addresses get proxied. Using 0.0.0.0/0 proxies everything, which is interesting if you don't trust the people on your local network.)

Any TCP session you initiate to one of the proxied IP addresses will be captured by sshuttle and sent over an ssh session to the remote copy of sshuttle, which will then regenerate the connection on that end, and funnel the data back and forth through ssh.

Fun, right? A poor man's instant VPN, and you don't even have to have admin access on the server.

Theory of Operation

sshuttle is not exactly a VPN, and not exactly port forwarding. It's kind of both, and kind of neither.

It's like a VPN, since it can forward every port on an entire network, not just ports you specify. Conveniently, it lets you use the "real" IP addresses of each host rather than faking port numbers on localhost.

On the other hand, the way it works is more like ssh port forwarding than a VPN. Normally, a VPN forwards your data one packet at a time, and doesn't care about individual connections; ie. it's "stateless" with respect to the traffic. sshuttle is the opposite of stateless; it tracks every single connection.

You could compare sshuttle to something like the old Slirp program, which was a userspace TCP/IP implementation that did something similar. But it operated on a packet-by-packet basis on the client side, reassembling the packets on the server side. That worked okay back in the "real live serial port" days, because serial ports had predictable latency and buffering.

But you can't safely just forward TCP packets over a TCP session (like ssh), because TCP's performance depends fundamentally on packet loss; it must experience packet loss in order to know when to slow down! At the same time, the outer TCP session (ssh, in this case) is a reliable transport, which means that what you forward through the tunnel never experiences packet loss. The ssh session itself experiences packet loss, of course, but TCP fixes it up and ssh (and thus you) never know the difference. But neither does your inner TCP session, and extremely screwy performance ensues.

sshuttle assembles the TCP stream locally, multiplexes it statefully over an ssh session, and disassembles it back into packets at the other end. So it never ends up doing TCP-over-TCP. It's just data-over-TCP, which is safe.

Useless Trivia

Back in 1998 (12 years ago! Yikes!), I released the first version of Tunnel Vision, a semi-intelligent VPN client for Linux. Unfortunately, I made two big mistakes: I implemented the key exchange myself (oops), and I ended up doing TCP-over-TCP (double oops). The resulting program worked okay - and people used it for years - but the performance was always a bit funny. And nobody ever found any security flaws in my key exchange, either, but that doesn't mean anything. :)

The same year, dcoombs and I also released Fast Forward, a proxy server supporting transparent proxying. Among other things, we used it for automatically splitting traffic across more than one Internet connection (a tool we called "Double Vision").

I was still in university at the time. A couple years after that, one of my professors was working with some graduate students on the technology that would eventually become Slipstream Internet Acceleration. He asked me to do a contract for him to build an initial prototype of a transparent proxy server for mobile networks. The idea was similar to sshuttle: if you reassemble and then disassemble the TCP packets, you can reduce latency and improve performance vs. just forwarding the packets over a plain VPN or mobile network. (It's unlikely that any of my code has persisted in the Slipstream product today, but the concept is still pretty cool. I'm still horrified that people use plain TCP on complex mobile networks with crazily variable latency, for which it was never really intended.)

That project I did for Slipstream was what first gave me the idea to merge the concepts of Fast Forward, Double Vision, and Tunnel Vision into a single program that was the best of all worlds. And here we are, at last, 10 years later. You're welcome.

-- Avery Pennarun apenwarr@gmail.com

Mailing list: Subscribe by sending a message to sshuttle+subscribe@googlegroups.com List archives are at: http://groups.google.com/group/sshuttle