> ## Content Index
> Fetch the complete content index at: https://snubmonkey.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# SSH Tunneling — Part 3/3: Dynamic Port Forwarding and SOCKS Proxies.
- URL: https://snubmonkey.com/ssh-tunneling-part-3-dynamic-port-forwarding-and-socks-proxies/
- Published: 2026-10-21T21:16:52.000Z
- Updated: 2026-10-22T20:56:07.000Z
- Description: Learn how to route application traffic through an encrypted SSH connection using dynamic port forwarding (-D). Explore SOCKS proxies, browser configuration, command-line tools, DNS handling, troubleshooting, and security best practices.
- Author: SNUBmonkeyteam
- Tags: how to 🪄, ethical hacking 🤖, SSH 🕳, security 🦾🦿

In [Part 1](https://snubmonkey.com/ssh-tunneling-local-port-forwarding/): **Local Port Forwarding**, we used SSH’s `-L` option to send traffic from a local port through the SSH server to a remote service.  
In [Part 2](https://snubmonkey.com/ssh-tunneling-remote-port-forwarding/): **Remote Port Forwarding**, we used SSH’s `-R` option to make a local service accessible through a port on the remote server.

*In this final part, we'll examine* **Dynamic Port Forwarding (`-D`)** *, which turns an SSH connection into a SOCKS proxy.*  

Unlike `-L` and `-R`, which forward traffic to a predefined destination, D**ynamic Forwarding** allows compatible applications to request connections to different destinations through the same SSH tunnel.

This is useful for remote browsing, testing applications from another network perspective, and accessing services reachable from an SSH server.

## 1\. What Is Dynamic Port Forwarding?

Dynamic port forwarding creates a local listening port that acts as a **SOCKS proxy**. Applications configured to use that proxy can send connection requests through SSH to different destinations.

For example:

```
Your Machine
     │
     ▼
127.0.0.1:1080
     │
     │ SOCKS proxy
     ▼
Encrypted SSH Tunnel
     │
     ▼
Remote SSH Server
     │
     ├──► example.com:443
     ├──► internal-server:8080
     └──► another-host:22
```

The destination is selected by the application for each connection rather than being fixed in the SSH command.

**The key difference:** local and remote forwarding define a destination in advance; dynamic forwarding lets the application specify the destination through the SOCKS protocol.  

## 2\. Creating a SOCKS Proxy with SSH

The basic syntax is:

```
$ ssh -N -D [BIND_ADDRESS:]LOCAL_PORT user@REMOTE_SERVER
```

For example:

```
$ ssh -N -D 127.0.0.1:1080 user@server.example.com
```

This creates a SOCKS proxy listening on `127.0.0.1:1080` on your local machine.

### Understanding the options

- `-D`: Enables dynamic port forwarding.
- `127.0.0.1:1080`: Specifies the local listening address and port.
- `-N`: Prevents execution of a remote command or opening of an interactive shell.
- `user@server.example.com`: Specifies the remote SSH server.

Once connected, compatible applications can send their traffic through the proxy.

**Important:** Creating the proxy does not automatically route all your computer's traffic through SSH. You must configure each application to use it, or use another tool that explicitly routes traffic through the SOCKS proxy.  

## 3\. Testing the SOCKS Proxy

After establishing the tunnel, test it with `curl`.

For example:

```
$ curl --proxy socks5h://127.0.0.1:1080 https://example.com
```

The request follows this path:

```
curl
  │
  ▼
127.0.0.1:1080
  │
  ▼
SSH Tunnel
  │
  ▼
Remote SSH Server
  │
  ▼
example.com:443
```

The `socks5h://` scheme tells `curl` to resolve the destination hostname through the proxy rather than resolving it locally first.

This is useful when you want DNS resolution to occur from the remote side, particularly when accessing internal hostnames.

To compare, you can also use:

```
$ curl --proxy socks5://127.0.0.1:1080 https://example.com
```

With `socks5://`, hostname resolution may happen locally, depending on how the application uses the SOCKS proxy. With `socks5h://`, hostname resolution is delegated through the proxy.  

## 4\. Configuring a Browser to Use SSH

One of the most common uses for dynamic port forwarding is routing browser traffic through a remote server.

First, establish the tunnel:

```
$ ssh -N -D 127.0.0.1:1080 user@server.example.com
```

Then configure your browser to use the SOCKS proxy.

For browsers that support manual proxy configuration, enter:

| Setting            | Value                 |
| ------------------ | --------------------- |
| Proxy type         | SOCKS v5              |
| Proxy hostname     | 127.0.0.1             |
| Proxy port         | 1080                  |
| Proxy DNS requests | Enabled, if available |

In Firefox, these settings are available under **Settings → General → Network Settings → Manual proxy configuration**. Select SOCKS v5 and enable DNS proxying where the option is available.

Once configured, compatible browser connections will travel through the SSH tunnel.

```
Browser
   │
   ▼
SOCKS5 Proxy
127.0.0.1:1080
   │
   ▼
SSH Tunnel
   │
   ▼
Remote Server
   │
   ▼
Destination Website
```

Other applications continue to use their normal network connections unless they are separately configured to use the proxy.  

## 5\. Accessing Internal Network Services

Dynamic forwarding becomes particularly useful when the remote SSH server has access to services on a private network.

Suppose your SSH server can reach:

```
10.10.20.50:8080
10.10.20.60:3000
internal.example.local:443
```

You can create a SOCKS proxy:

```
$ ssh -N -D 127.0.0.1:1080 user@bastion.example.com
```

Configure a SOCKS-compatible application to use `127.0.0.1:1080`, then request the required internal destination.

The connection path becomes:

```
Your Machine
     │
     ▼
SOCKS Proxy
     │
     ▼
SSH Tunnel
     │
     ▼
Bastion Host
     │
     ├──► 10.10.20.50:8080
     ├──► 10.10.20.60:3000
     └──► internal.example.local:443
```

The SSH server must be able to resolve and reach the requested destinations, and its forwarding policies must permit the connections.

This technique can provide convenient access to multiple internal services without creating a separate static port forward for each one.  

## 6\. Local Binding and Security

By default, OpenSSH dynamic forwarding generally listens on the local loopback interface.

For example:

```
$ ssh -N -D 127.0.0.1:1080 user@server.example.com
```

The proxy is accessible from your own machine but is not normally exposed to other devices on your network.

You can verify the listening socket on Linux:

```
$ ss -lntp
```

On macOS:

```
$ lsof -nP -iTCP:1080 -sTCP:LISTEN
```

Avoid binding the proxy to `0.0.0.0` unless other devices genuinely need access.

For example:

```
$ ssh -N -D 0.0.0.0:1080 user@server.example.com
```

This requests a listener on all local IPv4 interfaces. Other machines may be able to use the proxy if network and firewall rules permit it.

An exposed SOCKS proxy can allow unauthorized users to route traffic through your SSH connection. Keep the listener restricted to loopback unless broader access is intentional and appropriately controlled.

##   
7\. Running the Proxy in the Background

If you want the proxy to remain active without occupying an interactive terminal, use `-f`:

```
$ ssh -f -N -D 127.0.0.1:1080 user@server.example.com
```

SSH moves into the background after authentication.

To terminate the tunnel, identify the relevant SSH process and stop it, or close the original terminal if you did not start it in the background.

For persistent use, you can manage the connection through a service manager or use a tool such as `autossh` to help restart failed connections.

For example:

```
$ autossh -M 0 -N -D 127.0.0.1:1080 user@server.example.com
```

You can add keepalive options to detect unresponsive connections:

```
$ autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -D 127.0.0.1:1080 user@server.example.com
```

Keepalives help detect failures, while `autossh` provides connection-monitoring and restart behavior.  

## 8\. Troubleshooting Dynamic Port Forwarding

If the proxy does not work, verify the following.

**1\. Confirm that the SSH connection is established**

Run SSH with verbose output:

```
$ ssh -vvv -N -D 127.0.0.1:1080 user@server.example.com
```

Look for authentication failures, forwarding restrictions, and connection errors.

**2\. Check that the local port is listening**

On Linux:

```
$ ss -lntp
```

On macOS:

```
$ lsof -nP -iTCP:1080 -sTCP:LISTEN
```

**3\. Test the proxy with `curl`**

```
$ curl --proxy socks5h://127.0.0.1:1080 https://example.com
```

If this fails, the error may indicate a local connection problem, a SOCKS negotiation failure, a DNS issue, or an unreachable destination.

**4\. Verify destination reachability**.

The remote SSH server must be able to connect to the requested destination. Network restrictions, DNS configuration, firewalls, and SSH server forwarding policies can prevent access.

**5\. Check for port conflicts.**

If another process already occupies port `1080`, choose another local port:

```
$ ssh -N -D 127.0.0.1:1081 user@server.example.com
```

Then update your application's proxy settings to use port `1081`.  

## 9\. Security Considerations

A SOCKS proxy over SSH is useful, but it is important to understand what it protects.

- **SSH encryption:** Protects traffic between your local machine and the SSH server.
- **HTTPS:** Continues to protect application traffic between your browser and the destination website.
- **DNS resolution:** Can be delegated through the proxy when the application supports remote resolution.
- **Remote visibility:** The SSH server can generally observe destination addresses and connection metadata.
- **Unencrypted traffic:** Traffic that is not independently encrypted may be readable beyond the SSH endpoint.
- **Application scope:** Only traffic actually routed through the proxy benefits from the SSH tunnel.

Dynamic forwarding is **not a full VPN**. It does not automatically route every application, UDP traffic, or all system networking through SSH.

Use trusted SSH servers, protect your credentials, restrict proxy access, and verify that the applications you care about are actually using the tunnel.

##   
  
Quick Reference

**Create a local SOCKS proxy**

```
$ ssh -N -D 127.0.0.1:1080 user@server
```

**Test the proxy with remote DNS resolution**

```
$ curl --proxy socks5h://127.0.0.1:1080 https://example.com
```

**Run the proxy in the background**

```
$ ssh -f -N -D 127.0.0.1:1080 user@server
```

**Enable SSH debugging**

```
$ ssh -vvv -N -D 127.0.0.1:1080 user@server
```

**Use a different local port**

```
$ ssh -N -D 127.0.0.1:1081 user@server
```

## The Mental Model

The three SSH forwarding modes serve different purposes:

```
-L  Local listener  → Remote destination
-R  Remote listener → Destination reachable from the SSH client
-D  Local SOCKS proxy → Dynamically selected destinations
```

With dynamic forwarding, the SSH command establishes the proxy, and compatible applications decide which destinations to reach through it.

The essential command is:

```
$ ssh -N -D 127.0.0.1:1080 user@server
```

  
Think of it as:  
**Create a local proxy, send its traffic through SSH, and let the application choose the destination**.
  
  
SSH tunneling offers three flexible ways to connect services across network boundaries:

- **Local forwarding (`-L`)** provides local access to remote services.
- **Remote forwarding (`-R`)** exposes local services through a remote listener.
- **Dynamic forwarding (`-D`)** routes compatible application traffic through a SOCKS proxy.

Together, these techniques provide practical solutions for remote administration, development, testing, and controlled access to private networks.

That wraps up our **three-part SSH tunneling series**, covering local forwarding, remote forwarding, and dynamic forwarding with SOCKS proxies.

We hope this series has helped you understand how to use SSH tunnels securely and effectively.

**Keep learning. Keep exploring. Stay secure.**