Knowledge
How to forward ports with SSH tunneling
#CommandLine
Forward ports over SSH with local, remote, and dynamic SOCKS tunnels, including reaching a remote MySQL database safely from your laptop.
Published by Mark van Eijk on June 23, 2026 · 2 minute read
- What SSH tunneling is for
- Local forwarding (-L)
- Remote forwarding (-R)
- Dynamic forwarding (-D)
- The -N and -f flags
What SSH tunneling is for
SSH can do more than give you a shell: it can carry other connections through its encrypted channel. I lean on this constantly to reach services that aren't exposed to the internet, like a database bound to localhost on a remote server. If you're new to the ssh command itself, start with connecting to a server with ssh.
There are three kinds of forwarding worth knowing.
Local forwarding (-L)
Local forwarding makes a remote service appear on a port of your own machine. The syntax is -L local_port:target_host:target_port:
ssh -L 8080:localhost:80 jane@app.example.com
Here localhost:80 is resolved from the server's perspective, so this exposes the server's local web service on http://localhost:8080 on your laptop.
The classic use is a database. Say MySQL on the server listens on 3306 but isn't reachable from outside. Tunnel it:
ssh -L 3306:localhost:3306 jane@app.example.com
Now point your local MySQL client at 127.0.0.1:3306 and you're talking to the remote database over SSH. If 3306 is already busy locally, just pick another local port like -L 13306:localhost:3306.
Remote forwarding (-R)
Remote forwarding is the reverse: it exposes a port on your machine to the server. The syntax is -R remote_port:target_host:target_port. This is handy for letting a remote box reach a service running on your laptop, for example a webhook receiver during development:
ssh -R 9000:localhost:3000 jane@app.example.com
Now connections to port 9000 on the server are forwarded to your local port 3000.
Dynamic forwarding (-D)
Dynamic forwarding turns SSH into a local SOCKS proxy, routing whatever you send through it out via the server. Point a browser or tool at the SOCKS port and your traffic exits from the server:
ssh -D 1080 jane@app.example.com
Configure your application to use 127.0.0.1:1080 as a SOCKS5 proxy. This is great for reaching internal services that are only allowed from the server's network.
The -N and -f flags
When you're tunnelling, you usually don't want an interactive shell as well. Two flags help:
-Ntells SSH not to run a remote command (just forward), so you don't get a shell prompt.-fsends SSH to the background after authenticating.
Combined, they give you a clean background tunnel:
ssh -fN -L 3306:localhost:3306 jane@app.example.com
That command sets up the MySQL tunnel and returns your prompt immediately. To shut it down later, find and kill it:
pkill -f "3306:localhost:3306"
Once you've got the -L, -R, and -D shapes memorised, you can punch a secure path to almost any service without exposing it to the open internet.
Subscribe to our newsletter
Do you want to receive regular updates with fresh and exclusive content to learn more about web development, hosting, security and performance? Subscribe now!
Related articles
Argument list too long (Bash: /bin/rm)
Forward ports over SSH with local, remote, and dynamic SOCKS tunnels, including reaching a remote MySQL database safely from your laptop.
How to install Composer packages locally
Forward ports over SSH with local, remote, and dynamic SOCKS tunnels, including reaching a remote MySQL database safely from your laptop.