Skip to main content
  1. Tutorials/

How To Route Web Traffic Securely Without a VPN Using a SOCKS Tunnel

Tutorials Security Ubuntu

The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

Introduction>

Introduction #

At some point, you may find yourself on a network that is insecure or has an overly restrictive firewall and you’ll want to make sure no one is watching your traffic. One solution is to use a VPN, but many VPNs require special client software on your machine, which you may not have rights to install. However, if all you need to secure is your web browsing, there is a fast, free, and useful alternative: a SOCKS 5 proxy tunnel.
A SOCKS proxy is an SSH encrypted tunnel in which configured applications forward their traffic down, and then, on the server-end, the proxy forwards the traffic to the general Internet. Unlike a VPN, a SOCKS proxy has to be configured on an app-by-app basis on the client machine, but you can set up apps without any specialty client software as long as the app is capable of using a SOCKS proxy. On the server-side, all you need to configure is SSH.
In this tutorial you’ll use a server running Ubuntu 20.04 (although any Linux distribution that you can access via SSH will work), and the Firefox web browser as the client application. By the end of this tutorial you will be able to browse websites securely through the encrypted SSH tunnel.

Prerequisites>

Prerequisites #

A Linux server running Ubuntu 20.04 (other distributions will work) with a sudo user and SSH access. To set this up, you can follow our Initial Server Setup Tutorial for Ubuntu 20.04. Go here to build your tunnel on a DigitalOcean Droplet.
An application to configure with the SOCKS proxy, such as the Firefox web browser.
For Windows users, you’ll also need either the PuTTY tool or Windows Subsystem for Linux (WSL)

PuTTY is used to set up the proxy tunnel for Windows users. Users of macOS or Linux have the tools to set up the tunnel pre-installed.

Step 1 (macOS/Linux) — Setting Up the Tunnel>

Step 1 (macOS/Linux) — Setting Up the Tunnel #

On your local computer, create an SSH key if you didn’t create your Droplet with one already in place. Once the key is created, make sure the public side is added to the ‘authorized_keys’ file on your SSH Droplet. Then open a terminal application to create an SSH tunnel with SOCKS proxy enabled.
Set up the tunnel with this command:

ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@your_domain

Explanation of arguments

-i: The path to the SSH key to be used to connect to the host
-D: Tells SSH that we want a SOCKS tunnel on the specified port number (you can choose a number between 1025 and 65536)
-f: Forks the process to the background
-C: Compresses the data before sending it
-q: Uses quiet mode
-N: Tells SSH that no command will be sent once the tunnel is up

Be sure to replace sammy@your_domain with your sudo user and server IP address/domain name.
Once you enter the command, you’ll immediately be brought to the command prompt again with no sign of success or failure; that’s normal.
Verify that the tunnel is running with this command:

ps aux | grep ssh

You will see a line in the output like this:

sammy    14345   0.0  0.0  2462228    452   ??  Ss    6:43AM   0:00.00 ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@your_domain

You can quit your terminal application and the tunnel will stay up. That is because we used the -f argument, which put the SSH session into the background:

Note: to terminate the tunnel you’ll have to grab the PID via ps. In our example, the PID is 14345. We would then use the command kill 14345. We’ll walk through termination in Step 3.

Step 1 (Windows) — Setting Up the Tunnel>

Step 1 (Windows) — Setting Up the Tunnel #

Open PuTTY.
If you haven’t installed it yet, download PuTTY and save it where you like. PuTTY doesn’t require admin rights to install; just download the .exe and run it.
Complete the following steps to set up the tunnel:

From the Session section, add the Host Name (or IP address) of your server, and the SSH Port (typically 22)
On the left, navigate to: Connection > SSH > Tunnels
Enter any Source port number between 1025 and 65536, such as 1337
Select the Dynamic radio button
Click the Add button
Go back to Session on the left
Add a name under Saved Sessions and click the Save button
Now click the Open button to make the connection
Enter your sudo username and server password to log in

You can minimize the PuTTY window now, but don’t close it. Your SSH connection should be open:

Note: You can save your sudo username (sammy) and SSH key for this same session by following the PuTTY SSH Key instructions. Then you won’t have to enter your username and password every time you open the connection.

Step 2 — Configuring Firefox to Use the Tunnel>

Step 2 — Configuring Firefox to Use the Tunnel #

Now that you have an SSH tunnel, it’s time to configure Firefox to use that tunnel. Remember that for a SOCKS 5 tunnel to work, you have to use a local application that can implement the tunnel; Firefox has this capability:

This step is the same for Windows, macOS, and Linux.

Make sure you have the port number that you used in your SSH command; in our examples we’ve used 1337.
(The following steps were performed with Firefox version 80 but should work on other versions, though the locations of the options may be different.)
Open Firefox.

