Ridiculously Easy SOCKS Proxy with ssh

Sometimes, ssh tunneling a port is insufficient. It’s fantastic if you want to remotely access some system, but suppose you want more of an ad-hoc VPN/proxy, to allow you to, say, browse the web through a remote system?

I thought about setting up squid on a remote system, but that would be a bit of work. Plus, I’d have to take care to lock it down so I wasn’t accidentally running an open proxy, which is all sorts of bad. I could also do OpenVPN, but that’s an even bigger headache to set up.

As it turns out, ssh includes native support for establishing a SOCKS proxy, too. Your local ssh client will stand up a SOCKS proxy on localhost, on a port you specify, and forward traffic through ssh to the remote system. You can then simply point your web browser at your local SOCKS server, and viola!

From the ssh manpage, it’s astonishingly easy:

     -D [bind_address:]port
             Specifies a local ``dynamic'' application-level port forwarding.  This works by
             allocating a socket to listen to port on the local side, optionally bound to the
             specified bind_address.  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 SOCKS4 and
             SOCKS5 protocols are supported, and ssh will act as a SOCKS server.  Only root can
             forward privileged ports.  Dynamic port forwardings can also be specified in the
             configuration file.

Add -N to stand up the tunnel but not give you a command prompt, and optionally -C to enable compression. (Typically only useful on slower connections.)

Putting it in action, it looks something like this:

mawagner ~ $ ssh -CND 8000 bos.n1zyy.com

It will continue to run in the foreground without any output. That’s all it takes—you’ve now got a SOCKS server running.

Now, configure your browser to use it. In Firefox, in the Preferences menu, Advanced › Network › Connection › Settings lets you set up a SOCKS proxy. Just fill in the SOCKS proxy line, with “localhost” for the hostname (not the remote server—ssh is listening on localhost and forwarding connections there for you) and whatever port you specified on the command line (8000 in my example).

Chrome seems to want this as command-line flags. On the Mac, it took this ridiculous command to launch:

$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --proxy-server="socks5://localhost:8000"

Take note that the SOCKS proxy will handle the actual connections, but DNS requests will still take place locally. If you’re trying to hide your traffic from an oppressive regime, this could be bad. It’ll also be bad if you’re trying to connect to something over a great distance and they’re using geo-DNS to steer you to the right place. But when your home ISP just sucks and you want to bypass their overloaded connection to Youtube, this is just the trick.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>