Using SOCKS5 Over SSH for Web Browsing

You’re on the road, connected to a wi-fi network you don’t trust, and you want to do some web browsing without having your traffic sniffed. A VPN connection would solve the problem, but all you really want is to keep your web session from prying eyes.

If you have three things, you’re in luck:

  • OpenSSH installed on your local system
  • A remote system to which you can establish an SSH connection
  • Firefox

Setting up the SSH tunnel

Modern versions of OpenSSH can emulate a SOCKS5 server and tunnel the proxied traffic over your encrypted SSH session. You can see the gory details in the ssh(1) man page; look for the -D option.

For the sake of example, I’ll assume you have an account on a machine named your.remote.host. The init-style script below takes care of starting and stopping the proxy.

#!/bin/sh
#
# control an SSH-managed SOCK5 proxy
#
# This script works on MacOS; the lsof invocation needs changing
# to work on Linux or other platforms.
#
# ======================================================================
  
# grab a PID for any process listening on 1080/tcp and see if
# we get a return value that passes for a positive integer
PROXYPID=$(lsof -Fp -i 4:1080 -s TCP:LISTEN | grep '^p' | sed 's/^p//')
(($PROXYPID))
RETVAL=$?
  
# set PROXYPID to 0 if it's non-existent or not an integer
if test $RETVAL -eq 1; then
  PROXYPID=0
fi
  
# test the command-line argument: start, stop, or status
case "$1" in
  start)
    if test $PROXYPID -gt 0; then
      echo "SOCKS proxy already running. Exiting now!" 1>&2
    else
      /usr/bin/ssh -f -N -C -D 1080 your.remote.host
    fi
    ;;
  stop)
    if test $PROXYPID -gt 0; then
      kill $PROXYPID
    else
      echo "SOCKS proxy doesn't appear to be running." 1>&2
    fi
    ;;
  status)
    if test $PROXYPID -gt 0; then
      echo "SOCKS proxy running as PID $PROXYPID"
    else
      echo "SOCKS proxy doesn't appear to be running."
    fi
    ;;
  *)
    echo "usage: $(basename $0) {start|stop|status}"
    ;;
esac
# eof

A couple notes on the script:

  • If you don’t have, or don’t want to use, a sh-compatible shell for this, the only really important bit in the whole script is line 24, which invokes ssh.
  • The ssh -D option can also take an address or hostname, but the default (which I use) is the loopback address, aka localhost.
  • I use port 1080 in the script because it’s called the socks port in /etc/services, but the number is basically arbitrary; you can use most any valid port number. (If you use another number, be sure to make the corresponding adjustment in the Firefox configuration below.)

If you install the script as socks-proxy, then you can start the proxy tunnel by invoking it with the start option:

socks-proxy start

Configuring Firefox to use the tunnel

Launch Firefox and enter about:config where you’d normally the address of the site you want to visit. You’ll probably see a sinister warning advising you that This might void your warranty! Oh, well! March on!

In the search box just above the long list of configuration options, type proxy. You’ll be rewarded with a much smaller list of options. Here are the ones you want to change and their new values:

  • network.proxy.socks: localhost
  • network.proxy.socks_port: 1080
  • network.proxy.socks_remote_dns: true
  • network.proxy.type: 1

Assuming your SSH tunnel/proxy is already running, you should be able to browse the web safely at this point. You can verify your setup by asking Google what is my ip address. It should display the address for your.remote.host. (Note: it may display an IPv6 address if you’ve got it configured on your local host and your remote host.)

Howto