SSH dynamic port forwarding lets you route selected (or all) network traffic from your local machine through a remote server with one command. On macOS, this is a fast way to test geo-specific behaviour, protect traffic on untrusted networks, or debug “works from server, not from laptop” problems.
If you like it is a cook your own VPN solution using standard tools which have been battle tested over the last 25–30 years.
This post shows a minimal setup using a public server you control (for example, a small VPS), then a clean way to spin the tunnel up and down without remembering long commands, and finally how to forward all traffic using the in built macOS SOCKS proxy.
Why use an SSH tunnel as a SOCKS proxy?
Common cases:
- You need your outbound IP to be the server’s IP for testing
- You are on public Wi-Fi and want traffic from selected apps encrypted to your server first
- You need a temporary proxy and do not want a full VPN setup
- You want a reversible setup you can enable for 10 minutes and then switch off
Important caveat: your traffic is encrypted from your Mac to the SSH server, then exits to the internet from that server. Use a server you trust and keep it patched.
Prerequisites
- macOS with OpenSSH client (already included)
- A reachable Linux server with SSH access (
user@your-server) - SSH key-based login already working
Quick check:
ssh user@your-server 'echo ok'
One-off tunnel (fastest way)
Create a local SOCKS5 proxy on port 1080:
ssh -N -D 127.0.0.1:1080 user@your-server
What those flags do:
-N: no remote command, tunnel only-D: dynamic forward (SOCKS proxy)
Keep that terminal open while you use the proxy. Press Ctrl+C to stop.
Verify it is working
In another terminal:
curl https://ifconfig.me
curl --socks5-hostname 127.0.0.1:1080 https://ifconfig.me
The second command should return the IP address of your SSH server, not your local network.
Make spin up and spin down simple
First create a short directory for SSH control sockets:
mkdir -p ~/.ssh/cm
chmod 700 ~/.ssh/cm
Put this host block in ~/.ssh/config:
Host socks-tunnel
HostName your-server
User your-user
IdentityFile ~/.ssh/id_ed25519
DynamicForward 127.0.0.1:1080
ExitOnForwardFailure yes
ServerAliveInterval 30
ServerAliveCountMax 3
ControlMaster auto
ControlPath ~/.ssh/cm/%C
ControlPersist 10m
Using %C keeps the control socket path short and avoids failures caused by long usernames or hostnames.
Now start in the background:
ssh -fN socks-tunnel
Stop cleanly using the SSH control socket:
ssh -O exit socks-tunnel
Check whether the local SOCKS listener exists:
lsof -nP -iTCP:1080 -sTCP:LISTEN
Optional: toggle macOS system SOCKS proxy
If you want all system traffic for a network service to use this tunnel:
networksetup -listallnetworkservices
networksetup -setsocksfirewallproxy "Wi-Fi" 127.0.0.1 1080
networksetup -setsocksfirewallproxystate "Wi-Fi" on
Turn it off when finished:
networksetup -setsocksfirewallproxystate "Wi-Fi" off
Replace "Wi-Fi" with your actual network service name if different.
Handy shell aliases
Add to ~/.zshrc:
alias socks-up='ssh -fN socks-tunnel'
alias socks-down='ssh -O exit socks-tunnel'
alias socks-test='curl --socks5-hostname 127.0.0.1:1080 https://ifconfig.me'
Reload shell config:
source ~/.zshrc
Now your whole workflow is:
socks-up- Use your app/browser with SOCKS5
127.0.0.1:1080 socks-testwhen neededsocks-down
That gives you a lightweight, secure proxy path without the overhead of running a full VPN stack.