Multi-Hop SSH: Chaining Connections Through Bastion Hosts
Navigate complex network topologies by chaining SSH connections through multiple bastion hosts. ProxyJump, ProxyCommand, and agent forwarding.
In enterprise networks, internal servers aren't directly accessible from the internet. You must chain SSH connections through bastion hosts (jump servers) to reach them. This guide covers secure multi-hop SSH patterns.
Why Multi-Hop SSH?
Network architecture:
Internet → Bastion Host → Internal Server
Benefits:
- ✅ Single entry point (easier to secure)
- ✅ Audit all access centrally
- ✅ Internal servers not exposed to internet
- ✅ Centralized key management
Method 1: ProxyJump (Recommended)
ProxyJump is the modern, clean way to chain SSH connections.
Basic ProxyJump
# ~/.ssh/config
Host bastion
HostName bastion.example.com
User admin
IdentityFile ~/.ssh/bastion_key
Host internal
HostName internal-server.local
User deploy
ProxyJump bastion
Usage:
ssh internal
# Automatically connects: you → bastion → internal
Multiple Jump Hosts
Host region-bastion
HostName bastion.region.example.com
Host zone-bastion
HostName bastion.zone.example.com
ProxyJump region-bastion
Host server
HostName server.internal
ProxyJump zone-bastion
Connection path: you → region-bastion → zone-bastion → server
ProxyJump with Different Users
Host bastion
HostName bastion.example.com
User admin
Host internal
HostName internal.local
User deploy
ProxyJump admin@bastion.example.com
Method 2: ProxyCommand (Legacy)
ProxyCommand is the older method, still useful for complex scenarios.
Basic ProxyCommand with nc
Host internal
HostName internal.local
User deploy
ProxyCommand ssh bastion nc %h %p 2>/dev/null
ProxyCommand with -W flag
Host internal
HostName internal.local
User deploy
ProxyCommand ssh -W %h:%p bastion
The -W flag is cleaner than nc.
ProxyCommand with Custom Port
Host internal
HostName internal.local
Port 2222
ProxyCommand ssh -W %h:%p bastion
Method 3: Agent Forwarding
Agent forwarding lets you use your local SSH key on intermediate hosts.
Enable Agent Forwarding
# ~/.ssh/config
Host bastion
HostName bastion.example.com
ForwardAgent yes
Host internal
HostName internal.local
ProxyJump bastion
⚠️ Security warning: Only enable ForwardAgent on trusted hosts.
How It Works
Your Mac (SSH key) → Bastion (uses your key) → Internal Server
Your private key never leaves your Mac, but bastion can authenticate to internal servers using it.
Practical Examples
Example 1: AWS VPC Access
# Bastion in public subnet
Host aws-bastion
HostName bastion.ap-southeast-1.compute.amazonaws.com
User ec2-user
IdentityFile ~/.ssh/aws_key.pem
# EC2 instance in private subnet
Host aws-internal
HostName ip-10-0-1-100.ec2.internal
User ec2-user
IdentityFile ~/.ssh/aws_key.pem
ProxyJump aws-bastion
Example 2: Corporate Network
# Corporate bastion
Host corp
HostName bastion.corp.example.com
User $USER
CertificateFile ~/.ssh/corp-cert.pub
# Development server
Host dev
HostName dev.internal.corp.example.com
User developer
ProxyJump corp
# Production server
Host prod
HostName prod.internal.corp.example.com
User deploy
ProxyJump corp
Example 3: Multi-Region Setup
# US bastion
Host us-bastion
HostName bastion.us.example.com
# EU bastion via US
Host eu-bastion
HostName bastion.eu.example.com
ProxyJump us-bastion
# EU server via both bastions
Host eu-server
HostName server.eu.internal
ProxyJump eu-bastion
Port Forwarding Through Bastions
Local Port Forwarding
# Forward internal PostgreSQL to local port
ssh -L 5432:internal-db:5432 bastion
# Or with ProxyJump
ssh -L 5432:localhost:5432 internal
Now connect to localhost:5432 to reach internal database.
Dynamic Port Forwarding (SOCKS)
# Create SOCKS proxy through bastion
ssh -D 1080 bastion
# Configure browser to use SOCKS proxy at localhost:1080
# All traffic routes through bastion
Remote Port Forwarding
# Expose local service to internal network
ssh -R 8080:localhost:3000 internal
Now internal server can access your local port 3000 via its port 8080.
Security Best Practices
1. Restrict Bastion Access
# /etc/ssh/sshd_config on bastion
AllowUsers admin deploy
AllowGroups ssh-users
PasswordAuthentication no
2. Use Certificates
# ~/.ssh/config
Host bastion
CertificateFile ~/.ssh/id_ed25519-cert.pub
IdentityFile ~/.ssh/id_ed25519
3. Limit Agent Forwarding
# Only forward to specific hosts
Host bastion
ForwardAgent yes
Host *
ForwardAgent no
4. Enforce Key-Only Auth
Host bastion
PreferredAuthentications publickey
PasswordAuthentication no
5. Audit Logging
# /etc/ssh/sshd_config on bastion
LogLevel VERBOSE
Troubleshooting
Problem: Connection timeout
# Check bastion connectivity
ssh -v bastion
# Check internal server from bastion
ssh bastion
ssh internal-server
Problem: Permission denied
# Verify key is loaded
ssh-add -l
# Check key permissions
ls -l ~/.ssh/id_*
# Should be 600
Problem: Host key verification failed
# Remove old host key
ssh-keygen -R internal-server
# Reconnect and accept new key
ssh internal
FoxTerm Multi-Hop Support
FoxTerm makes multi-hop SSH visual and simple:
Visual Connection Chains
- See full connection path: you → bastion → server
- Color-coded hop indicators
- Latency per hop
- One-click reconnect
Bastion Management
- Define bastion hosts once
- Auto-apply to internal servers
- Certificate rotation reminders
- Access audit logs
Port Forwarding UI
- Visual port forward setup
- Active forwards dashboard
- Bandwidth monitoring
- Auto-reconnect on disconnect
Conclusion
Multi-hop SSH is essential for secure enterprise network access. ProxyJump provides a clean, declarative way to chain connections through bastion hosts.
FoxTerm makes multi-hop connections visual, with clear path indicators and one-click management.
FoxTerm Pro includes advanced multi-hop SSH management. Download at foxterm.app.