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 tono
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