As I am a frequent guest in public WLANs I spent some time looking into ways to connect safely to both the corporate network and the rest of the internet while enjoying the amenities of a cafés’ or hotel’s wifi.
Because of its simplicity and universal availability I like SSH tunnels which are easily set up and even work on Android (for the sad state of encrypted VPNs on Android devices have a look at Issue 4706) with the excellent SSHTunnel.
The solution I am describing here is by no way my invention, just interesting bits and pieces glued together:
- Provides a SOCKS 5 proxy that runs locally and tunnels connections through a remote SSH server
- Runs automatically when a network is available
- Increases reliability and throughput on bad connections (i.e. public WLAN with bad reception) when compared to the plain connection
- Accepts plain password authentication so as to be set up easily
Apart from obvious system/network requirements and a remote server running SSH you need a local SSH client and the “expect” package (get it via apt-get install expect).
In an accessible path on your laptop create an expect script, i.e. proxy.expect:
/home/george/scripts/proxy.expect
#!/usr/bin/expect
set timeout 60
spawn ssh -2 -o TCPKeepAlive=no -o ServerAliveInterval=10 -o ServerAliveCountMax=6 -o IPQoS=reliability -v -N -D localhost:8080 -p 22 -C sshaccount@sshserver
while {1} {
expect {
eof {break}
"The authenticity of host" {send "yes\r"}
"password:" {send "mypassword\r"}
"*\]" {send "exit\r"}
}
}
wait
close $spawn_id
The parts that you probably will want to adjust are the port ssh runs on the remote server (22 in my example which is also the default), ‘sshaccount’ which is the login for the ssh user on the remove server and ‘sshserver’ which is the host name or IP address of the remote server. If you know that the server IP is static then it is probably smarter to hardcode it since this will allow you to get around DNS problems. 8080 is the port on your laptop the SOCKS proxy will be expecting connections on. mypassword is the remote SSH user’s password.
The other options (-o …) to ssh are used to increase connection reliability (i.e. a dropped physical connection will not lead to dropping the SSH connection easily), you may want to read the man pages (man ssh_config).
Now you need the main network script that calls proxy.expect when you are connected to a specific WLAN (again, edit “nameOfYourWlan” and the local port 8080), i.e proxy.sh:
/home/george/scripts/proxy.sh #!/bin/sh WLAN="nameOfYourWlan" netstatlist=`netstat -an | grep 127.0.0.1:8080 | grep LISTEN` if [ -n "$netstatlist" ] ; then echo proxy already running, quitting exit 1 fi out=`iwconfig wlan0 | grep $WLAN`; if [ -n "$out" ] ; then echo Connected to $WLAN, starting proxy ./proxy.expect else echo Not connected to $WLAN, quitting exit 2 fi
After making the script executable (chmod a+x proxy.sh) you can run it manually. It’s more comfortable to have the system run it whenever the network is available. This is done by adding a script:
/etc/network/if-up.d/autoproxy
#!/bin/sh
if [ "$IFACE" = "wlan0" ]; then
(/home/george/scripts/proxy.sh)&
fi
which you need to make executable (chmod a+x autoproxy) and of course edit "wlan0" and "/home/george/scripts/proxy.sh") to match your setup. Now every time the network is available the script is run.
Last, don’t forget to add localhost:8080 (or whatever your port is) as a system-wide network proxy or configure each application that needs it manually.
Resources
[1] Droid phone PPTP VPN dying after a short while
http://code.google.com/p/android/issues/detail?id=4706
[2] SSHTunnel for Android
https://play.google.com/store/apps/details?id=org.sshtunnel&hl=en