Use SSH As a SOCKS Proxy

Use SSH As a SOCKS Proxy

Protect your web traffic using the basic VPN functionality built into SSH itself.

In the search for the perfect way to secure their wireless networks, many people overlook one of the most useful features of SSH: the -D switch. This simple little switch is buried near the bottom of the SSH manpage. Here is a direct quote from the manpage:

-D port

Specifies a local "dynamic" application-level port forwarding. This works by allocating a socket to listen to port on the local side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS 4 protocol is supported, and SSH will act as a SOCKS 4 server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file.

This turns out to be an insanely useful feature if you have software that is capable of using a SOCKS 4 proxy. It effectively gives you an instant encrypted proxy server to any machine to which you can SSH, and it does so without the need for further software on either your machine or the remote server.

Just as with SSH port forwarding [Hack #96], the -D switch binds to the specified local port, encrypts any traffic to that port, sends it down the tunnel, and decrypts it on the other side. For example, to set up a SOCKS 4 proxy from local port 8080 to remote, type the following:

[email protected]:~$ ssh -D 8080 

That's all there is to it. Now you simply specify localhost:8080 as the SOCKS 4 proxy in your application, and all connections made by that application will be sent down the encrypted tunnel. For example, to set your SOCKS proxy in Mozilla, go to PreferencesAdvancedProxies, as shown in Figure.

Proxy settings in Mozilla

Select "Manual proxy configuration" and type in localhost as the SOCKS host. Enter the port number that you passed to the -D switch, and be sure to check the SOCKSv4 button.

Click OK, and you're finished. All of the traffic that Mozilla generates is now encrypted and appears to originate from the remote machine that you logged into with SSH. Anyone listening to your wireless traffic now sees a large volume of encrypted SSH traffic, but your actual data is well protected.

One important point is that SOCKS 4 has no native support for DNS traffic. This has two important side effects to keep in mind when using it to secure your wireless transmissions.

First of all, DNS lookups are still sent in the clear. This means that anyone listening in can still see the names of sites that you browse to, although the actual URLs and data are obscured. This is rarely a security risk, but it is worth bearing in mind.

Second, you are still using a local DNS server, but your traffic originates from the remote end of the proxy. This can have interesting (and undesirable) side effects when attempting to access private network resources.

To illustrate the subtle problems that this can cause, consider a typical corporate network with a web server called This web server uses the private address but is accessible from the Internet through the use of a forwarding firewall. The DNS server for normally responds with different IP addresses depending on where the request comes from, perhaps using the views functionality in BIND 9. When coming from the Internet, you would normally access with the IP address, which is actually the IP address of the outside of the corporate firewall.

Now, suppose that you are using the SOCKS proxy example just shown, and remote is actually a machine behind the corporate firewall. Your local DNS server returns as the IP address for (since you are looking up the name from outside the firewall), but the HTTP request actually comes from remote and attempts to go to This is often forbidden by the firewall rules, because internal users are supposed to access the intranet by its internal IP address, How can you work around this DNS schizophrenia?

One simple method to avoid this trouble is to make use of a local hosts file on your machine. Add an entry like this to /etc/hosts (or the equivalent on your operating system):

In this manner, you can list any number of hosts that are reachable only from the inside of your corporate firewall. When you attempt to browse to one of those sites from your local machine through remote (via the SOCKS proxy), the local hosts file is consulted before DNS, so the private IP address is used. Since this request is actually made from remote, it finds its way to the internal server with no trouble. Likewise, responses arrive back at the SOCKS proxy on remote, are encrypted and forwarded over your SSH tunnel, and appear in your browser as if they came in from the Internet.

SOCKS 5 support is planned for an upcoming version of SSH, which will also make tunneled DNS resolution possible. This is particularly exciting for Mac OS X users, as there is support in the OS for SOCKS 5 proxies. Once SSH supports SOCKS 5, every native OS X application will automatically be able to take advantage of encrypting SSH SOCKS proxies. In the meantime, we'll just have to settle for encrypted HTTP proxies [Hack #98].

Rob Flickenger

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows