Setting Up a SOCKS Proxy Using OpenSSH

Web browsing on a public Wifi network is a security risk as it's quite simple to capture network traffic. Even if you only connect to SSL-protected sites, people can still find out which web sites you're accessing. Fortunately, there is a quick way to protect your privacy - all you need is a host on the public network that you can access via SSH.

OpenSSH provides a SOCKS proxy that your browser or any other application supporting SOCKS can use to securely tunnel network traffic to a host outside the insecure network. People on the insecure network will only see SSH-encrypted traffic and for the web sites you access it will look like traffic came directly from your proxy host.

Enabling SOCKS support in OpenSSH is quite simple:

$ ssh -D 4711

Now you have a service listening on localhost:4711 that you use as a SOCKS proxy server (any non-privileged port is fine). To save some typing, add the following section to your ~/.ssh/config file:

Host proxy
    DynamicForward 4711

Call it like this:

$ ssh proxy

Keep the SSH session open as long as you want to use the proxy and configure your browser to use the SOCKS proxy at localhost on port 4711. Note that the proxy is unauthenticated even though it only listens on the loopback interface by default. This means local users can use your proxy while remote users can't.

It's extremely important to validate your setup - false security is more dangerous than having no security at all. Due to bugs or misconfiguration, your applications may not use the proxy. Firefox, for example, will only route DNS traffic via SOCKS if the network.proxy.socks_remote_dns property is set to true. Always use a network traffic analyzer like tcpdump(1) or wireshark(1) to make sure everything works as intended.

Before enabling the proxy, network traffic should be sent to the destination host directly. Expect to see both DNS and HTTP traffic, but keep in mind that there may be caches on your system that you have to flush first.

After enabling the proxy, you should no longer see DNS or HTTP traffic. Instead, there should be SSH traffic every time you trigger an HTTP request from your browser.

As a first step, you can test your proxy using curl:

$ curl > /dev/null
$ curl --proxy socks5h://localhost:4711 > /dev/null

Curl has two relevant proxy protocols: socks5h and socks5. The former also sends DNS requests via the proxy while the latter doesn't. The following command makes tcpdump listen on all interfaces but doesn't place it in promiscuous mode:

$ sudo tcpdump -i any -p

On most desktop systems, you'll notice that your browser isn't the only application causing network traffic. You can try enabling SOCKS for your entire desktop session, but if your applications don't cooperate, you're out of luck. You could try proxifier tools that intercept network requests, but if you need a high level of security, you should really look into VPNs even though they are more difficult to set up.