Use a Public SSH Server as a SOCKS Proxy on macOS

Use a Public SSH Server as a SOCKS Proxy on macOS

~ 3 min read


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:

  1. socks-up
  2. Use your app/browser with SOCKS5 127.0.0.1:1080
  3. socks-test when needed
  4. socks-down

That gives you a lightweight, secure proxy path without the overhead of running a full VPN stack.

all posts →