Create a SOCKS proxy on a Linux server with SSH to bypass content filters

Are you on a network with limited access? Is someone filtering your internet traffic, limiting your abilities? Well, if you have SSH access to any server, you can probably set up your own SOCKS5 proxy and tunnel all your traffic over SSH.

From that point on, what you do on your laptop/computer is sent encrypted to the SOCKS5 proxy (your SSH server) and that server sends the traffic to the outside.

It’s an SSH tunnel on steroids through which you can easily pass HTTP and HTTPs traffic.

And it isn’t even that hard. This guide is for Linux/Mac OSX users that have direct access to a terminal, but the same logic applies to PuTTy on Windows too.

Set up SOCKS5 SSH tunnel#

You set up a SOCKS 5 tunnel in 2 essential steps. The first one is to build an SSH tunnel to a remote server.

Socks5 tunnel explained

Once that’s set up, you can configure your browser to connect to the local TCP port that the SSH client has exposed, which will then transport the data through the remote SSH server.

Socks5 linux proxy

It boils down to a few key actions;

  1. You open an SSH connection to a remote server. As you open that connection, your SSH client will also open a local TCP port, available only to your computer. In this example, I’ll use local TCP port :1337.
  2. You configure your browser (Chrome/Firefox/…) to use that local proxy instead of directly going out on the internet.
  3. The remote SSH server accepts your SSH connection and will act as the outgoing proxy/vpn for that SOCKS5 connection.

To start such a connection, run the following command in your terminal.

$ ssh -D 1337 -q -C -N [email protected]

What that command does is;

  1. -D 1337: open a SOCKS proxy on local port :1337. If that port is taken, try a different port number. If you want to open multiple SOCKS proxies to multiple endpoints, choose a different port for each one.
  2. -C: compress data in the tunnel, save bandwidth
  3. -q: quiet mode, don’t output anything locally
  4. -N: do not execute remote commands, useful for just forwarding ports
  5. [email protected]: the remote SSH server you have access to

Once you run that, ssh will stay in the foreground until you CTRL+C it to cancel it. If you prefer to keep it running in the background, add -f to fork it to a background command:

$ ssh -D 1337 -q -C -N -f [email protected]

Now you have an SSH tunnel between your computer and the remote host, in this example ma.ttias.be.

Use SOCKS proxy in Chrome/Firefox#

Next up: tell your browser to use that proxy. This is something that should be done per application as it isn’t a system-wide proxy.

Chrome doesn’t have its own proxy panel anymore, it hands off to your operating system’s network settings. The simpler route is to skip the OS entirely and launch Chrome with the proxy baked in: chrome --proxy-server="socks5://localhost:1337". That way only that Chrome instance uses the tunnel.

In Firefox, go to Settings → Network Settings → Settings and pick Manual proxy configuration. Set the SOCKS Host to localhost with port 1337, select SOCKS v5, and tick Proxy DNS when using SOCKS v5 so your DNS lookups don’t leak around the tunnel. Change them as such:

Socks5 browser settings

From now on, your browser will connect to localhost:1337, which is picked up by the SSH tunnel to the remote server, which then connects to your HTTP or HTTPs sites.

Encrypted Traffic#

This has some advantages and some caveats. For instance, most of your traffic is now encrypted.

socks5 proxy encryption

What you send between the browser and the local SOCKS proxy is encrypted if you visit an HTTPs site, it’s plain text if you visit an HTTP site.

What your SSH client sends between your computer and the remote server is always encrypted.

What your remote server does to connect to the requested website may be encrypted (if it’s an HTTPS site) or may be plain text, in case of plain HTTP.

Some parts of your SOCKS proxy are encrypted, some others are not.

Bypassing firewall limitations#

If you’re somewhere with limited access, you might not be allowed to open an SSH connection to a remote server. You only need to get an SSH connection going, and you’re good to go.

So as an alternative, run your SSH server port on additional ports, like :80, :443 or :53: web and DNS traffic is usually allowed out of networks. Your best bet is :443, as it’s already an encrypted protocol and less chance of deep packet inspection middleware from blocking your connection because it doesn’t follow the expected protocol.

The chances of :53 working are also rather slim, as most DNS is UDP based and TCP is only used in either zone transfers or rare DNS occasions.

Testing SOCKS5 proxy#

Visit any "what is my IP " website and refresh the page before and after your SOCKS proxy configuration.

If all went well, your IP should change to that of your remote SSH server, as that’s now the outgoing IP for your web browsing.

If your SSH tunnel is down, crashed or wasn’t started yet, your browser will kindly tell you that the SOCKS proxy is not responding.

proxy server refusing connections

If that’s the case, restart the ssh command, try a different port or check your local firewall settings.