In the upper right hand corner, click on the hamburger icon to access Firefox’s menu.
Click on the Preferences or Options menu item.
Scroll to the bottom and under Network Settings select the Settings… button.
Under the ‘Configure Proxy Access to the Internet’ heading select Manual proxy configuration.
For the SOCKS Host enter localhost or 127.0.0.1 and for the port, use the custom port specified in your tunnel, 1337.
Near the bottom, check the box ‘Proxy DNS when using SOCKS v5’
Click the OK button to save and close your configuration

Now, open another tab in Firefox and start browsing the web. You should be all set for secure browsing through your SSH tunnel. The data that you get back from the website encrypted. Additionally, because you checked the Proxy DNS option, your DNS lookups are also encrypted so your ISP can’t see what you see or where you went to get it.
To verify that you are using the proxy, go back to the Network Settings in Firefox and enter a different port number and save the settings. Now if you try to browse the web, you should get an error message: ‘The proxy server is refusing connections’. This proves that Firefox is using the proxy and not just the default connection. Alternatively, you can go to a public IP site, such as ipecho.net, and the IP it returns should be the IP of your SSH Droplet since it is acting as your proxy now.

Step 3 — Reverting the Proxy in Firefox>

Step 3 — Reverting the Proxy in Firefox #

When you are done needing the privacy of the SSH tunnel, go back to the network proxy settings in Firefox. Click on the radio button for ‘Use system proxy settings’ and click OK. Now that Firefox is no longer using the SOCKS tunnel we can shut that down as well. You can leave the tunnel up so you can enable and disable the proxy in Firefox at will but if you leave the tunnel idle for too long, it may close itself.

Closing the Tunnel (macOS/Linux)>

Closing the Tunnel (macOS/Linux) #

The tunnel we created earlier on our local machine was sent to the background, so closing the terminal window you used to open the tunnel won’t terminate it. To terminate the tunnel we need to identify the Process ID (PID) using the ps command, and then terminate the process using the kill command.
Let’s search for all active ssh processes on our machine:

ps aux |grep ssh

Find the line that looks like the command you entered earlier to create the tunnel. Here’s the sample output:

sammy    14345   0.0  0.0  2462228    452   ??  Ss    6:43AM   0:00.00 ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@your_domain

From the beginning of the line, in one of the first two columns, is a 3-5 digit number. This is the PID. The sample PID of 14345 is highlighted in here.
Now that you know what the PID is, you can use the kill command to bring the tunnel down. Use your PID when you kill the process:

kill 14345

Closing the Tunnel (Windows)>

Closing the Tunnel (Windows) #

Close the PuTTY window you used to create the tunnel. That’s it.

Step 4 (macOS/Linux) — Creating Shortcuts for Repeated Use>

Step 4 (macOS/Linux) — Creating Shortcuts for Repeated Use #

For macOS or Linux systems, we can make an alias or create a script to quickly create the tunnel for us. The following are two ways to automate the tunnel process:

These shortcut methods both require passwordless/passphraseless SSH key authentication to the server.

Clickable BASH Script>

Clickable BASH Script #

If you want an icon that, when clicked, will start the tunnel, we can create a small BASH script to do the job. The script will set up the tunnel and then launch Firefox, although you’ll still need to add the proxy settings manually in Firefox the first time.
On macOS, the Firefox binary that we can launch from the command line is inside Firefox.app. Assuming the app is in the Applications folder, the binary will be found at /Applications/Firefox.app/Contents/MacOS/firefox.
On Linux systems, if you installed Firefox via a repo or if it’s pre-installed, then its location should be /usr/bin/firefox. You can always use the command which firefox to find out where Firefox resides on your system if it’s not in the standard location.
In this script, replace the path to Firefox with the one that is appropriate for your system. You may also need to adjust the SSH line to reflect the successful command you used previously to stand up a tunnel.
Using a text editor like nano create a new file:

nano ~/socks.sh

Add the following lines:
socks.sh

#!/bin/bash -e
ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@`your_domain`
/Applications/Firefox.app/Contents/MacOS/firefox &

Replace 1337 with your desired port number (it should match what you put in Firefox)
Replace sammy@your_domain with your SSH user @ your hostname or IP
Replace /Applications/Firefox.app/Contents/MacOS/firefox with the path to Firefox’s binary for your system

Save your script. For nano, type CONTROL + o, and then to quit, type CONTROL + x.
Make the script executable, so that when you double click on it, it will execute. From the command line, use the chmod command to add execute permissions:

chmod +x /path/to/socks.sh

