How to secure public WIFI connections on PC’s, Laptops and Android devices

Wifi connections are convenient and are nearly essential these days for most users. However, securing your connection can be complex and difficult, especially if using a free wifi hotspot at an airport, hotel or cafe.

If you have the option, using a VPN is often a simple, effective way to create a secure connection. However, not everyone has a VPN server available and may want a homegrown/personal solution. Here, secure shell is the best way to go.

This blog post will cover how to secure your wireless connection from prying eyes when using free or paid public wifi when using Linux. Even if the free/public wifi is “secured” with encryption, you don’t want to trust these 3rd parties as you have no control over who else has access to the network or how it’s configured.

Securing your wireless connection could be done in Windows as well, through Putty and I may cover that in another post in the future.

Doing this will require a Intermediate understanding of the bash shell, the dynamics of SSH, public IP’s, port forwarding, as well as the concept of SOCKS Proxies.

It will require that you can reach your home Linux server over SSH from an outside public IP address. If you’re not sure how to do that, you should research that separately. It’s pretty simple in that it requires you to forward a port of your choice to your Linux server, whether on the DMZ or in your LAN, making sure your SSH service will answer to SSH calls on that port number. I would also suggest that you never run SSH on it’s default port (22) on your home Linux box, you’ll want that changed to a non-standard port and forward that port to your Linux box. Use the -p <port number> option in the SSH command to SSH out to your Linux box on the port number of your choice. For example:

 ssh -D 7890 server-ip-address -p 50004

I’ll discuss the -D option later in this post.

Before you try to connect to any public WIFI, you want to make sure your browser is configured to use the SOCKS Proxy protocol that will take advantage of the SSH connection. In FIREFOX, that’s under EDIT/PREFERENCES then ADVANCED, then the NETWORK tab, then click on SETTINGS.

You’ll want to remember the default proxy configuration here so you can change this setting back when you no longer wish to use the SSH encrypted tunnel for web traffic. In this menu, you’ll want to select a MANUAL PROXY CONFIGURATION.

Go down to SOCKS HOST and type in “localhost” (without quotes) and to the right, the port number (e.g. 7890, see the SSH command below). You’ll also want to select SOCKS v5, then click OK, then CLOSE settings.

This is only good for the actual web browsing data, but will not cover your DNS requests. Someone sniffing your packets on that free/public wifi will still be able to see your DNS requests and could return false DNS data to your machine, redirecting you to fake websites causing all sorts of issues (like man-in-the-middle attacks and other problems). The fix here is to make sure Firefox is set up to tunnel all DNS requests through the SOCKS Proxy. To do this, open a tab in your FIREFOX browser and in the address bar type: about:config. This will take you to the core FIREFOX settings.

From there, you’ll want to search for socks. Look for network.proxy.socks_remote_dns and double click that line to make sure the value changes from false to true. If It’s already true, leave it alone and exit the tab. You won’t need to save this change as it’s automatically saved once the setting is changed. You can close this tab after confirming this change.

There is no graphical way to do this in CHROME, so you’ll need to execute CHROME with your SOCKS Proxy settings directly from command line:

google-chrome --proxy-server="socks5://localhost:7890"

… where 7890 is the correct port number used for your dynamic SOCKS Proxy. This single command for CHROME will funnel all your web traffic as well as your DNS requests through the SSH SOCKS Proxy.

Once you’ve confirmed your browser of choice is properly configured, open a command prompt and SSH to your home Linux box.

ssh -D 7890 server-ip-address

… where -D tells SSH that you want to engage dynamic application-level port forwarding using the SOCKS protocol on your local computer’s port number 7890. You can choose any port you like.

As a side note, any application capable of using the SOCKS Proxy protocol can concurrently take advantage of this same connection and offer secure data exchange between your current public/wifi connection and your Linux SSH server.

You’ll want to confirm your browser is streaming it’s web requests through your Linux box as well as your DNS requests. The easy way to check your web traffic is just go to — which will tell you your current public IP address. This should be a familiar IP as it ought to be your home public IP address and not the public IP of your free/public wifi.

To check that your DNS requests are being translated by your Linux box and not by the DNS server of the free/public wifi, you’ll want to type this command in your Linux SSH shell:

sudo tcpdump -i eth0 port 53

