ssh -D 1080 starts a SOCKS proxy on port 1080 of your machine and relays every connection through the SSH server, which then reaches the Internet or its internal network. Point your browser at SOCKS5 on 127.0.0.1:1080 and you browse as if you were sitting on the server, with the leg to it encrypted inside SSH.
How ssh -D 1080 works as a SOCKS proxy
OpenSSH's -D [bind_address:]port option sets up dynamic forwarding. The client listens on that local port and speaks SOCKS4 or SOCKS5. When the browser requests a page, the request travels over the SSH connection, usually to TCP port 22, and the server opens the final connection. The destination sees the server's IP, not yours.
The minimal command, with no remote shell:
ssh -D 1080 -N -C [email protected]-D 1080: SOCKS proxy on local port 1080.-N: runs no remote command; it only keeps the forwards alive.-C: compresses traffic, handy on slow links.-f(optional): sends ssh to the background after authentication.
Only the superuser can forward ports below 1024, which is why 1080 is the usual pick. Every flag is described in the official ssh manual page.
Setting up DynamicForward in ~/.ssh/config for the SOCKS proxy
DynamicForward is the config-file equivalent of -D and takes the same [bind_address:]port syntax. It saves you from retyping flags:
Host office-proxy
HostName server.example.com
User user
Port 22
IdentityFile ~/.ssh/id_ed25519
DynamicForward 127.0.0.1:1080
ExitOnForwardFailure yes
ServerAliveInterval 30
Compression yesWith that block, ssh -N office-proxy brings the tunnel up. ExitOnForwardFailure yes makes ssh quit if it cannot bind port 1080, instead of leaving you with a session and no proxy. Check permissions: ~/.ssh at 700 and the private key at 600. If you still rely on RSA, OpenSSH 8.8 disabled ssh-rsa SHA-1 signatures by default; an Ed25519 key, supported since OpenSSH 6.5, sidesteps that.
Browser setup for the ssh -D SOCKS proxy
The browser must use SOCKS5 on 127.0.0.1, port 1080, and resolve hostnames through the proxy. If DNS is resolved locally, the server's internal names fail and your lookups leave through your own network.
- Firefox: Settings → Network Settings → Manual proxy configuration. SOCKS Host 127.0.0.1, port 1080, SOCKS v5, and tick "Proxy DNS when using SOCKS v5".
- Chrome or Chromium: launch it with
--proxy-server=socks5://127.0.0.1:1080, ideally with a separate profile so traffic does not mix. - curl: use
--socks5-hostname, not--socks5, so the server resolves the name.
google-chrome --user-data-dir=/tmp/socks-profile --proxy-server=socks5://127.0.0.1:1080
curl -I --socks5-hostname 127.0.0.1:1080 https://intranet.example.comIf curl returns headers from a host that only exists on the server's network, the tunnel is working.
ssh -D versus Mosh: comparison table for the SOCKS proxy
Mosh does no port forwarding and no X11 forwarding, so it cannot carry a SOCKS proxy. Each tool covers a different job:
| What is compared | ssh -D (SOCKS) | Mosh |
|---|---|---|
| Transport and default port | TCP, port 22 | UDP, ports 60000-61000 |
| Port forwarding or SOCKS proxy | Yes, dynamic forwarding | Not supported |
| How it is established | Direct SSH connection | Starts mosh-server over an initial SSH connection |
| Best use | Browsing or running tools through the server | Interactive shell on changing mobile networks |
In practice you combine them: Mosh for the shell from your phone, and a separate SSH connection with -D or DynamicForward when you need the proxy.
4 mistakes when building a SOCKS proxy with ssh -D
- Expecting Mosh to forward the proxy: it will not; the tunnel has to be plain SSH.
- DNS leaks: without "Proxy DNS" in Firefox, or with
--socks5in curl, names get resolved on your local network. - Forwarding disabled on the server: if
sshd_configsetsAllowTcpForwarding noorDisableForwarding yes, the channel is refused even though login works. - Listening on every interface:
-D 0.0.0.0:1080turns your machine into an open proxy for anyone on your network. Pin it to127.0.0.1unless you have a reason not to.
Managing the SOCKS proxy server from your phone with termi1
The ssh -D tunnel usually runs from a laptop, but the server behind it can be checked from your phone. With the termi1 SSH terminal you open /etc/ssh/sshd_config in your editor of choice using its own keyboard, which includes Esc, Ctrl, Tab and arrow keys, or download it over SFTP without leaving the session.
Before restarting the service, validate the syntax:
sudo sshd -t
grep -Ei 'allowtcpforwarding|disableforwarding' /etc/ssh/sshd_configAsk the AI to "check the sshd configuration" and it types the command at the prompt without pressing Enter. On connections tagged as production, Production Guard holds back anything that stops or changes something, such as an sshd restart, before it reaches the prompt. Keys generated on the phone live in the system's secure storage and the private key never leaves the device. If the server has no public IP, a private mesh network such as Prialo, or Tailscale, reaches it without opening ports. termi1 is on the App Store for iPhone and on Google Play.
Frequently asked questions
What does ssh -D 1080 actually do?
ssh -D 1080 opens a SOCKS4/SOCKS5 proxy on local port 1080 and sends every connection it receives through the SSH server. The server opens the final connection, so the sites you visit see the server's IP address rather than the client machine's.
What is the difference between ssh -D and DynamicForward?
ssh -D and DynamicForward do the same thing: the first is the command-line option and the second is the ~/.ssh/config directive. Both accept the [bind_address:]port syntax, and DynamicForward saves you from repeating the flag every time you connect to that host.
Can I use Mosh to create a SOCKS proxy?
Mosh cannot create a SOCKS proxy because it does no port forwarding and no X11 forwarding. It uses UDP on ports 60000-61000 only for the interactive shell. For the proxy you need a regular SSH connection with -D or DynamicForward in your config file.
How do I prevent DNS leaks with the ssh SOCKS proxy?
DNS leaks with the ssh SOCKS proxy are prevented by resolving names on the server: in Firefox, tick "Proxy DNS when using SOCKS v5"; in curl, use --socks5-hostname; in Chrome, pass --proxy-server=socks5://127.0.0.1:1080 with a separate profile.
Why does the server refuse the ssh -D tunnel?
The server refuses the ssh -D tunnel when sshd_config contains AllowTcpForwarding no or DisableForwarding yes. Login still succeeds, but forwarding channels are denied. Change the directive, validate it with sudo sshd -t and then restart the SSH service.