How to Tunnel SSH Through SOCKS Proxy (OpenSSH on macOS) – Complete Guide with Examples


2 views

When working behind restrictive corporate networks or in certain geographic locations, you might find yourself limited to HTTP/SOCKS proxies for external access. This becomes particularly tricky when you need SSH access to remote servers.

Unlike HTTP proxies which only handle web traffic, SOCKS proxies (especially version 5) can tunnel any TCP traffic, making them ideal for SSH connections. Here's how to configure OpenSSH on macOS to leverage this:

The simplest method uses SSH's built-in proxy command support. Edit your ~/.ssh/config:

Host remote-server
    HostName example.com
    Port 2222  # Non-standard SSH port
    ProxyCommand nc -X 5 -x proxy.example.com:1080 %h %p

Different macOS versions ship with different netcat implementations. For BSD netcat (older macOS):

ProxyCommand nc -X connect -x proxy.example.com:1080 %h %p

For GNU netcat (brew-installed):

ProxyCommand nc --proxy-type socks5 --proxy proxy.example.com:1080 %h %p

For environments with multiple proxy options, you can create flexible configurations:

Host *
    ProxyCommand bash -c 'if [[ "%h" == "server1"* ]]; then
        nc -X 5 -x proxy1:1080 %h %p
    else
        nc -X 5 -x fallback-proxy:1080 %h %p
    fi'

If your SOCKS proxy requires authentication, you'll need to modify the approach. Using corkscrew for authenticated HTTP proxies:

Host authenticated-proxy
    ProxyCommand corkscrew proxy.example.com 8080 %h %p ~/.ssh/proxy-auth

For SOCKS5 with auth, consider using connect-proxy:

Host socks5-auth
    ProxyCommand connect -S user:pass@proxy.example.com:1080 %h %p

When things don't work as expected:

  • Verify proxy connectivity first: nc -zv proxy.example.com 1080
  • Check if the proxy allows outbound connections to your SSH port
  • Test with verbose SSH output: ssh -vvv user@host
  • Try different proxy types (SOCKS4 vs SOCKS5)

For frequent usage, establish a master SSH connection through the proxy:

Host persistent-tunnel
    HostName remote.example.com
    ControlMaster auto
    ControlPath ~/.ssh/%r@%h:%p
    ControlPersist 10m
    ProxyCommand nc -X 5 -x proxy.example.com:1080 %h %p

Remember that while SOCKS proxies can tunnel your SSH traffic:

  • The proxy server can see your connection metadata (destination IP/port)
  • SSH encryption still protects your actual session content
  • Consider using VPN alternatives if available

If only HTTP proxies are available, you can still make SSH work:

Host http-proxy-host
    ProxyCommand corkscrew http-proxy.example.com 8080 %h %p

When operating behind restrictive network environments that only permit HTTP or SOCKS proxy access, traditional SSH connections fail because OpenSSH doesn't natively support proxy protocols. This technical deep-dive explores reliable methods to establish SSH tunnels through SOCKS proxies on macOS systems.

First verify your OpenSSH version and proxy availability:


# Check SSH version
ssh -V

# Test SOCKS proxy connectivity
nc -vz -X 5 proxy.example.com 1080

The most reliable approach uses netcat (nc) through your ~/.ssh/config:


Host remote-server
    HostName server.example.com
    Port 2222
    User admin
    ProxyCommand nc -X 5 -x proxy.example.com:1080 %h %p

Key parameters:
-X 5 specifies SOCKS5 protocol
-x defines proxy address:port
%h %p expands to target host and port

For HTTP proxy environments, use the connect utility:


Host remote-server
    ProxyCommand connect -H http_proxy.example.com:8080 %h %p

Timeout errors: Add -o ConnectTimeout=30 to SSH command
Authentication failures: Configure proxy credentials with:


ProxyCommand nc -X 5 -x user:pass@proxy.example.com:1080 %h %p

Create a resilient tunnel that survives network changes:


autossh -M 0 -o "ProxyCommand=nc -X 5 -x proxy.example.com:1080 %h %p" \ 
-N -D 1081 user@server.example.com -p 2222
  • Always verify proxy server certificates with -o StrictHostKeyChecking=yes
  • Consider tunneling through SSH bastion hosts instead of SOCKS when possible
  • For sensitive operations, chain multiple proxies: ssh -J proxy1,proxy2 destination