Tunnels & Port Forwarding
Local -L, remote -R, accessing private DBs.
Learning objectives
- Create local, remote, and dynamic SSH tunnels
- Access internal services (Proxmox, PostgreSQL) safely through SSH
- Understand security implications of each tunnel type
Port forwarding overview
SSH can carry other TCP traffic inside its encrypted session. Workshop Co. uses tunnels so Marcus administers internal services without publishing them on the internet.
| Type | Flag | Direction | Example use |
|---|---|---|---|
| Local forward | -L | Local port → remote host:port | Browser to Proxmox UI |
| Remote forward | -R | Remote port → local host:port | Expose dev app temporarily |
| Dynamic | -D | SOCKS proxy | Browse through bastion network |
Local forward — Proxmox web UI
# Marcus laptop — forward local 8006 to Proxmox on private LAN
ssh -L 8006:192.168.10.2:8006 marcus@bastion.workshopco.ca
# Browser: https://127.0.0.1:8006
# Traffic path: laptop:8006 → SSH → bastion → 192.168.10.2:8006
Same effect as LocalForward 8006 127.0.0.1:8006 in config when Proxmox listens on localhost only from bastion's perspective — adjust target IP accordingly.
Local forward — PostgreSQL admin
Marcus uses TablePlus from home to inspect booking DB — never expose 5432 on the router:
ssh -L 15432:10.20.0.5:5432 workshop-db
# TablePlus connects to localhost:15432, user deploy, db workshop_bookings
-L 127.0.0.1:15432:... listens only on laptop localhost. Omitting the bind address can expose the tunnel to your LAN — specify 127.0.0.1 for admin tools.
Remote forward — caution
# On Marcus laptop — expose local dev server to bastion's port 8080
ssh -R 8080:127.0.0.1:3000 marcus@bastion.workshopco.ca
Anyone who can reach bastion:8080 hits Marcus's local app. Workshop Co. disables GatewayPorts on bastion and avoids remote forwards unless debugging with time-limited firewall rules.
Dynamic SOCKS proxy
ssh -D 1080 marcus@bastion.workshopco.ca
# Configure browser SOCKS5 → 127.0.0.1:1080
Useful to reach internal-only HTTP sites (staging dashboard) as if Marcus were on the workshop LAN. Do not use as general VPN replacement without understanding DNS leaks.
Worked example — one-shot tunnel without shell
ssh -N -L 15432:10.20.0.5:5432 workshop-db
-N = no remote command, tunnel only. Marcus runs this in a tmux pane while working.
Try it yourself
Write the command to locally forward port 9080 to Nextcloud on VM 130 at 10.20.0.15:80 through the bastion jump config alias workshop-files.
Answer
ssh -N -L 127.0.0.1:9080:10.20.0.15:80 workshop-files
Check your understanding
- Local vs remote forward — which exposes a service from your laptop to the remote network?
- Why bind PostgreSQL tunnel to 127.0.0.1?
Answers
- Remote forward (
-R) — remote listeners reach back to your local machine. - Prevents other devices on your home Wi-Fi from using your DB tunnel without your knowledge.