On macOS, you may have to perform an additional step to tell macOS that a .sh file should be executed like a program and not be opened in an editor. To do this, right click on your socks.sh file and select ‘Get Info’.
Locate the section ‘Open with:’ and if the disclosure triangle isn’t pointing down, click on it so you can see the dropdown menu. Xcode might be set as the default app.
Change it to Terminal.app. If Terminal.app isn’t listed, choose ‘Other’, and then navigate to Applications > Utilities > Terminal.app (you may need to set the pull down menu ‘Enable’ from ‘Recommended Applications’ to ‘All Applications’).
To open your SOCKS proxy now, double click on the socks.sh file. The script will open a terminal window, start the SSH connection, and launch Firefox. Feel free to close the terminal window at this point. As long as you kept the proxy settings in Firefox, you can start browsing over your secure connection:

This script will help you quickly stand up the proxy, but you’ll still have to perform the manual steps listed above to find the ssh process and kill it when you’re done.

Command Line Alias>

Command Line Alias #

If you find yourself on the command line frequently and want to bring up the tunnel, you can create a command line alias to do the job for you.
The hardest part of creating an alias is figuring out where to save the alias command.
Different Linux distributions and macOS releases save aliases in different places. The best bet is to look for one of the following files and search for alias to see where other aliases are currently being saved. Possibilities include:

~/.bashrc
~/.zshrc
~/.bash_aliases
~/.bash_profile
~/.profile

Once you’ve located the correct file, add the alias below to any you already have, or just at the end of the file. In the example below we’re using the alias ‘firesox’ to bring up the SOCKS tunnel, but you can use any word you wish as your alias:
.bashrc

alias firesox='ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@your_domain && /Applications/Firefox.app/Contents/MacOS/firefox &'

Replace 1337 with your desired port number (it should match what you put in Firefox)
Replace sammy@your_domain with your SSH user @ hostname or IP
Replace /Applications/Firefox.app/Contents/MacOS/firefox with the path to Firefox’s binary

Your aliases are only loaded when you start a new shell, so close your terminal session and start a new one. Now when you type:

firesox

This alias sets up your tunnel, then launches Firefox for you and returns you to the command prompt. Make sure Firefox is still set to use the proxy. You can now browse securely.

Step 5 (Optional) — Troubleshooting: Getting Through Firewalls>

Step 5 (Optional) — Troubleshooting: Getting Through Firewalls #

If your connection is working, you are good to go and can stop reading. However, if you’ve discovered that you can’t make an SSH connection out due to a restrictive firewall, then it’s likely that port 22, which is required to create the tunnel, is being blocked. If you can control the proxy server’s SSH settings (with root access to a DigitalOcean Droplet, you will be able to do this), you can set SSH to listen on a port other than 22.
Which port can you use that isn’t being blocked?
Ports that are often open include 80 (general web traffic) and 443 (TLS, secure web traffic).
If your SSH server isn’t serving web content, we can tell SSH to use one of these web ports to communicate over instead of the default port 22. 443 is the best choice since it’s expected to have encrypted traffic on this port, and our SSH traffic will be encrypted.
From a non-firewalled location, SSH in to the DigitalOcean Droplet you are using for the proxy or use the built in console from the Digital Ocean control panel.
Edit the server’s SSH settings:

sudo nano /etc/ssh/sshd_config

Look for the line Port 22.
We can either replace ‘22’ entirely or add a second port for SSH to listen on. We’ll choose to have SSH listen on multiple ports, so we’ll add a new line under Port 22 that reads Port 443. Here is an example:
sshd_config

. . .

Port 22
Port 443

. . .

Restart SSH so it will reload the SSH configuration you just edited. Depending on your distribution, the name of the SSH server daemon may be different, but it’s likely to be ssh or sshd. If one doesn’t work try the other:

sudo service ssh restart

To verify that your new SSH port works, open a new shell (don’t close the current one yet, just in case you accidentally locked yourself out) and SSH in using the new port:

ssh sammy@your_domain -p 443

If you are successful, you can now log out of both shells and open your SSH tunnel using the new port:

ssh -i ~/.ssh/id_rsa -D 1337 -f -C -q -N sammy@your_domain -p 443

The Firefox settings will be the same since it doesn’t depend on the SSH port, just the tunnel port (1337 above).

Conclusion>

Conclusion #

In this modern day and age there are a multitude of ways to browse securely when you’re on a potentially hostile network, like a coffee shop’s public wifi. In most situations, if you’re able the use a VPN to secure and protect all of your traffic then its usage is preferred. But having a SOCKS Tunnel will give you the security you need while web browsing when you can’t use or trust a VPN. A SOCKS tunnel is quick to set up and use in a pinch, and you have total control over it. They are an excellent option for secure browsing.