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 127.0.0.1:8080. 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 127.0.0.1:p1 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
Server side configuration
GatewayPorts should be “yes” in /etc/ssh/sshd_config on sshd server to enable remote forwarding for machine c0.
Description of GatewayPorts:
Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd binds remote port forwardings to the loopback ddress. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be “no to force remote port forwardings to be available to the local host only, “yes” to force remote port forwardings to bind to the wildcard address, or “clientspecified” to allow the client to select the address to which the forwarding is bound. The default is “no”.
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.