Back in March this year I had a post in which I described a backup plan to access my cloud services at home over the cellular network in case of a DSL line failure. The core of the solution is a Raspberry Pi sitting behind a cellular router waiting for an incoming ssh connection over which I can then access my other machines. The Pi allows access to other machines on the network either from the command line, or via the Pi's graphical user interface that I can forward through the ssh tunnel using VNC.
Forwarding the GUI over the tunnel is quite useful for accessing the web based user interfaces of my DSL gateway and cellular gateway routers via a web browser running on the Pi to analyze the fault and to modify port forwarding settings. A shortcoming of this approach, however, is that the web browser is quite slow on the Pi, especially when used remotely. Also, it doesn't handle some of the web page input fields very nicely, so some configuration tasks are a bit tricky. When a colleague recently showed me a much simpler and faster solution, I immediately jumped ship:
Instead of forwarding the graphical user interface of the Pi through the ssl tunnel, the ssh client can also be used as a SOCKS proxy for Firefox (or any other browser for that matter) running on my notebook. When a web browser is used in SOCKS proxy mode, all web page requests are tunneled from the local ssh SOCKS proxy tcp port to the SOCKS proxy server running as part of the ssh daemon process.
In practice, it's surprisingly simple to set-up. On the Raspberry Pi side, no configuration whatsoever is necessary! On the client side, the command to start the ssl client as as SOCKS proxy looks as follows on the Linux command shell (on a Windows machine, Putty should do the trick):
ssh -D 10123 -p 22999 firstname.lastname@example.org
In this example, 10123 is the local port number that has to be used as the SOCKS port number in Firefox as shown in the picture on the left. The '-p 22999' is optional and is given in case the ssh server is mapped away from the standard port 22 for ssh to 10123.
In Firefox, the SOCKS proxy mode has to be configured as shown in the image. In addition 'network.proxy.socks_remote_dns' has to be set to 'true' in 'about:config' so the browser also forwards DNS requests through the SOCKS connection.
Obviously, transmitting html pages instead of screen updates over the ssh connection makes the process of interacting with the web interfaces of the remote routers a lot snappier. And by the way: The proxying is not limited to web servers in my network at home as the SOCKS server running as part of the ssh daemon on the Raspi is also happy to establish a TCP connection to any server on the Internet. Also, any other SOCKS capable program such as the Thunderbird email client can use the proxy to tunnel their traffic.
Before my colleague told me I never thought this could actually be done by ssh, as this proxying capability is not part of of the original ssh functionality. Wikipedia has a nice post on how SOCKS works: When a SOCKS capable program (e.g. Firefox) contacts the proxy for a new TCP connection for the first time from a new TCP port, it tells the local SOCKS front end which IP address and port it wants to contact. The front end then contacts the SOCKS backend over the ssh tunnel on the Raspberry Pi which in turn will create the connection to the requested IP address and TCP port. The browser then goes ahead and sends the http request over this connection. The SOCKS frontend can establish many independend TCP connections simultaneously as it can distinguish different data streams from the local TCP port the socks capable program has initially established the connection from. How nifty 🙂