Proxy Using SSH Tunnel

We can set up a socks proxy on top of a SSH tunnel. Besides the common proxy functions, such as web browsing, the proxy on top of SSH tunnel also ensures the security between the browser and the proxy server (the SSH server). In this post, we introduce and explain how to set up a proxy over SSH tunnel and the mechanism of it.

A simple example

Let’s start with a simple example. We can access a sshd server sshd_server and we want to use it as a socks5 proxy server. It is simple by using ssh:

$ ssh -D 8080 username@sshd_server

After that, set the browser such as firefox’s proxy option to use socks5 proxy That’s it!

Then, check whether your IP is from the proxy from the websites’ view: Who am I.

Making ssh proxy

We can set up a more complex proxy server through ssh. For example, we have a sshd server s2 and another server s1 as the proxy server. Then we can set up a proxy server system using ssh tunnel. s1 will act as the proxy server, while s2 connects to the service provider (s3). The overall system can be shown as this:

c0:p0 <--> s1:p1 <==> s2:p2 <--> s3

Maybe most of the time c0 and s1 are the same machines as the simple example at the beginning of the post.

Using ssh as a proxy to browse the web is very useful under some situation: Local access restriction such as behind a strict firewall in some country, company or school; You are in a insecure network environment while you want to login to your account.

Now let’s look at how to set up proxy by using ssh tunnel. This uses ssh’s “dynamic” port forwarding function by using parameter “-D”. ssh allocates a socket to listen to port on the local side, optionally bound to the specified ip address. Whenever a connection is made to this port, the connection is forwarded over the ssh channel, and the application protocol is then used to determine where to connect to from the remote machine.

1) Proxy listening to localhost port only

This proxy server can only be used on localhost, which means the other users can not use it. c0 and s1 in the graph above are the same machine.
The command is:

$ ssh -D p1 username@sshd_server

p1 is the port on localhost. Any port larger than 1024 can be chosen as p1. After setting up this proxy tunnel, set the proxy option in browser to and using socks5. Then it is done. Enjoy it now :) .

2) Proxy listening to specific IP

This kind of proxy server can provide service to other users. Users (and include yourself of course) can use this socks5 proxy with address s1_ip and port p1.
The command is:

$ ssh -D s1_ip:p1 username@sshd_server

This command sets up a socks5 proxy server on s1. The proxy address is: s1_ip:p1.

  • Some useful ssh arguments

There are some other ssh arguments that can make the port forwarding more convenient for us:

-C  Requests gzip compression of all data
-T  Disable pseudo-tty allocation
-N  Do not execute a remote command. This is useful for just forwarding ports.
-f  Requests ssh to go to background just before command execution.
-n  Redirects stdin from /dev/null (actually, prevents reading from stdin).
-q  Quiet mode. Causes most warning and diagnostic messages to be suppressed.

These arguments can be used with -D for different usages. I like to use this combination:

$ ssh -CnfND 8080 username@sshd_server

When I want to close the ssh proxy tunnel, I need to find the pid of it by

$ ps aux | grep ssh

and then kill it.

Or let it run in the shell:

$ ssh -CTND 8080 username@sshd_server

You can also configure it to listen on all addresses on the host by:

$ ssh -D "*:8080" username@sshd_server

Port forwarding squid proxy

This post mainly focus on using ssh to build up the proxy system. But the connection between the client and the other kind of proxy server such as squid can also make use of ssh tunnel. I only provides a simple example here, while more details of ssh port forwarding can be found from Port Forwarding using ssh Tunnel. For example, the proxy server and port is proxy:port. Now we can port forwards port 8080 on localhost to it by this:

$ ssh -L 8080:proxy:port username@sshd_server

Global Proxy in GNOME with NetworkManager on Linux

If you are using Linux with NetworkManager, it is very convenient to set up the global proxy of GNOME to use the socks proxy created by SSH.

Creating and Using Socks Proxy on Windows

Check Proxy using SSH Tunnel on Windows.

Using Socks Proxy on iOS

Check How to Configure iOS to Use Socks Proxy over SSH with a Linux/Unix Host.

Eric Z Ma

Eric is a father and systems guy. Eric is interested in building high-performance and scalable distributed systems and related technologies. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.


  1. This solution might be useful to bypass the restrictions on corporate networks. If the port that our SSH uses is locked, we can tell the server to listen on port 443 using the

  2. The “Server side configuration” part is completely misleading. There is no need to specify GatewayPorts in sshd_config on the server side for dynamic and local port forwarding (-D and -L). This could be needed only for remote port forwarding (-R).

    1. Right although that part specified it is for “remote forwarding”. However, “remote forwarding” is not discussed here anymore. Removed that section.

Leave a Reply

Your email address will not be published. Required fields are marked *