SSH tunnels
Before you open a port in the firewall to reach something, consider that SSH can already carry it and you have the credentials.
Local forwarding: bring a remote service to you
ssh -L 5433:localhost:5432 user@server
Now localhost:5433 on your laptop is the PostgreSQL on the server. The
database stays bound to localhost, no firewall rule is needed, and the connection is
encrypted by SSH.
This is the right way to reach a database, a Redis instance or an admin interface for an occasional look. See connecting your own servers for the permanent arrangement.
To reach a third machine the server can see:
ssh -L 8080:10.0.0.9:80 user@server
The second host and port are resolved from the server's point of view, which is the part people get backwards.
Dynamic forwarding: a SOCKS proxy
ssh -D 1080 user@server
Point your browser at SOCKS5 on localhost:1080 and everything goes out
through the server. Convenient for reaching several internal interfaces at once
without a tunnel each.
For regular use, WireGuard is better: faster, survives a dropped connection, and routes whole networks rather than one browser.
Remote forwarding: the one to be careful with
ssh -R 9000:localhost:3000 user@server
Makes a service on your machine reachable from the server. Handy for
showing someone a local development build. By default it binds to the server's
localhost only; GatewayPorts would expose it more widely, and you almost
never want that.
Keeping it up
In ~/.ssh/config:
Host server
ServerAliveInterval 30
ServerAliveCountMax 3
ExitOnForwardFailure yes
That last one matters: without it, a tunnel whose port is already in use fails silently and you spend twenty minutes wondering why you are talking to the wrong thing.
For a tunnel that must stay up, run it under systemd with
Restart=always and -N (no shell) rather than in a
screen session — see
running your application as a service.
Jump hosts
ssh -J bastion user@internal
Connects through a bastion in one command, with no agent forwarding and no key
sitting on the intermediate machine. Prefer this to ssh -A: agent
forwarding lets anyone with root on the intermediate host use your key while you are
connected.
Restrict what a key can do
For an automated tunnel, give it a dedicated key limited in
authorized_keys:
restrict,port-forwarding,permitopen="10.0.0.9:5432" ssh-ed25519 AAAA...
That key can forward to one host and port and do nothing else — no shell, no other destinations. See SSH access and users and sudo.
Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base