SSH tunnel command generator
Build the right SSH port-forwarding command without second-guessing whether you need -L, -R or -D. Choose the tunnel direction, fill in the ports and hosts, and copy both the one-line ssh command and an equivalent ~/.ssh/config block. Each part is explained so the local-versus-remote confusion finally makes sense. Generated entirely in your browser.
What this SSH tunnel generator does
SSH can do more than open a shell: it can forward network ports through its encrypted connection, letting you reach services that are otherwise blocked, private or behind a firewall. The three forwarding modes, -L, -R and -D, are endlessly confused because their syntax looks similar but their direction is opposite. This generator asks what you are trying to reach and from where, then produces the correct command and a matching ~/.ssh/config entry so you can save the tunnel for reuse.
Local, remote and dynamic forwarding
| Mode | What it does | Example |
|---|---|---|
-L Local | Expose a remote service on a local port. You connect to localhost and reach something on the server side. | ssh -L 8080:localhost:80 user@server |
-R Remote | Expose a local service on a remote port. The server (or its users) can reach something on your machine. | ssh -R 9000:localhost:3000 user@server |
-D Dynamic | Open a local SOCKS proxy that routes any traffic through the SSH server. | ssh -D 1080 user@server |
The reliable way to keep them straight: -L brings a remote thing to you (you listen locally), -R sends a local thing out (the remote listens), and -D turns the SSH server into a general-purpose proxy. The -N flag tells SSH not to run a shell, since you only want the tunnel; -f pushes it to the background.
Reading the -L syntax
The local-forward argument 8080:localhost:80 reads as: listen on local port 8080, and forward connections to localhost:80 as seen from the SSH server. That last detail is the key insight. localhost in the forward spec means localhost on the server, not on your machine. To reach a database that only the server can see, you would write -L 5432:db.internal:5432, where db.internal is resolved by the server. You then connect your client to localhost:5432.
Saving tunnels in ssh config
Typing a long tunnel command every time is error-prone. The generator also outputs a ~/.ssh/config block using the LocalForward, RemoteForward or DynamicForward directives. Save it once and the tunnel becomes ssh mytunnel. Config files also centralise the user, port, identity file and keepalive settings, so your commands stay short and consistent across a team.
Privacy and how this tool runs
The command and config block are built by JavaScript in your browser. No hostnames, ports or key paths are sent anywhere or logged. You can use the generator offline once the page has loaded.
Frequently asked questions
What is the difference between ssh -L and -R?
-L (local) listens on your machine and forwards to a destination reachable from the server, so you reach a remote service via localhost. -R (remote) listens on the server and forwards back to a destination reachable from your machine, so the server side reaches one of your local services. -L pulls in, -R pushes out.
How do I create a SOCKS proxy with SSH?
Use dynamic forwarding: ssh -D 1080 -N user@server. This opens a SOCKS5 proxy on local port 1080 that tunnels all traffic through the server. Point your browser or application at socks5://localhost:1080 to route through it, useful on hostile networks.
Why does my -L tunnel connect to the wrong host?
In -L localport:host:hostport, the host is resolved from the SSH server, not your machine. If you write localhost it means the server itself. To reach another internal box, put its server-visible name or IP there, for example -L 5432:db.internal:5432.
What do -N and -f do?
-N tells SSH not to execute a remote command, which is what you want for a pure tunnel, so you do not get a shell prompt. -f sends SSH to the background after authenticating. Together, -fN is the classic combination for a background tunnel.
How do I keep an SSH tunnel from dropping?
Add keepalives with -o ServerAliveInterval=60 so SSH sends a probe every 60 seconds and notices a dead connection. For automatic reconnection, wrap the tunnel in a tool like autossh, or run it as a systemd service with Restart=always.
How do I tunnel through a bastion or jump host?
Use -J user@bastion (ProxyJump), which connects through the bastion to the final host in one command: ssh -J user@bastion -L 8080:localhost:80 user@target. In ssh config the equivalent directive is ProxyJump user@bastion.
Related tools and resources
More command builders and references from the same toolkit.













