SSH Tunnel Command Generator

Pick a direction, drop in your ports and hosts, and copy the ssh tunnel command plus a matching ssh config block.

This SSH tunnel generator settles the question nobody remembers: do you want -L, -R or -D? Pick the direction, drop in your ports and hosts, and you get the one-line ssh command plus a matching ~/.ssh/config block to copy. Local forwarding (-L) pulls a remote or internal service onto a port on your machine. Remote forwarding (-R) pushes one of your local services out to the server side. Dynamic forwarding (-D) spins up a SOCKS5 proxy that routes any traffic through the box. It handles a jump host, an identity file, keepalives and the background flags too, and it explains every piece so the local-versus-remote trap stops biting you. Everything runs in your browser, so the hostnames and key paths you type never leave the page.

100% in your browser. Nothing you type ever leaves this page.

SSH tunnel command generator

Nobody remembers whether they want -L, -R or -D. I have looked it up roughly a hundred times. So: pick the direction, drop in your ports and hosts, and you get the one-line ssh command plus a matching ~/.ssh/config block to copy. Every piece gets explained, because the local-versus-remote thing trips up everyone, and honestly it should. It all runs in your browser.

ssh command
$
~/.ssh/config equivalent

What this SSH tunnel generator does

This SSH tunnel generator builds the exact port-forwarding command you need, then hands you a matching config block so you stop retyping it. SSH is not just a shell. It will also shove network ports through its encrypted pipe, which means you can reach stuff that is private or stuck behind a firewall. There are three forwarding modes: -L, -R and -D. People mix them up constantly. The syntax looks almost identical, but the direction is flipped, and that is exactly where the confusion lives. This generator just asks what you are reaching and from where. Then it gives you the right command, plus a ~/.ssh/config entry so you can stop retyping the thing.

Local, remote and dynamic forwarding

ModeWhat it doesExample
-L LocalPulls a remote service onto a local port. You hit localhost, you land on the server side.ssh -L 8080:localhost:80 user@server
-R RemotePushes a local service out to a remote port, so the server (or whoever is on it) can reach back into your machine.ssh -R 9000:localhost:3000 user@server
-D DynamicSpins up a local SOCKS proxy that shoves any traffic through the SSH server.ssh -D 1080 user@server

Here is the mnemonic that finally stuck for me. -L brings a remote thing to you, you are the one listening. -R sends a local thing out, the remote listens instead. And -D just turns the whole SSH server into a proxy you can point traffic at. The -N flag tells SSH to skip the shell, because you only want the tunnel, not a prompt. -f shoves it into the background.

Reading the -L syntax

Take 8080:localhost:80. It means: listen on local port 8080, then forward to localhost:80 as the SSH server sees it. That last bit is the whole thing, really. The localhost in there is the server's localhost, not yours. This is the part that bites people, me included, the first dozen times. Say you have a database only the server can touch. You would write -L 5432:db.internal:5432, where the server resolves db.internal, and then you point your client at localhost:5432.

Saving tunnels in ssh config

Retyping a long tunnel command is how you end up with a typo at 2am. So the generator also hands you a ~/.ssh/config block, using whichever of LocalForward, RemoteForward or DynamicForward fits. Save it once. After that the tunnel is just ssh mytunnel. The config also tucks away the user, the port, the identity file, the keepalive, all of it in one place, so your commands stay short and everyone on the team is running the same thing.

Privacy and how this tool runs

JavaScript builds the command and the config block right in your browser. The hostnames and key paths you type never leave the page, and nothing gets logged anywhere. Which matters a bit more here than usual, since tunnel configs tend to describe your internal network.

Sources and further reading

Frequently asked questions

What is the difference between ssh -L and -R?

-L (local) listens on your machine and forwards to something the server can reach, so you get at a remote service through localhost. -R (remote) flips it: the server listens, then forwards back to something your machine can reach, so the server side can poke at one of your local services. The bit I actually memorized: -L pulls in, -R pushes out.

How do I create a SOCKS proxy with SSH?

Dynamic forwarding does it: ssh -D 1080 -N user@server. That gives you a SOCKS5 proxy on local port 1080, and everything you send through it tunnels out via the server. Point your browser or app at socks5://localhost:1080. Handy on sketchy coffee-shop wifi.

Why does my -L tunnel connect to the wrong host?

In -L localport:host:hostport, that host gets resolved by the SSH server, not by you. So if you typed localhost, you just asked for the server itself. Want a different internal box? Put the name or IP the server can see, like -L 5432:db.internal:5432. I have lost a couple of hours to exactly this mistake.

What do -N and -f do?

-N says do not run a remote command, which is what you want for a tunnel, so no shell prompt shows up. -f drops SSH into the background once it is authenticated. Stick them together and -fN is the old reliable for a background tunnel.

How do I keep an SSH tunnel from dropping?

Add keepalives: -o ServerAliveInterval=60 makes SSH fire a probe every 60 seconds, so it actually notices when the link goes dead. That stops idle drops. It will not reconnect on its own, though. For that, wrap the tunnel in autossh, or run it as a systemd service with Restart=always.