SSH Jump Host (Bastion) with ProxyJump: The Clean, Modern Way
Prerequisites
- You can SSH to the gatekeeper from your laptop (WAN reachable).
- The gatekeeper can SSH to the workstation (LAN reachable).
- Both servers run sshd (OpenSSH server).
- Your laptop has OpenSSH client (ssh) (macOS/Linux yes by default).
Step 1 — Generate a Key (if you don’t have one)
On your laptop:
ssh-keygen -t ed25519 -C "soulevil@jumphost"
This creates:
- Private key: ~/.ssh/id_ed25519
- Public key: ~/.ssh/id_ed25519.pub
Step 2 — Put Your Public Key on the Gatekeeper
ssh-copy-id -p 422 soulevil@<wanip>
If ssh-copy-id isn’t available, you can do:
cat ~/.ssh/id_ed25519.pub | ssh -p 422 soulevil@<wanip> 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
Test direct access:
ssh -p 422 soulevil@<wanip>
Step 3 — Put Your Public Key on the Workstation (Recommended)
Option A (simple): If you can reach <localip> from your laptop already, run:
ssh-copy-id soulevil@<localip>
Option B (common real-world): You cannot reach <localip> directly from your laptop (that’s the point). In that case, copy the key through the gatekeeper:
cat ~/.ssh/id_ed25519.pub | ssh -p 422 soulevil@<wanip> "ssh soulevil@<localip> 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'"
Step 4 — Create
~/.ssh/config
On your laptop:
nano ~/.ssh/config
Add:
Host gatekeeper
HostName <wanip>
User soulevil
Port 422
IdentityFile ~/.ssh/id_ed25519
Host workstation
HostName <localip>
User soulevil
IdentityFile ~/.ssh/id_ed25519
ProxyJump gatekeeper
Fix permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
Now connect:
ssh workstation
That’s it.
What Each Line Means
Gatekeeper block
- Host gatekeeper: nickname you use in commands (ssh gatekeeper)
- HostName <wanip>: actual IP/DNS
- User soulevil: default username
- Port 422: your custom SSH port
- IdentityFile: which SSH key to use
Workstation block
- HostName <localip>: private IP (only gatekeeper can reach)
- ProxyJump gatekeeper: “to reach workstation, hop via gatekeeper”
Handy Commands You’ll Actually Use
Check the full resolved config
ssh -G workstation | head -n 50
Verbose debug (when it fails)
ssh -vvv workstation
One-off jump without config
ssh -J soulevil@<wanip>:422 soulevil@<localip>
File Copy Through the Jump Host
scp
via ProxyJump (modern)
scp -o ProxyJump=gatekeeper ./file.txt workstation:/tmp/
rsync
via SSH jump
rsync -av -e "ssh -J gatekeeper" ./mydir/ workstation:/var/www/mydir/
Port Forwarding Through the Jump Host
Forward a workstation service to your laptop
Example: workstation has a web app on localhost:8080 (from workstation’s point of view)
ssh -J gatekeeper -L 8080:127.0.0.1:8080 workstation
Then open on your laptop:
- http://127.0.0.1:8080
Forward a database port
ssh -J gatekeeper -L 3306:127.0.0.1:3306 workstation
Now your laptop can connect to MySQL as if it’s local.
Security Hardening Checklist (Strongly Recommended)
On
gatekeeper
- Disable password auth (use keys only)
- Disable root SSH login
- Add fail2ban or rate-limits
- Restrict by firewall (allow SSH only from your IP/VPN if possible)
- Consider 2FA (e.g., PAM Google Authenticator) for the bastion
Typical /etc/ssh/sshd_config ideas:
- PasswordAuthentication no
- PermitRootLogin no
- PubkeyAuthentication yes
Restart SSH after changes (carefully):
sudo systemctl restart ssh
On
workstation
- Keep it LAN-only
- Allow SSH only from gatekeeper’s LAN IP (firewall rule)
- Keys only
Common Problems & Fixes
1) “Permission denied (publickey)”
- Your key isn’t installed on gatekeeper/workstation
- Wrong User
- Wrong IdentityFile
- Bad permissions on remote:
- ~/.ssh should be 700
- authorized_keys should be 600
2) “Connection timed out” to workstation
- Gatekeeper can’t reach <localip>
- Wrong network route/VLAN
- Workstation firewall blocks SSH from gatekeeper
Test from gatekeeper:
ssh soulevil@<localip>
3) Custom port only on gatekeeper
That’s normal. Your workstation can stay on default port 22 on LAN.
Bonus: Multiple Environments Pattern
You can scale this cleanly:
Host gatekeeper-prod
HostName <prod-wan-ip>
User soulevil
Port 422
Host prod-app-1
HostName 10.0.10.11
User soulevil
ProxyJump gatekeeper-prod
Now ssh prod-app-1 just works.
Summary
- ProxyJump is the simplest, cleanest way to do a jump host in OpenSSH.
- You harden one public server (gatekeeper) and keep internal servers private.
- Your daily workflow becomes one command: ssh workstation.
If you want, paste your real topology (gatekeeper LAN IP/subnet + workstation subnet + firewall rules you use), and I’ll give you a “locked down” config example (firewall + sshd_config) that still stays convenient for daily dev work.
If you are interested in network security and system integration, you can also explore our detailed guide on OAuth 1.0 vs OAuth 2.0 Process Flow and Key Differences to secure your application architecture.
