Secure Web Access Through SSH Tunnel (SOCKS Proxy Server)
Mon 07 December 2015How to setup a dynamic SSH tunnel (also called SOCKS proxy server) and use it daily with Firefox and Thunderbird.
Introduction
I'm a kind of "digital nomad" (yeah I just like the expression :)). I use to go around with my laptop on my back, and I connect to the net from various places, like coffees, hotels, swimming-pools (yes :)), or whatever places that provide wifi.
I don't trust these access-points so much, and I've been wondering what kind of trick could be done to improve the security. It turns out that it's quite easy to go with SSH tunnels, and that there's no need of OpenVPN.
Notice that I have nothing against OpenVPN, but it just happens that I have a VPS out there, and of course I already have the OpenSSH daemon up and running on this VPS. I'm not a skilled sysadmin, so I don't want to install too much stuff and add plenty of doors to my server. The less doors the better.
SSH is already there, and it's fit for the job: SSH server can act as a SOCKS proxy server, and it's so simple you won't believe it...
One last word, this post provides specific solutions for Firefox and Thunderbird, as they're my favorite apps to surf the web.
SSH tunneling
Creating a tunnel to your remote server is achieved with only one line:
ssh -N -D 5222 user@vps
Let's quote the SSH manual page:
-N
Do not execute a remote command. This is useful for just forwarding ports.-D port
Specifies a local "dynamic" application-level port forwarding. [...] ssh will act as a SOCKS server.- We use the port 5222 in this example, but you can use whatever port you want.
This simple command opens a tunnel to vps
, aka the host where a friendly SSH server
is waiting for you to connect.
If you want to know more, I recommend this Linux Journal article:
SSH Tunneling - Poor Techie's VPN
Testing with Firefox
In order to test that, you must configure your web browser to use a proxy. Here is the procedure with Firefox:
- Go to Preferences > Advanced > Network > Settings
- Choose
Manual proxy configuration
- Fill the field
SOCKS Host
withlocalhost
- Set the right port (
5222
in this example) - Check
SOCKS v5
- Click OK
And that's all. Now Firefox sends its traffic to localhost:5222
, which is the
entrance of the SSH encrypted tunnel. Data goes through the tunnel and ends
up on your VPS, where the SSH daemon forwards it to the web...
Daily usage with Firefox and Thunderbird
Now that things work, what I want is a convenient way to use it. That is, I don't need to go through a proxy when I'm home, but as soon as I'm out, I'd like to enable the proxy easily. A one-line shell command would be sweet.
Basically, there are only two applications that should use the proxy: Firefox for web browsing, and Thunderbird for emails.
Of course, I can change the settings of both apps each time I'm out, and change it back when I'm home. But, how tedious is that!
Furthermore, if I do that manually, I must be careful to do things in the right order:
- Launch the apps, enable the proxy
- Connect to the WLAN (Wireless LAN)
- Open the SSH tunnel
- Start doing stuff
The key is to enable the proxy before connecting to the WLAN! If I do it the other order, when I launch Thunderbird, the first thing it does is to send my password out on the LAN before I have time to change the proxy settings. Enabling the proxy after that is quite useless, passwords have been leaked already...
Doing things manually is always error prone, but you already knows that if you're an IT guy like me.
So it's better to automate things. Somehow, I would like to declare my proxy settings system wide, so that applications can automatically know it, and use the proxy to go on the WAN.
Attempt 1: pure environment variables [FAILURE]
Ok, so after browsing the web, I found what seems to be the perfect solution:
declaring the proxy settings in environment variables, and letting applications
handle that by themselves. For example, Firefox can be configured to
Use system proxy settings
, as they say.
So the idea is to declare the proxy in the environment, but what variables should we use? It seems that there is no consensus about that. If you have a look at the ArchLinux wiki, you can see that the guys define plenty of variables, just to be sure. Then you pray that your favorite application picks up one of these and honor it...
So here we go:
export all_proxy=socks://localhost:5222
export http_proxy=$all_proxy
export https_proxy=$all_proxy
export ftp_proxy=$all_proxy
export rsync_proxy=$all_proxy
export ALL_PROXY=$all_proxy
export HTTP_PROXY=$all_proxy
export HTTPS_PROXY=$all_proxy
export FTP_PROXY=$all_proxy
export RSYNC_PROXY=$all_proxy
Then, you launch Firefox from the same shell (since environment variables only live in the shell where they're defined, and its sub-processes), and Firefox should pick up these values and use it.
But somehow, it just doesn't work, Firefox ignores all the stuff we defined in the environment.
If you like to read, there's a good discussion about that on the Ubuntu forums:
Configuring Firefox to use a proxy from the command line
So long for the environment variables...
Attempt 2: environment variables & add-ons [SUCCESS]
So I kept on googling around, and it just happens that someone wrote an add-on for Firefox to fix that. It's named "Environment Proxy", and there's a version for Firefox and for Thunderbird.
I'm not a big fan of the add-on solution. Simply because the add-on can break at any Firefox/Thunderbird update. If you update your system steadily like me, you probably noticed that there's a new Firefox version every two months. So the add-on may let you down on a regular basis, and it's a little bit scary. Furthermore, if the add-on is not maintained thoroughly by its author, you're screwed, and you find yourself with the same problem to solve all over again...
Well, that's just my point of view on it. Anyway, I made an exception for this time, I tried this add-on, it works!
Have a look at the documentation page, it says which environment variable you should define. For SSH tunnel and SOCKS proxy, just one variable is needed:
export SOCKS_SERVER=localhost:5222
But beware! Exporting a variable is nice, but don't forget it lives only in the shell and its sub-processes. So now you must start Firefox from this shell, otherwise you won't use the proxy.
OK, so because I'd like to avoid mistakes, and don't want to type too many commands, I wrote a script! Here it is:
#!/bin/bash
#
# Ssh command, thanks to:
# http://unix.stackexchange.com/q/29912/105794
USER=root
HOST=vps
PORT=5222
SOCKET=/tmp/ssh_tunnel_${HOST}.sock
pgrep iceweasel >/dev/null 2>&1 && \
{ echo >&2 "Iceweasel already running, please stop it..."; exit 1; }
pgrep icedove >/dev/null 2>&1 && \
{ echo >&2 "Icedove already running, please stop it..."; exit 1; }
[[ -e $SOCKET ]] && \
{ echo >&2 "SSH tunnel already opened, please close it..."; exit 1; }
echo "Opening SSH tunnel, please wait..."
ssh -f -N -D $PORT -M -S $SOCKET -o ExitOnForwardFailure=yes $USER@$HOST || \
{ echo >&2 "Failed to open SSH tunnel"; exit 1; }
echo "Exporting environment variables..."
export SOCKS_SERVER=localhost:$PORT
echo -n "Starting iceweasel... "
(iceweasel >/dev/null 2>&1) &
weasel_pid=$!
echo $weasel_pid
echo -n "Starting icedove... "
(icedove >/dev/null 2>&1) &
dove_pid=$!
echo $dove_pid
echo "To end the session, just close iceweasel & icedove"
wait $weasel_pid $dove_pid
echo "Unexporting environment variables..."
unset SOCKS_SERVER
echo "Closing tunnel..."
ssh -S $SOCKET -O exit $USER@$HOST
echo "Done"
Notice that I use iceweasel
and icedove
instead of firefox
and thunderbird
.
This is the same thing, just the name is different on Debian.
Another solution: proxychains [SUCCESS]
If you don't like the add-on solution, or if you don't use Firefox and Thunderbird, and prefer a more generic solution, here it is.
I found that there are some pieces of software called proxifiers. They work by intercepting and modifying the network requests sent by a given program. I can mention two of them: tsocks and proxychains. I think both are fit for the job.
I tried proxychains.
Pretty simple to install:
apt-get install proxychains
Pretty simple to configure:
vi /etc/proxychains.conf
Just comment out the last line, and add your own proxy config:
socks5 127.0.0.1 5222
After that, just use proxychains to start your apps:
proxychains firefox
Conclusion
So as you can see, it was a long way for a simple thing, as often it is when you go through the command-line and want to understand a little bit how things work.
Currently I go with the Firefox/Thunderbird add-ons, it works great. However I need to go through the command-line to use my proxy, I can't launch my applications from the menu icon. So it's not as transparent as I hoped in the beginning,
Using OpenVPN would have make it totally transparent I think...