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.