Skip to main contentClaim $5 in free credit — one-time, per account. Claim $5 free
Krova CloudKrova Cloud
Developer Tools & CLI

SSH Local Port Forwarding: Find the Failing Hop

SSH connects but the private service doesn’t respond? Check the local listener, server forwarding policy and destination with two loopback probes.

RB
Rohit Bhadani4 min read
Share
Frosted glass laptop and server linked by a turquoise tunnel with a checkpoint, illustrating SSH local port forwarding.

Suppose your team runs a small admin dashboard on a Cube. The dashboard listens on 127.0.0.1:8080 inside the server, so you reach it through SSH local port forwarding. One morning SSH connects, but your browser can’t open the dashboard. You have a working login. You still don’t know whether the forwarding listener opened, whether the server permitted the forwarding request, or whether the dashboard answered.

Keep the service private while you diagnose it. Check the dashboard from the server first, then make a request through the local listener. Compare the two results and the SSH client’s diagnostics. There’s no need to publish the dashboard port just to find out which step failed.

The two loopback addresses are on different machines

Start with an existing SSH connection you’re authorized to use. The example assumes the SSH server and the dashboard run on the same Linux host, and that the dashboard has a read-only HTTP path at /. On a Cube, use the actual host, port and user from your working SSH command; admin@cube.example is a placeholder. The Krova SSH guide covers initial access.

ssh -N -T -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:18080:127.0.0.1:8080 admin@cube.example

The OpenSSH client manual describes the direction: your SSH client listens on the first address and port, then the remote SSH side connects to the second address and port when a client uses that listener. Here the first 127.0.0.1 is your laptop, and the second is the remote server. The local port can change without changing the destination port. -N requests no remote command; -T disables a terminal. A quiet foreground session is normal.

The explicit local bind keeps that listener off the laptop’s LAN interfaces. Loopback does not make it exclusive to your user on a shared machine. Keep the app’s authentication and use a trusted client. If the real endpoint uses HTTPS, test it with its expected hostname and certificate verification; this HTTP example is only for the private loopback endpoint described above.

Prove the destination can answer before blaming SSH

In a separate, normal SSH session to the server, run the first command below. In a second terminal on the laptop, with the forward still running, run the second. The curl manual documents these options. They bypass client proxy settings for the local probe, bound the wait time and print the HTTP status without dumping the response body.

# Run on the server that terminates SSH:
curl --noproxy '*' --max-time 5 -sS -o /dev/null \
  -w '%{http_code}\n' http://127.0.0.1:8080/

# Run on the laptop with the forward open:
curl --noproxy '*' --max-time 5 -sS -o /dev/null \
  -w '%{http_code}\n' http://127.0.0.1:18080/

If the server-side probe can’t connect, start with the dashboard process, its port and its bind address. A dashboard bound to loopback inside a separate container isn’t automatically reachable on the host’s loopback. Check how that service is meant to be reached from the host where SSH terminates. An HTTP 401 or 403 can be useful evidence that the app answered; it doesn’t grant access. A 000 with a curl error is not an HTTP response.

Read the symptom at the point it appears

  • SSH exits while opening the forward. Check the reported bind error and whether another process already owns laptop port 18080. Choose a different loopback port if it’s in use, then point the browser to the new local port.
  • SSH stays open, the server-side probe works, and the laptop request fails. Restart the diagnostic tunnel with ssh -v and repeat the request while watching that terminal. If the channel is administratively prohibited, ask the operator to check the effective forwarding policy and key restrictions. Don’t broaden permissions to make the test pass.
  • Both probes return HTTP, but the browser still fails. Inspect the expected hostname, redirects, scheme and application login. An HTTP response proves a responder was reached; verify it is the intended dashboard before signing in.

The subtle point is ExitOnForwardFailure. It catches failures to establish the requested forward, such as a local bind failure. It doesn’t test whether a later connection can reach the final destination. The SSH server configuration manual explains controls such as AllowTcpForwarding and PermitOpen; those rules can permit SSH login while restricting which destinations may be opened.

For this hypothetical dashboard, leave the notes with three facts: where the laptop listened, what destination the SSH server attempted, and what the app returned. Close the foreground tunnel with Ctrl+C when you’re done. If you need a shared or permanent access path, plan it separately rather than turning a developer’s temporary tunnel into team infrastructure.

Keep private tools on a self-managed Cube

Run the dashboard or development service on your own Linux instance, and use an authorized SSH path for temporary access. Check the app’s bind, authentication and forwarding policy as separate settings.

Creation context: This AI-assisted guide uses a hypothetical dashboard and commands based on the linked manuals. No remote tunnel or dashboard was tested for this article. The cover is a generated illustration.

For AI agents:llms.txtsitemap

Related posts