An SSH dynamic SOCKS proxy lets you tunnel any application’s network traffic through an SSH connection, making it appear as if it originated from the remote server.

Let’s see it in action. Imagine you want to access a service only available on your company’s internal network from your home laptop. Your laptop is local-host and the company server is company-server. You can SSH into company-server from local-host.

First, on local-host, you start the SSH tunnel:

ssh -D 8080 -N -C user@company-server

Here’s what’s happening:

  • -D 8080: This is the magic. It tells SSH to bind a SOCKS proxy server to port 8080 on your local machine. Any application configured to use localhost:8080 as a SOCKS proxy will have its traffic sent through this SSH connection.
  • -N: This tells SSH not to execute a remote command. We’re just setting up the tunnel.
  • -C: This enables compression. Useful if your network connection is slow.
  • user@company-server: Your username and the hostname of the remote server you’re tunneling through.

Now, on local-host, you configure your application (e.g., your web browser, curl, etc.) to use localhost as the SOCKS host and 8080 as the port.

For example, to use curl to access an internal service at http://internal-service.company.local:

curl --socks5 localhost:8080 http://internal-service.company.local

When curl makes this request, it doesn’t go directly to internal-service.company.local. Instead, it sends the request over the established SSH connection to company-server. company-server then makes the actual request to internal-service.company.local on your behalf, and the response is sent back through the tunnel to your local-host.

The core problem this solves is network egress control and access to private networks. You can treat company-server as a gateway. All traffic routed through the SOCKS proxy originates from company-server’s IP address, bypassing your home IP’s limitations or firewall rules. This is invaluable for testing how your service appears to external networks, or for securely accessing resources that aren’t directly exposed to the internet.

Internally, SSH acts as a SOCKS server. When your application sends a connection request (e.g., "connect to host X port Y"), SSH intercepts this SOCKS command. It then initiates a new TCP connection from the remote server (company-server) to the target host (internal-service.company.local). The data payload from your application is then forwarded bidirectionally over the SSH tunnel. It’s essentially a transparent proxy for TCP connections, built on top of the SSH protocol’s authenticated and encrypted channel.

The primary levers you control are the local port the SOCKS proxy listens on (-D <port>), the remote server you tunnel through, and the applications you configure to use that proxy. You can also control compression (-C) and whether SSH should try to reconnect if the connection drops (-o ServerAliveInterval=60 -o ServerAliveCountMax=3).

Most people configure their browser and stop there, but SSH dynamic forwarding works at the TCP level. This means it can proxy any application that supports SOCKS proxies, including databases, custom clients, or even other tunneling tools. If an application can be told "use this SOCKS server," it can be routed through your SSH tunnel. It doesn’t matter if the protocol is HTTP, SQL, or something entirely custom; as long as it’s TCP, SSH can tunnel it.

The next step is often understanding how to make this tunnel persistent or how to integrate it into more complex routing scenarios using tools like ProxyCommand.

Want structured learning?

Take the full Ssh course →