SSH Tunneling and Port Forwarding
SSH tunneling allows you to route network traffic through an encrypted SSH connection. Useful for accessing databases, admin panels, and services not exposed publicly.
Tunneling Types
| Type | Command | Typical Use |
|---|---|---|
| Local | -L | Access a service on the server from your PC |
| Remote | -R | Expose a local service on the remote server |
| Dynamic | -D | SOCKS proxy to route all traffic |
Local Port Forwarding (`-L`)
Makes a remote server port accessible on your local machine.
ssh -L [local_port]:[destination_host]:[destination_port] user@server
Example: MySQL Locally
The MySQL database is on 127.0.0.1:3306 on the server, not exposed publicly:
ssh -L 3307:127.0.0.1:3306 root@123.45.67.89
Now you can connect to MySQL from your PC on localhost:3307:
mysql -h 127.0.0.1 -P 3307 -u root -p
Example: Access an Admin Panel
# Grafana panel on server port 3000
ssh -L 8080:127.0.0.1:3000 root@123.45.67.89
# Now visit http://localhost:8080 in your browser
Persistent Tunnel in Background
ssh -L 3307:127.0.0.1:3306 -N -f root@123.45.67.89
# -N: don't execute commands (tunnel only)
# -f: go to background
Remote Port Forwarding (`-R`)
Exposes a port from your local machine on the remote server.
ssh -R [remote_port]:[local_host]:[local_port] user@server
Example: Expose a Development Server
Your Node.js server runs on localhost:3000: make it accessible from the VPS:
ssh -R 9000:localhost:3000 root@123.45.67.89
On the server, localhost:9000 now points to your local PC.
To make the port accessible from the internet (not just server's localhost), add GatewayPorts yes to /etc/ssh/sshd_config on the server, then restart SSH.
Dynamic Port Forwarding (`-D`): SOCKS Proxy
Creates a SOCKS5 proxy that routes all traffic through the server.
ssh -D 1080 -N -f root@123.45.67.89
Then configure your browser to use SOCKS5 proxy: 127.0.0.1:1080. All your browser traffic will pass through the VPS.
Persistent Tunnel with autossh
For tunnels that automatically reconnect if disconnected:
apt install autossh -y
# Persistent local MySQL tunnel
autossh -M 0 -N -f \
-o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
-L 3307:127.0.0.1:3306 \
root@123.45.67.89
Systemd Service for Permanent Tunnel
nano /etc/systemd/system/ssh-tunnel-mysql.service
[Unit]
Description=SSH Tunnel MySQL
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/autossh -M 0 -N \
-o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
-o "ExitOnForwardFailure yes" \
-i /root/.ssh/id_ed25519 \
-L 3307:127.0.0.1:3306 root@123.45.67.89
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
systemctl enable --now ssh-tunnel-mysql
`~/.ssh/config` Configuration
Instead of repeating the command every time, save it in your SSH config:
Host my-vps
HostName 123.45.67.89
User root
IdentityFile ~/.ssh/id_ed25519
# Local MySQL tunnel
LocalForward 3307 127.0.0.1:3306
# Local Grafana tunnel
LocalForward 8080 127.0.0.1:3000
Then just ssh my-vps and the tunnels open automatically.
Security
SSH tunnels bypass firewalls. Use them only to securely access services, not to expose insecure services. Always make sure AllowTcpForwarding yes is set consciously in /etc/ssh/sshd_config.
To disable tunneling for untrusted users:
# In /etc/ssh/sshd_config
AllowTcpForwarding no # disable for everyone
# or for specific user in authorized_keys:
no-port-forwarding ssh-ed25519 AAAA... user@pc
Verwandte Artikel
