SSH tunneling for secure port forwarding
An SSH tunnel carries TCP traffic inside an authenticated, encrypted SSH session. It lets an administrator reach a private database, dashboard or maintenance service without publishing that service directly to the internet.
Local forwarding, remote forwarding and dynamic proxying solve different network paths, but all rely on the same principle: only the SSH endpoint needs to be reachable. A bastion host can therefore front services in a closed network while the administrator works from home or an Australian office.
The examples below suit RHEL, CentOS and Fedora systems, with OpenSSH client options available on macOS and Windows too. They also keep listeners on loopback by default, reducing the chance of accidental exposure.
Map the network path
Start by mapping the path. In a common three-tier layout, a laptop connects to a bastion, and the bastion reaches an application server or database that accepts traffic only from its private subnet. Decide which side owns the listener before choosing local, remote or dynamic forwarding.
Australian networks add useful constraints. Many NBN fixed-line and FTTN connections sit behind carrier-grade NAT, so inbound SSH may fail while an outbound tunnel works; 4G and 5G links can also change IP addresses during a session. In the Australian cloud market, Sydney and Melbourne regions are widely used for such bastions, but the target database should remain private. Linuxtpoint’s broader Linux administration tutorials can support the surrounding setup.
Configure local forwarding
For a local forward, the administrator connects to the bastion and asks it to open a local port that leads to the private target. This example exposes a PostgreSQL service on the administrator’s machine at port 8080:
ssh -N -L 127.0.0.1:8080:10.20.4.15:5432 admin@bastion.example.au
After authentication, requests to 127.0.0.1:8080 travel through the encrypted SSH link to 10.20.4.15:5432. The client listener is loopback-only, so other devices cannot connect to it. ExitOnForwardFailure=yes prevents a misleading command prompt when the requested port is already occupied.
Put recurring settings in ~/.ssh/config rather than relying on a long command:
Host bastion-au
HostName bastion.example.au
User admin
IdentityFile ~/.ssh/id_ed25519_au
IdentitiesOnly yes
ExitOnForwardFailure yes
ServerAliveInterval 30
ServerAliveCountMax 3
Use IdentitiesOnly yes so the server receives only the intended key, and keep the key file readable only by its owner. Confirm the bastion’s host-key fingerprint through a trusted channel before accepting it; avoid StrictHostKeyChecking=no.
Use remote and dynamic forwarding
Remote forwarding runs the listener on the SSH server. It is useful when a service must call another host that only permits connections from the bastion’s network, although it should not become a hidden substitute for a proper application network.
ssh -N -R 127.0.0.1:9000:target.internal:80 admin@bastion.example.au
With GatewayPorts no, the usual SSH server setting, the remote listener remains on the server’s loopback interface. Only local processes on that server can use it; changing this behaviour requires a deliberate security decision.
Dynamic forwarding creates a SOCKS5 proxy for clients that accept proxy settings:
ssh -N -D 127.0.0.1:1080 admin@bastion.example.au
Applications such as a browser can then select the proxy, while unrelated traffic stays outside the tunnel. Dynamic forwarding is flexible but less transparent, so restrict it to administrative use and avoid sending bulk or unrelated traffic through the bastion.
For multi-hop access, a ProxyJump alias can route through the bastion and a second management host without agent forwarding. Agent forwarding lets a compromised remote host use the administrator’s authentication agent, so dedicated keys and explicit jump hosts provide cleaner separation.
Harden keys and server policy
Generate a dedicated Ed25519 key with a passphrase, rather than accepting the server’s default key on every workstation:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_au
The -a 100 option increases key-derivation work, making passphrase guessing more expensive. Keep the private key under ~/.ssh; copy only the .pub file to authorized_keys on the bastion. Set directory permissions to 0700 and private-key permissions to 0600. Separate keys make revocation and audit trails clearer.
On the SSH server, use PermitOpen to limit local-forward destinations and PermitListen, where supported, to constrain remote listeners. Accounts that need no forwarding can receive DisableForwarding yes through a Match block. Keep a second administrative session open while changing daemon settings, then validate sshd -t before reloading.
Security depends on configuration, not chance. The reel-game probability example illustrates the distinction: calculated odds describe an outcome, while SSH relies on verified keys, encryption and access policy. A passphrase still protects the private key if the workstation is stolen.
Maintain a hardened tunnel service
Operational hardening includes patching the bastion and monitoring unusual sessions. For the host patching side, Linuxtpoint’s guide to automatic yum security updates provides a practical companion.
- Bind local and remote listeners to
127.0.0.1unless remote access is explicitly required and firewalled. - Use a separate Ed25519 key for each administrator, protect it with a passphrase and record its owner.
- Restrict forwarding with
PermitOpen,PermitListenand per-account SSH rules on the bastion. - Verify host keys out of band and alert when a known host fingerprint changes unexpectedly.
- Review
sshdlogs, active sessions and listening sockets on a regular schedule. - Remove obsolete accounts, stale keys and unused forwarding permissions during maintenance windows.
Use a systemd unit or managed automation if the tunnel must survive logout, but preserve ExitOnForwardFailure and keepalives. Rotate credentials, test recovery access and document every local, remote or SOCKS proxy.
Diagnose and remember the path
When a forward fails, run ssh -vvv temporarily, inspect the client with ss -lntp, and test the target route from the bastion. On RHEL-family hosts, check SELinux audit messages and firewalld rules as well as cloud security groups. A remote forward can fail because GatewayPorts or PermitListen prevents the requested bind.
Log timestamps in UTC even when teams in Brisbane, Perth, Adelaide, Sydney and Melbourne operate across Australian Eastern, Central and Western time zones. Daylight-saving changes and mobile connections can otherwise make event sequences look inconsistent. Centralised logs and accurate NTP settings support useful incident timelines.
The lasting rule is simple: bind locally, authenticate with strong keys, restrict destinations, and monitor the encrypted path.