How to SSH Tunnel Through Intermediate Server to Access Private IP Service (Port Forwarding Example)


4 views

When working with cloud infrastructure, we often encounter servers in private subnets that are only accessible through bastion hosts. Here's a complete solution for accessing private services through an intermediate server using SSH tunnels, without requiring root privileges.

  • localhost: Your development machine
  • remoteserver: Public-facing jump host (ssh.example.com)
  • private.remoteserver: Internal server (10.0.1.100)

The simplest approach creates a local port that tunnels through remoteserver to private.remoteserver:

ssh -L 8080:private.remoteserver:8080 user@remoteserver -N

Now you can access the service on your local machine:

curl http://localhost:8080/

For hostname-based access that mimics direct connection, modify your SSH config (~/.ssh/config):

Host private.remoteserver
  ProxyCommand ssh -W %h:%p user@remoteserver
  HostName private.remoteserver
  User privateuser

Now you can use standard SSH commands transparently:

ssh private.remoteserver
scp file.txt private.remoteserver:/tmp/

For web service access without modifying /etc/hosts:

ssh -L 8080:private.remoteserver:8080 user@remoteserver -N &
curl -H "Host: private.remoteserver" http://localhost:8080/

For production environments, consider using AutoSSH to maintain stable connections:

autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
  -L 8080:private.remoteserver:8080 user@remoteserver -N
  • Ensure GatewayPorts isn't set to no in remoteserver's sshd_config
  • Verify private.remoteserver's firewall allows connections from remoteserver
  • Check that the SSH user has permissions to forward ports

For accessing multiple services behind the firewall:

ssh -D 1080 user@remoteserver -N

Configure your browser or tools to use SOCKS5 proxy at localhost:1080


Let's visualize this common scenario that many developers encounter when working with cloud infrastructure:

  • localhost: Your development machine
  • gateway.server.com: A bastion host with public IP
  • internal.server: Target machine with private IP (only accessible from gateway)

When you need to access services on internal.server (like a web app on port 8080) but lack root privileges on the gateway, traditional port forwarding solutions might not work. Here's how to solve this with SSH tunneling.

The most reliable method is creating a two-hop tunnel:

ssh -L 8080:internal.server:8080 user@gateway.server.com ssh -L 8080:localhost:8080 user@internal.server

This command does the following:
1. Creates local port 8080 forwarded to gateway.server.com
2. From gateway.server.com, forwards to internal.server:8080
3. All without requiring root access on gateway

For frequent access, add this to your ~/.ssh/config:

Host internal-via-gateway
    HostName gateway.server.com
    User yourusername
    LocalForward 8080 internal.server:8080
    ProxyCommand ssh -W %h:%p gateway.server.com

Now you can simply run:

ssh internal-via-gateway

Once the tunnel is established (either method), test with:

curl http://localhost:8080/

For accessing multiple ports dynamically:

ssh -D 1080 user@gateway.server.com ssh -D 1080 user@internal.server

Then configure your browser/local apps to use localhost:1080 as SOCKS proxy.

  • Ensure GatewayForwarding is enabled on gateway (not root required)
  • Check firewall rules on both servers
  • Verify SSH agent forwarding if using keys
  • Use -v flag for verbose debugging