SSH client is usually used to connect a client to a remote machine securely and for executing commands on a remote computer. But this time, we are going to use the SSH tunnel as a SOCKS5 proxy to our local machine.

Sometimes when we use public wireless hotspots and any other insecure networks, or even if the network has overly restrictive firewall, you cannot browse or access certain websites. More importantly, you also don’t want anyone spying on your activities!

One solution is to use VPN, though using SSH tunnel SOCKS5 proxy can also achieve the same results. SOCKS5 proxy requires you to configure the application you are using such as a web browser to use the proxy server. If all you need to secure is your web browsing, SOCKS5 proxy tunnel is a simple alternative. To make all comparison between VPN and SOCKS5 proxy is a large topic, maybe we can cover this later.

Why use SSH tunneling?

As I said above, it can be used to secure yourself when browsing from potential Man-In-The-Middle attacks, firewalls evasion and securing traffic tunneling. It tunnels all your web traffic through the remote machine.


  1. Remote server. (sign up with my referal link and get 50$ DigitalOcean credit!)
  2. An application that supports SOCKS proxy. In this case we're using FireFox web browser.

Step 1 - Set up the tunnel

Before we go through this, I recommend you to have an SSH key (for password-less authentication and security reasons). I also assume that you already have the SSH key on your local machine. If you don't have one, please create one. It's good practice to give the SSH key a passphrase, but for this tutorial we will leave the passphrase blank for simplification. Please also make sure to add the key to authorised keys in the server.

So, to set up the tunnel, open your terminal and enter this:

ssh -C -f -N -q -D 9999 [email protected]

Explaination of the arguments:

  • -C : Compresses all data (using a standard gzip compression algorithm). Compression is desireable on slow connections, but will only slow down things if you're on fast network.
  • -f: This means to forks the process to background just before the command execution.
  • -N : This tells SSH to not execute remote command once the tunnel is up. This is useful for just forwarding ports.
  • -q : Uses quite mode. Causes most warning and diagnostic messages to be suppressed.
  • -D [bind_address:]port : This tells SSH that we want to connect SSH SOCKS tunnel on specified port and what that does is it creates a local dynamic aplication-level port forwarding, SOCKS5 proxy that we can use to send any of our web traffic that supports a SOCKS5 proxy through. This works by allocating a socket to listen to port on the local side and optionally bound to specified bind_address. The port can be any user/registered ports or dynamic/private ports which range between 1024-65535.

Replace [email protected] with your remote sudo user and server IP address or domain name.

Once you enter the command above, you'll be brought back to the terminal. It’s normal to see no indication of success or failure (because we applied the -q option.)

Step 2: Verify the tunnel

When we’re done setting up the tunnel above, verify that the tunnel is up and running with this command:

ps -ef | grep ssh

You should see a line in the output, something like this:

user  14609     1  0 23:32 ?        00:00:00 ssh -CfNq -D 9999 [email protected]

This means that the SSH process is up and running. (If you don't see it, it means the tunnel did not work - perhaps due to network connection issues, blocked firewall or invalid IP.)

You may close the terminal now. The tunnel will keep running because we specified -f option which forks the process to background.

Step 3: Configuring web browser to use the tunnel

Now that the SSH tunnel is up and running, it's time to configure the web browser (Firefox) to use that tunnel. Remember that when the tunnel was established, you need to configure local applications to use that SOCKS5 proxy.

Some applications such as IRC need you to specify -L port:host:host_port where port is another local port to be use other than -D port, host is your program host IP address (in the IRC case, it is IRC server IP) and host_port is the IRC host port.

There are a few ways to configuring web browser through SOCKS proxy:

  1. Config through the browser itself.
  2. Using Firefox plugin: FoxyProxy
  3. Using Gnome Shell extension: Proxy Switcher

I will choose the easiest way, which is the third option, using Gnome Proxy Switcher. The SOCKS host address is our localhost, and port is what we specify in the -D port. (It is localhost because the SSH Client is in our local machine (of course) and it opens the tunnel from the port that we specified.)

If you prefer the other options, check out below.

To config through the Firefox browser itself:

  1. Goto Preference > Advanced > Network > Connection settings
  2. Check manual proxy configuration > SOCKS Host: Port:port And checks SOCKS v5 > Ok > Done

To config using the FoxyPoxy:

  1. Download Firefox plugin: FoxyProxy and restart browser.
  2. In your Firefox web browser, go to Tools > FoxyProxy > Options (you can also press CTRL-F2)
  3. In Proxy tab, click add new proxy > Checks Manual Proxy Configuration > Enter server host IP address: Port: port > checks SOCKS proxy, SOCKSv5
  4. Go to General tab > Enter Proxy name and Proxy Notes.
  5. Optional: cache and cookies options below and click Ok. Done.

To use Gnome Shell Extension Proxy Switcher:

Back to using the Proxy Switcher to configure the web browser through SOCKS proxy.

  1. Download Gnome Shell extension: Proxy Switcher
  2. Enable it on Gnome Tweak Tool > Extensions > Turn on Proxy Switcher.
  3. Go to Network Settings > Proxy > Manual > Enter SOCKS host: Port: port > Click Ok.
  4. Set up your web browser (and FoxyProxy) to use system proxy settings.
  5. Everytime you need to use the SOCKS5 proxy, just toggle it on Network settings.

This establishes a secure SSH tunnel. So if anybody is sniffing between your PC and your VPS, they will not get anything as SSH traffic is encrypted. Nice!

Step 4: Verify that you're using the proxy (Optional)

Finally, you can browse the Internet securely as all traffic will go through the SOCKS5 proxy that we have just created. You can tell that this is working by checking at Here you can see that your IP address is actually the IP of the server, meaning that the proxy routes all your web traffic through the remote server.

The proxy server is refusing connections

If you try and change to a different SOCKS port, you can see that the browser says that the proxy server is refusing connections. This proves that the Firefox browser uses the proxy, not just the default connection.

Step 5: Closing the tunnel

Closing the tunnel will stop Firefox’s ability to browse over the proxy. If you just close the web browser and the terminal, the proxy tunnel is actually still up and running. Remember that the tunnel we created earlier was sent to the background.

To terminate the tunnel completely, we need to identify the process ID (PID) of the running SSH. Then we can use the kill command.

Search the active SSH process:

ps -ef | grep ssh

You should see a line in the output, something like this:

user  14609     1  0 23:32 ?        00:00:00 ssh -CfNq -D 9999 us[email protected]

As you can see, the number 14609 is the process ID of my SSH process. Let’s kill that process with the command below:

kill 14690

Please note that your process ID might be different, so make sure to amend the SSH process ID above!

And now, your tunnel is terminated.


As you can see, this setup is very easy. As long as you can SSH to your remote server, you can port forward the local port as a SOCKS proxy. Some firewalls may blocks SSH port (which is port 22.) In that case, you need to change the default SSH port to something else such as 80, or 443 because these ports are usually open to allow you access a website.

The SSH tunnel can be combined with other tunnels to improve the ability to penetrate the restrictive firewall - but this is an advanced topic! The basic tunneling that we’ve just discussed is still very useful, especially when you want to experimenting with network tunnel redirection. Any thoughts? Comment below!