All DNS requests occur on port 53. This command will show on-screen any traffic that passes your Linux box on port 53. All you’ll need to do is enter that command, then keep an eye on it while you browse to any webpage (like, you should immediately see traffic showing DNS translation requests for as well as any ads loading from various ad providers.

If you see no traffic on your command prompt after browsing to a web page, your DNS translations are being handled by the free/public wifi and you may be in danger as your website requests may be redirected.

I should add that this method also works very well if you’re stuck behind a firewall that has some sort of access restriction. Even if you’re on a wired connection, you can use the above method to bypass nearly any restriction.

For example, if you’re in a wired or wireless network where you’re trying to access GMail and GMail is blocked for some reason, you can use the above method to securely access the GMail website, tunneling through your encrypted SSH session. The local content filter will not detect your attempt to reach GMail because the web request as well as all DNS requests are transmitted in the encrypted SSH tunnel. All they will see is the encrypted (inaccessible) traffic to your home public IP.

In some cases, your local Internet provider may restrict SSH from a protocol level (regardless of port number) — this is very rare though. Should that be the case, you will not be able to use this method at all to securely tunnel to your home Internet connection.

In other cases, hotels or other entities may require you to sign a EULA agreement before allowing any traffic AT ALL out to the Internet. This means you need to fire up your browser and try to access the internet (without any tunneled encryption or security measures) and their DNS servers will automatically redirect your browser to a custom hotel web page to sign off on the EULA. Once you do, they record your MAC address and then add it to their access control list to allow general access the Internet for the 24 or 48 hours, or whatever period you’ve purchased.

The problem here, is that once you’ve fired up your browser without securing the connection, a man-in-the-middle attack can already take place and grab a hold of your browser and execute some nasty lines of javascript code or other code without your knowledge. In this scenario, you can’t fire up your SSH tunnel without first opening your browser and exposing it to this security risk. One might think they’d be in a catch-22 here, but there’s a simple fix: Live-CD or Live-USB Linux boot!

In this instance, if you cannot make your SSH connection without first signing the hotel’s EULA, you would make sure to bring with you a Live-USB (or Live-CD) version of Linux (like Linux Mint or Fedora or any flavor you prefer). This is a read-only version of Linux that you can use on a public PC (like the crappy hotel PC in the “business lounge” if you want some privacy) or you can use it on your own travel laptop just for scenarios like this. You would boot up your Live-Linux USB and then access their WIFI, open your browser (without any proxy settings), browse to their default home EULA page, sign the EULA and then immediately log off and shut down.

At this point, your wireless MAC address is already cached in their access control list as an authorized device for Internet access. You can then follow the procedure at the top of this blog post to effectively and securely access the internet on a homemade encrypted tunnel.

For Android devices it can be done using a combination of ConnectBot and the FIREFOX mobile browser. I’m not aware of a way to do this with the CHROME browser in android. Though if the hotel or other entity forces that EULA page before Internet access is allowed, you may be out of secure options on a rigid Android device, since there’s no Live-Boot options for an Android device.

Another option is if you have a laptop with you as well as an android tablet or phone, you can configure your laptop to share your wifi connection and you can have your android device tunnel through your laptop’s already-established secure wifi to reach the Internet.

In ConnectBot you’ll want to create a Dynamic SOCKS proxy and choose a local port (like 7890) and configure your Linux Box public IP and port number (or the IP and port number of your laptop with its already-established secure wifi connection that you’ve shared in your hotel room or cafe). If you’re not sure how to use ConnectBot, you should research that separately.

In FIREFOX for Android, you’ll also browse to about:config just like in the full desktop version. Be sure to search for socks and and make sure your network.proxy.socks is set for, your network.proxy.socks_port is set for 7890 (or whatever port number you like) and your network.proxy.socks_remote_dns is true. Also make sure that your network.proxy.socks_version is set for 5.

In addition, you’ll want to search for proxy.type in the about:config settings page and look for network.proxy.type and make sure it’s set for the number 1. This tells FIREFOX to use your manual proxy settings which were all the settings configured in the previous paragraph. Without setting network.proxy.type to 1, it will ignore the settings in the prior paragraph.

The default should be 0, which means no proxy. Your FIREFOX browser for Android may have a different default for network.proxy.type. This link will show you the 5 different proxy settings types (note there is no value 3 in that listing).

Be sure to change this setting back to its default when you no longer wish to have FIREFOX use the SSH encrypted tunnel for web traffic.