How to Forward SSH Through an SSH Tunnel to Access Internal Servers Directly


2 views

Many developers need to access internal servers (like Server B with IP 192.168.25.100) that are only reachable through a jump host (Server A with public IP 100.100.100.100). While you can chain SSH commands, this approach becomes tedious for frequent access.

The attempted solution ssh -L 22:localhost:22 user@100.100.100.100 doesn't work because:

  1. It forwards your local port 22 to Server A's localhost
  2. But you need to reach Server B's port 22
  3. The forwarding syntax needs adjustment

To access Server B directly from your local machine:

ssh -L 2222:192.168.25.100:22 user@100.100.100.100

Then in another terminal:

ssh -p 2222 user@localhost
  • -L 2222:192.168.25.100:22: Creates a tunnel from your local port 2222 to Server B's port 22
  • The first connection establishes the tunnel through Server A
  • The second connection uses the tunnel to reach Server B

Add this to your ~/.ssh/config for easier access:

Host serverB-via-A
    HostName localhost
    Port 2222
    User remoteuser
    ProxyCommand ssh -W %h:%p user@100.100.100.100

Now simply use:

ssh serverB-via-A

For newer SSH versions (7.3+):

Host serverA
    HostName 100.100.100.100
    User userA

Host serverB
    HostName 192.168.25.100
    User userB
    ProxyJump serverA

Usage remains simple:

ssh serverB

When working with remote infrastructure, we often encounter servers that aren't directly accessible from our local machine. Here's the typical scenario:

Your Local Machine → Server A (public IP: 100.100.100.100) → Server B (private IP: 192.168.25.100)

The correct approach uses local port forwarding through SSH. Here's the proper syntax:

ssh -L [local_port]:[target_host]:[target_port] [jump_host_user]@[jump_host]

For your specific case:

ssh -L 2222:192.168.25.100:22 user@100.100.100.100

Then in another terminal:

ssh -p 2222 user@localhost

Your original command ssh -L 22:localhost:22 had two issues:

  1. Forwarding port 22 requires root privileges (ports below 1024)
  2. You were forwarding to localhost on the jump host instead of Server B

For frequent access, create a more robust setup:

ssh -fN -L 2222:192.168.25.100:22 user@100.100.100.100

Options breakdown:

  • -f: Fork to background
  • -N: Don't execute remote command
  • -L: Local port forwarding

Modern SSH versions (7.3+) support a cleaner method:

ssh -J user@100.100.100.100 user@192.168.25.100

Or configure in ~/.ssh/config:

Host serverB
    HostName 192.168.25.100
    ProxyJump user@100.100.100.100
    User targetuser
  • Verify Gateway: Can you SSH to Server A?
  • Check Internal Access: From Server A, can you ping/SSH Server B?
  • Port Conflicts: Ensure your local port (2222) isn't in use
  • Firewalls: Check both Server A and B's firewall rules

While convenient, port forwarding exposes internal services:

  • Use SSH keys instead of passwords
  • Consider restricting forwarded ports with -L [bind_address]:port:host:hostport
  • For production, implement a VPN or bastion host with stricter controls