SSH tunnels create encrypted connections that can forward traffic between ports, providing secure access to remote services without exposing them to the internet. This is essential for accessing databases, admin panels, and internal services securely.
Local Port Forwarding
Access a remote service through a local port.
# Forward local port 3307 to remote MySQL (port 3306)
ssh -L 3307:localhost:3306 deploy@your-server
# Now connect to MySQL via localhost:3307
mysql -h 127.0.0.1 -P 3307 -u dbuser -p
# Forward to a service on a different host via the SSH server
ssh -L 9200:elasticsearch-server:9200 deploy@jump-host
# Run in background
ssh -fNL 3307:localhost:3306 deploy@your-server
# -f = background, -N = no command, -L = local forwardRemote Port Forwarding
Make a local service accessible on the remote server.
# Expose local port 3000 on the remote server as port 8080
ssh -R 8080:localhost:3000 deploy@your-server
# Now http://your-server:8080 reaches your local port 3000
# Useful for: sharing a local dev server, webhooks testingDynamic Port Forwarding (SOCKS Proxy)
# Create a SOCKS5 proxy through your server
ssh -D 1080 deploy@your-server
# Configure your browser/application to use:
# SOCKS proxy: localhost:1080
# All traffic is routed through your VPS
# Useful for: accessing geo-restricted content, secure browsing on public WiFiSSH Config for Persistent Tunnels
# ~/.ssh/config
Host db-tunnel
HostName your-server-ip
User deploy
LocalForward 3307 localhost:3306
LocalForward 6380 localhost:6379
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
ServerAliveCountMax 3
# Then just run:
ssh db-tunnelJump Hosts (ProxyJump)
# Access a private server through a bastion/jump host
ssh -J bastion@jump-host deploy@private-server
# SSH config equivalent
Host private-server
HostName 10.0.0.5
User deploy
ProxyJump bastion@jump-host-ipKeeping Tunnels Alive
# Use autossh for persistent tunnels
sudo apt install autossh
# Auto-reconnecting tunnel
autossh -M 0 -fNL 3307:localhost:3306 deploy@your-server \
-o "ServerAliveInterval=30" -o "ServerAliveCountMax=3"
# Create a systemd service for permanent tunnels
# /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=SSH Tunnel to Database
After=network.target
[Service]
User=deploy
ExecStart=/usr/bin/autossh -M 0 -NL 3307:localhost:3306 deploy@your-server -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3"
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target