Every once in a while, I learn something new and magical that SSH can do.  For a while now, I have been using its “dynamic port forwarding” capability, and I wanted to share that here.

Dynamic port forwarding is a way to create a SOCKS proxy that listens on your local machine, and forwards all traffic through the SSH tunnel to the remote side, where it will be passed along to the remote network.

What this means is that you can tell your web browser to send some – or all – of your web requests through the tunnel, and the SSH daemon on the other side will send those requests out to the internet for you, and then it will send the responses back through the tunnel to your browser.

There are several practical uses for SSH tunneling.  Here are a few real-world examples of where I have used tunnels:

  • You may be behind a firewall that blocks web sites that you want to visit. I was at a company that had a web proxy that blocked some “hacking” web sites, when I really needed to look up some information on computer vulnerabilities, to make sure that their systems were properly patched.  Using the SSH tunnel bypassed that company’s web proxy.
  • You may not trust a hotel’s internet service. In fact, you SHOULD NOT trust a hotel’s internet service.  They keep records of sites that you visit, ostensibly to keep a customer profile of your interests.  Some also do deep packet inspection to observe words in the web pages and emails that you read.  Intrusive marketing!
  • You may want to work from home, and access work lab resources from home. If you can SSH into one machine at work, then you can access the web resources inside that network.
  • Working on a cluster of machines, where only one of them is directly accessible from your desk. It stinks to have to do your work in a noisy lab.  Why not shell into the gateway machine and tunnel your web traffic through that SSH connection?
  • You may want to access a web interface to something at home, like a printer… or an oven. You should open the SSH service to your router, and then you can SSH in and easily access web interfaces to everything in your home.
  • You may want a web interface on some service on an internet-facing machine, but you don’t want to expose it to everyone. Maybe you want phpMyAdmin on a server, but you don’t want everyone to see it. So run the web service on the local ( network only, and use an SSH tunnel to get to it from wherever you are.
  • Your ISP throttles web traffic from a particular site. In my case, it was an overseas movie streaming site, and my ISP would limit my traffic to 300kbps for 30 seconds, followed by nothing for 30 seconds (they do this to discourage you from watching movies over the internet).  Sending the traffic through an SSH tunnel means the ISP only sees an encrypted stream of something on port 22 — they have no idea that the content is actually a movie streamed from China on port 80.
  • You may live in India, but want to watch a show on Hulu (which only serves the US market).  By tunneling through a US-based server, it will appear to Hulu that you’re in the US.
  • You may be visiting China, and you want to bypass the Great Firewall of China. Believe it or not, my humble domain was not accessible directly from Shanghai.
  • You may get a “better” route by going through a proxy. This is speculation on my part… but I did this once when I was in a free-for-all online ticket purchase.  I wondered if I might get a faster route from my remote data center than I would get directly from my ISP.

So, how do you create a tunnel?  It’s super easy.

Create an SSH session with a tunnel.

On Linux or a Mac, open a shell and type “ssh -D 10000 username@remotehost.com“.

On Windows*, you can run Putty (an SSH client).  In the “connection / SSH / tunnels” menu, click on “dynamic”, then enter source port = 10000, then click “add”.  You’ll see a “D10000” in the box that lists your forwarded ports.  (* Putty is also available for Linux.)

That’s it… you’re done.

Tell the browser to use the tunnel.

The easiest way to get started with SOCKS proxies is to set it in the “preferences / advanced / network / connection settings” menu in Firefox (or the “preferences / under the hood / change proxy settings” menu in Google Chrome).  In both cases, you want to set “manual proxy configuration” and SOCKS host = “localhost” and SOCKS port = 10000.  If there is a selection for SOCKS v5, then check it.

Now, all web requests will go to a proxy that is running on your local machine on port 10000.  If you do a “netstat -plnt | grep 10000”, you’ll see that your SSH or Putty session is listening on port 10000.  SSH then forwards the web request to the remote machine, where SSHD will send it on out to the internet.  Web responses will come back along that same path.

Anyone on your local network will only be able to see one connection coming from your machine: an encrypted SSH session to the remote.  They will not see the web requests or responses.  This makes it a great tool for using on public networks, like coffee shops or libraries.

Test it

Point your browser to a site that tells you your IP address, such as whatismyip.com.  It should report the IP address of the remote server that you are connecting through, and not your local IP address.

Advanced – quickly selecting proxies using FoxyProxy or Proxy Switchy!

It can be a hassle to go into the preferences menu to turn the proxy on and off.  So there are browser plug-ins that allow you to quickly switch between a direct connection and using a SOCKS proxy.

For Firefox, there is the excellent “FoxyProxy“.  For Chrome, you’ll want “Proxy Switchy!“.  Both plug-in’s allow you to select a proxy using a button on the main browser window.

But there’s more… they also allow you build a list of rules to automatically switch based on the URL that you are browsing.  For example, at work, I set up a rule to route all web requests for the lab network through my SSH session that goes to the lab gateway machine.

It works like this.  First, I set up a tunnel to the lab gateway machine:

  • ssh -D 10001 alan@ (lab gateway)

Then I set up the following FoxyProxy rules:

  • 192.168.100.* – SOCKS localhost:10001 (SSH to lab)
  • anything else – direct

Now, I can get to the lab machines using the lab proxy, and any other site that I access uses the normal corporate network.

Closing thoughts

If you like Putty or FoxyProxy or Proxy Switchy!, please consider donating to the projects to support and encourage the developers.