A SOCKS5 proxy over SSH to get around censorship
This setup is for when your device can only reach the local network, a machine on that network can reach a filtered internet, and you have a server somewhere outside the filter. One SSH tunnel chains them together, and your device ends up with a normal SOCKS5 proxy.
What you need
- Client: the device you want to browse from. It only reaches the intranet.
- Middle: a Linux machine the client can reach, with internet access that is filtered.
- Server: a machine outside the filter that you can SSH into from the middle machine. A small VPS is enough.
- SSH on the middle machine and the server.
- Dante on the server, only if you use option B.
- Proxifier, or any app that can use a SOCKS5 proxy, on the client.
Tip
Anywhere below you can use a domain name instead of an IP address, and any free port instead of
1080.
Option A: SSH alone
SSH can act as a SOCKS5 proxy by itself. Run this on the middle machine:
ssh -C -N -D 0.0.0.0:1080 user@server.example.com
-D 0.0.0.0:1080opens a SOCKS5 proxy on port 1080 of the middle machine, on all its network interfaces, so the client can reach it.-Ccompresses the traffic, and-Nmeans “no shell, just the tunnel”.- Add
-vwhile you test, to see each connection as it opens.
Every connection the client makes through the proxy now leaves from the server, outside the filter.
Option B: Dante on the server
If you’d rather run a real SOCKS server on the outside machine, for example to share it between several tunnels, install Dante there and keep it on localhost, so only the tunnel can reach it:
sudo apt install dante-server
A minimal /etc/danted.conf:
logoutput: syslog
internal: 127.0.0.1 port = 1080
external: eth0
socksmethod: none
clientmethod: none
user.privileged: root
user.unprivileged: nobody
client pass { from: 127.0.0.0/8 to: 0.0.0.0/0 }
socks pass { from: 127.0.0.0/8 to: 0.0.0.0/0 }
Replace eth0 with the server’s network interface (ip a lists them), then sudo systemctl restart danted.
Now forward a port from the middle machine to Dante:
ssh -N -L 0.0.0.0:1080:127.0.0.1:1080 user@server.example.com
The pattern is -L [listen IP]:[listen port]:[destination IP]:[destination port]. Here the middle machine listens on port 1080 and sends everything to port 1080 on the server’s own localhost, where Dante is waiting.
Point the client at the proxy
On the client, add a proxy in Proxifier:
- Profile → Proxy Servers → Add.
- Address: the middle machine’s intranet IP. Port:
1080. Protocol: SOCKS Version 5. - Click Check to test it, then let Proxifier send all traffic through it.
- Under Profile → Name Resolution, resolve hostnames through the proxy. Otherwise DNS lookups still go through the filtered network.
On a phone, use any app or browser setting that supports SOCKS5 with the same address and port. In Firefox it’s Settings → Network Settings → Manual proxy, with Proxy DNS when using SOCKS v5 ticked.
Keep it running
- Log in with an SSH key instead of a password, so the tunnel can start without you typing anything.
- Add
-o ServerAliveInterval=30 -o ExitOnForwardFailure=yesso a dead connection is noticed quickly. - Wrap the command in
autosshor a systemd service, so it comes back by itself after a drop. - Anyone who can reach the middle machine’s port 1080 can use your proxy. If the intranet isn’t yours, bind to one interface instead of
0.0.0.0, or block the port for everyone but your client with a firewall rule.