SSH through SSH SOCKS Proxy

Setting up a SOCKS Proxy using ssh

Port forwarding in ssh is really great. Next to local and remote forwarding there is also dynamic port forwarding that essentially turns the ssh server into a SOCKS Proxy server. This means that you can actually route all the traffic of a local application through the ssh connection to the host — given that the application supports SOCKS Proxies. Dynamic port forwarding is set up using the -D switch followed by a port. The SOCKS proxy is then listening to outgoing traffic on this chosen port. For example

ssh -N -C -D 1234 user@host

establishes a proxy under localhost:1234 that directs traffic first to host and then to the desired destination. The -C enables compression, which increases the performance if mainly text is transferred. For transferring binary data, compression is almost useless and one should probably leave out the -C to save the overhead. The -N tells ssh that you don't want to run any commands, so it won't allocate a shell. This circumvents issues with hosts where port forwarding is allowed, but where proper user logins have been disabled (e.g. by allocating the shell /bin/false to the user).

ssh connections via a SOCKS proxy

Amongst the programs that speak SOCKS are all common web browsers and almost all programs shipped with the major LinuX desktop environments (e.g. Evolution, Thunderbird, Transmission, ...). SSH itself, however, cannot connect via a SOCKS proxy out of the box, but with a little help from the TCP/IP swiss army knife netcat it still can be done. E.g. in order to connect to host2 via the proxy we established above, simply run

ssh -o 'ProxyCommand nc -x localhost:1234 %h %p'  user2@host2

Here the ProxyCommand option tells ssh to pipe all traffic through the command that follows. The variables %h and %p are replaced by ssh with the host and port of the ssh connection, respectively. A few other such variables exist as well: Check out the manual for further information. In this case ssh would hence pipe the traffic through nc -x localhost:1234 host2 22. The latter command, however, is netcat-speak for opening a plain tcp connection to host2 on port 22 via the SOCKS Proxy listening on 1234 on the local machine. Overall we achieve what we want: ssh through an ssh SOCKS Proxy.

Note that there are two common netcat versions out there: You will need the OpenBSD version, which is the package netcat-openbsd on Debian.

Why is this useful?

Many companies and universities have the understandable policy to only expose a few machines to the public internet, whereas the majority can't be reached outside a network of trusted IPs. In the terminology of above, host would be one of the publicly exposed machines. Having established the SOCKS proxy to host we are part of the trusted network and can hence use all the internal services offered. For example we can now logon to the host2, even if it can't be reached directly from the Internet.

Note, that in principle we only need to be able to forward ports on host, no rights to properly login on this machine are required.