Start the proxy
ssh -N -D 1080 user@server
-D 1080 opens the proxy, and -N means no remote command. Add -f to run it in the background. Check that it listens only on your own machine:
$ ss -ltn | grep 1080
LISTEN 0 128 127.0.0.1:1080 0.0.0.0:*
LISTEN 0 128 [::1]:1080 [::]:*
On a Mac use lsof -nP -iTCP:1080 -sTCP:LISTEN instead.
-D is the dynamic kind of SSH port forwarding, next to local and remote tunnels.
Test it with curl
curl --socks5-hostname localhost:1080 https://example.com/
Other forms that do the same:
curl -x socks5h://localhost:1080 https://example.com/
ALL_PROXY=socks5h://localhost:1080 curl https://example.com/
To see the address your traffic leaves from, ask a service that shows your IP, with and without the proxy. With the proxy it should be the server's address:
curl https://ifconfig.me
curl --socks5-hostname localhost:1080 https://ifconfig.me
DNS: the difference between socks5 and socks5h
| curl option | Who resolves names |
|---|---|
--socks5, socks5:// | Your machine, using your local DNS |
--socks5-hostname, socks5h:// | The SSH server |
We tested this with a name that existed only on the server. --socks5-hostname and socks5h:// reached the site, while --socks5 failed because the name had to be resolved locally.
This has two consequences. The local network and your DNS provider can see the names you look up unless the server resolves them, which is called a DNS leak. And names that only exist on the server's network work only with the hostname form.
Browser settings
These steps follow each vendor's documentation.
Firefox
Open Settings, then Network Settings, and choose Manual proxy configuration. Set SOCKS Host to localhost, Port to 1080, and choose SOCKS v5. Turn on Proxy DNS when using SOCKS v5, otherwise names are resolved locally.
Chrome and Chromium
Start the browser with a flag:
chrome --proxy-server="socks5://localhost:1080"
On a Mac, quit Chrome first, then start it with the flag from Terminal:
open -a "Google Chrome" --args --proxy-server="socks5://localhost:1080"
Chromium's documentation says some components can still make direct DNS requests, and it adds this flag to prevent it:
--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"
Safari and the whole Mac
Safari uses the system proxy. In System Settings, open Network, choose your network, then Details and Proxies, turn on SOCKS proxy and enter localhost and port 1080. The same from Terminal, and off again when you are done:
networksetup -setsocksfirewallproxy Wi-Fi localhost 1080
networksetup -setsocksfirewallproxystate Wi-Fi off
Replace Wi-Fi with the name of your network service, as listed by networksetup -listallnetworkservices.
Do not expose the port
The proxy has no password. Anyone who can reach it can use your server as an exit. These forms listen on all addresses, as we confirmed with ss:
ssh -N -D 0.0.0.0:1081 user@server
ssh -N -g -D 1080 user@server
Stick with the default, or write it out to be explicit:
ssh -N -D 127.0.0.1:1080 user@server
What it does not do
- It only carries programs that you point at it. It is not a system-wide VPN.
- It carries TCP. OpenSSH's SOCKS support has no UDP relay.
- Traffic is encrypted only between you and the server. From the server to the website, it is whatever the site uses.
- The website sees the server's address, and the server's owner can see the connections.
If it does not work
With AllowTcpForwarding no on the server, the port opens on your side and login succeeds, but each request fails. curl reported connection to proxy closed in our test. Check the server with sudo sshd -T | grep -i allowtcpforwarding. A port already in use gives bind [127.0.0.1]:1080: Address already in use. See that error's guide.
Questions
Is an SSH SOCKS proxy the same as a VPN?
No. Only programs set to use the proxy go through it, and it carries TCP only. A VPN carries all the traffic of the machine.
What is the difference between socks5 and socks5h?
With socks5h, or --socks5-hostname in curl, the SSH server resolves names. With socks5 your machine resolves them, so internal names fail and the lookups can be seen on your local network.
Can I use a port other than 1080?
Yes. Any free local port works, such as ssh -N -D 1081 user@server. Point your programs at the same port.
Sources
- ssh(1), OpenBSD manual
- curl man page
- Configuring a SOCKS proxy server in Chrome
- Connection settings in Firefox