You need access to a web interface, a PostgreSQL database, or an administration service that only listens on 127.0.0.1Opening the port in the server’s firewall would be quick, but this service would then become accessible from a network where it has no business being.
A SSH tunnel This carries the connection into your SSH session. For occasional access, I prefer this method: the service remains publicly closed, and only the machine that opens the tunnel can use it. However, you must choose the correct redirection and verify the listening address, especially with -R.

Forward a port to your machine using -L
Local redirection -L opens a port on your machine, then forwards connections to a destination accessible from the SSH server. Its general form is as follows:
ssh -L local_address:local_port:target_host:target_port user@ssh_server
To reach an HTTP interface that listens only on port 80 of the remote server:
ssh -N -T -o ExitOnForwardFailure=yes
-L 127.0.0.1:8080:127.0.0.1:80
[email protected]
-Lcreates the local redirection;127.0.0.1:8080is the open port on your computer;127.0.0.1:80is the destination as seen from the SSH server;-Navoids launching a remote command;-Tavoids allocating a terminal;ExitOnForwardFailure=yesThe session closes if SSH cannot create the requested redirection.
This last option confirms the creation of the listening port. It does not prove that the final service is responding. Always test the destination after opening the tunnel.
As long as the order remains open, you can test the service from your computer:
curl http://127.0.0.1:8080/
The address located to the right of -L deserves your attention. In the previous example, 127.0.0.1 This refers to the SSH server, not your computer. If the target is on another machine on the private network, specify its private address:
ssh -N -T -o ExitOnForwardFailure=yes
-L 127.0.0.1:15432:10.20.0.15:5432
[email protected]
Your PostgreSQL client then connects to 127.0.0.1:15432The bastion opens the actual connection to 10.20.0.15:5432The base does not need to listen on the internet.
Check that the tunnel is actually listening
On your computer, control the local port with ss :
ss -ltnp | grep ':8080'
ss -ltnp | grep ':15432'
You need to see a listening session on 127.0.0.1associated with the process sshIf you see 0.0.0.0 Or The port may be accessible from other interfaces on the machine. Close the tunnel and recreate it, explicitly specifying 127.0.0.1.
The guide to open ports under Linux with ss details the reading of listening addresses. Also verify that the SSH server can reach the final destination:
curl -I http://127.0.0.1:80/
nc -vz 10.20.0.15 5432
If the tunnel is created but that curl or your SQL client receives Connection refusedSSH is probably working. It’s the final destination that isn’t listening on the specified address or port.
Using -R without publishing a service by mistake
Remote redirection -R It does the reverse. It opens a port on the SSH server and forwards it to a service accessible from your machine. Example: making a local application on port 3000 accessible only from the remote server:
ssh -N -T -o ExitOnForwardFailure=yes
-R 127.0.0.1:9000:127.0.0.1:3000
[email protected]
On the remote server, a local process can now call:
curl http://127.0.0.1:9000/
By default, sshd binds this remote port to the loopback interface. Do not replace 127.0.0.1 by 0.0.0.0 Or * without having decided who should be able to join the service. The server parameter GatewayPorts It can allow listening on other interfaces. A simple local demonstration can then become a service exposed to the network.
Also avoid the option -g with a local redirection if you don’t want other machines to connect to the forwarded port. To keep your footprint minimal, bind your tunnels to 127.0.0.1 on both sides.
Control SSH server restrictions
If SSH responds administratively prohibited If the redirection is refused, consult the actual server configuration:
sudo /usr/sbin/sshd -T | grep -E '^(allowtcpforwarding|gatewayports|permitopen|permitlisten)'
AllowTcpForwarding can allow local redirects, remote redirects, both, or neither. PermitOpen And PermitListen These restrictions are used to limit the allowed destinations and ports. On a shared server, these restrictions are preferable to granting global authorization to all accounts.
Before any modification of /etc/ssh/sshd_config or a file under /etc/ssh/sshd_config.d/Keep your current session open and test the syntax:
sudo /usr/sbin/sshd -t
Only restart SSH after a successful return without errors. The complete procedure is explained in the article on restarting the SSH service on UbuntuIf you are still using a password for this account, start by set up an SSH key.
Save a recurring tunnel in ~/.ssh/config
For a database used regularly, avoid copying a long command. Add a dedicated host in ~/.ssh/config :
Host tunnel-db
HostName bastion.example.net
Useradmin
LocalForward 127.0.0.1:15432 10.20.0.15:5432
ExitOnForwardFailure yes
ServerAliveInterval 30
ServerAliveCountMax 3
Protect the file, then open the tunnel to the foreground:
chmod 600 ~/.ssh/config
ssh -N -T tunnel-db
I recommend keeping the first execution in the foreground. You’ll immediately see any key, local port, or redirection errors, and Ctrl + C close the tunnel properly. If you then launch it in the background with -fIdentify the correct process before stopping it:
pgrep -af 'ssh.*15432'
kill PID
Avoid kill -9 By reflex. A normal signal is usually enough to close the session and free up the port.
Diagnosing a tunnel that doesn’t pass
- Address already in use Another process is using the local port. Check it with
ss -ltnpor choose another port. - Connection refused : the target service is not listening, or the destination address is incorrect from the perspective of the SSH server.
- Administratively prohibited : The SSH configuration blocks redirection or limits the requested destination.
- Timeout : The SSH server is unable to reach the target due to routing or an intermediate firewall.
- Falling tunnel : check the stability of the connection and use
ServerAliveIntervalrather than a loop that restarts SSH without any diagnosis.
To get details of the negotiation and redirections, temporarily add -v :
ssh -v -N -T -L 127.0.0.1:8080:127.0.0.1:80 [email protected]
An SSH tunnel protects the transport, but it doesn’t correct the access rights of the target service. Keep listening on the local loopback, use a limited SSH account, control authorized keys, and close the session as soon as access is no longer needed.
The syntaxes of -L, -R, -N And -g are detailed in the Official OpenSSH client documentationThe controls AllowTcpForwarding, GatewayPorts, PermitOpen And PermitListen are described in sshd_config(5).