Back to Blog
LinuxJuly 11, 20264 min read

Linux SSH Tunneling: A Practical Guide to Port Forwarding

Master SSH tunneling to securely bypass firewalls. Learn how to use local, remote, and dynamic ssh port forwarding to access internal services like a pro.

linuxsshnetworkingsysadminsecuritytutorialCLI

When you’re working on a remote machine and suddenly need to access a database or a web dashboard running on that server—but it’s blocked by a firewall—you don't necessarily need a full-blown VPN. I’ve spent countless hours dealing with restrictive network rules, and ssh tunneling is almost always the cleanest fix. It leverages the secure connection you already have to bypass those walls.

In this linux ssh guide, I’ll walk you through the three primary modes of port forwarding. Whether you need to expose a local service to the internet or reach a hidden internal resource, these commands are the bread and butter of daily sysadmin work.

Local Port Forwarding

Local port forwarding is the most common use case. It allows you to map a port on your local machine to a port on a remote server (or a host the server can reach).

Suppose you have a database running on localhost:5432 on a remote server, but the server’s firewall only permits SSH traffic. You can tunnel that traffic through your SSH connection:

Bash
ssh -L 9000:localhost:5432 user@remote-server

Now, when you point your local database client to localhost:9000, the traffic is encrypted, sent over the SSH tunnel, and unencrypted on the remote server to talk to the database. It’s exactly how I often debug remote services using tools like VS Code Port Forwarding: Debugging Client-Server Sync in Real-Time.

Remote Port Forwarding

Sometimes, the traffic needs to go the other way. Remote port forwarding lets you take a service running on your local machine and expose it to the remote server. This is a life-saver when you’re showing a local development build to a teammate or a client sitting on a different network.

Bash
ssh -R 8080:localhost:3000 user@remote-server

In this setup, anyone hitting localhost:8080 on the remote server will have their traffic forwarded back to your local machine’s port 3000. Just remember that for this to work, the remote sshd_config must have GatewayPorts enabled if you want users other than the SSH user to access the port.

Dynamic SSH Proxy

If you need to browse the web or access multiple internal services without setting up individual tunnels for each one, a dynamic ssh proxy is the way to go. It turns your SSH connection into a SOCKS proxy.

Bash
ssh -D 8080 user@remote-server

Once this is running, you can configure your browser or system network settings to use localhost:8080 as a SOCKS5 proxy. Every request your browser makes will be routed through the server, making it appear as if you’re browsing from the server's location.

Comparison Table

TypeFlagPrimary Use Case
Local-LAccessing remote internal services locally
Remote-RExposing local services to a remote network
Dynamic-DRouting all traffic through a remote host

A Note on Best Practices

If you find yourself using these commands constantly, don't keep typing them out. Add them to your ~/.ssh/config file to save time. I’ve previously written about Linux Server Security: SSH Keys and Fail2Ban Automation, and using keys instead of passwords is mandatory for these tunnels to stay stable and secure.

If you’re ever struggling with a connection, remember to check your processes with htop or top as mentioned in recent Linux performance monitoring guides to ensure the tunnel process hasn't hung. If you're managing these tunnels at scale, you might even consider wrapping them in a systemd service, which I covered in Mastering Linux Systemd Service Files: A Practical Tutorial.

SSH tunneling is incredibly powerful, but it’s also easy to leave "zombie" tunnels running in the background. Always verify your active connections with ps aux | grep ssh to keep your environment clean. I’m still experimenting with better ways to automate tunnel persistence—let me know if you’ve found a better way than simple autossh wrappers.

FAQ

Q: Why does my tunnel drop after a few minutes of inactivity? A: SSH connections often time out if there's no traffic. Add ServerAliveInterval 60 to your ~/.ssh/config to send a keep-alive packet every minute.

Q: Can I use SSH tunneling to bypass local ISP restrictions? A: Yes, a dynamic proxy (-D) will route your traffic through the remote server, effectively bypassing local network filters.

Q: Do I need root access on the remote server for port forwarding? A: Not usually, unless you are trying to bind to a privileged port (anything under 1024). Standard user accounts work fine for mapping to higher ports.

Similar Posts