Tunneling Everything through SOCKS5

At my current employer, many administrator-level services (SSH, SQL, development servers) must be accessed over a VPN. Generally speaking, this is a Good Thing. However, it can be inconvenient: only one VPN connection is allowed per user, and all traffic is sent over the VPN regardless of its final destination.

The ssh client included in OpenSSH includes a very easy to use SOCKS5 proxy server: ssh -D 9999 server.example.com opens a normal connection to server.example.com, but also creates a SOCKS5 server at localhost:9999 that routes traffic from supported applications through the remote server. Firefox includes support for SOCKS5, and add-ons like the Web Developer toolbar and FoxyProxy can quickly enable or disable the proxy settings. I've used this to great success in the past, but, as with most things, there is room for improvement.

Server names and IPs have been modified from their original values.

Fine-tuning Firefox

While you can provide Firefox with a simple SOCKS5 host and port, the software also supports proxy auto-config (PAC) files. Both Firefox (natively) and Safari (via Network preferences) support PAC. The following PAC file tells the application to route traffic for anything at example.com through the proxy server, and directly connect to everything else. This keeps your non-business traffic from routing through business servers, so you can stream Netflix and still access those servers behind the firewall.

function FindProxyForURL(url, host) {
    if(shExpMatch(url, '*.example.com/*')) return "SOCKS localhost:9999";
    return "DIRECT";
}

Proxy Everything

While ssh can create a proxy server, there is no built-in support for connecting to a host through a proxy. The same is true for many other applications, particularly console apps. Enter tsocks, a wrapper library that intercepts TCP calls and routes them through a SOCKS proxy. tsocks exploits something call preloaded libraries: when ssh is launched, special flags in the shell force a load of the tsocks library. My preferred way of running tsocks is to run it with no arguments, which sets up the preloading for any program run in the shell from that point forward.

Marc Abramowitz did some great work getting tsocks to compile under Mac OS X. I made a few tweaks to his patch, and release it here. To apply the patch, take the same steps that Marc mentions on his site, but use my patch instead.

After tsocks is installed, running something through your proxy is easy. In this example, you open an SSH connection to a host, then tunnel traffic through it via SOCKS.

$ ssh -f -N -D 9999 public-server.example.com
$ tsocks
$ ssh firewalled-server.example.com

The first line creates a proxy server, the second prepares tsocks, and the third opens an SSH connection using the proxy defined in /etc/tsocks.conf. For completeness, here is my tsocks.conf:

local = 10.0.0.0/255.0.0.0

path {
    reaches = 129.21.0.0/255.255.0.0

    server = 127.0.0.1
    server_port = 9999

    server_type = 5
}

That's all. Secure access to firewalled servers through HTTP and SSH. Works great, as long as you have one server that can be used as a gateway (available for SSH from outside the network, but able to access things inside).

This article was originally written for Mac OS X 10.5 "Leopard," and setup is identical for Mac OS X 10.6 "Snow Leopard."