Production networks usually hide servers behind a bastion; ProxyJump is the safe, simple way through.
Many networks expose only one hardened bastion (jump host). Internal servers accept SSH only from it.
ssh -J bastion app1 connects to the bastion, asks it to open a TCP connection to app1:22, and runs a second, end-to-end encrypted SSH session to app1 through that connection. Authentication to app1 happens from your machine, with your local keys and agent. The bastion only relays encrypted bytes; it never sees your private key or the inner session's contents.
In ~/.ssh/config:
Host app* db* / ProxyJump bastion makes ssh app1 transparent, and every tool (scp, rsync, Git, IDE remotes) inherits it. Several hops chain with commas: -J hop1,hop2.
Compare with the old approach: log in to the bastion with agent forwarding (ssh -A) and ssh onward from there. That lets anyone with root on the bastion use your agent to authenticate as you to other servers for as long as you are connected. Prefer ProxyJump; if you must forward an agent, do it only to hosts you trust, and consider ssh-add -c so each use requires confirmation.
ProxyJump needs TCP forwarding allowed on the bastion (AllowTcpForwarding); ProxyCommand remains for unusual transports (e.g. a cloud provider's tunnel CLI).
Example
ssh -J alice@bastion.example.com alice@10.0.3.21 # one-off
# ~/.ssh/config
Host bastion
HostName bastion.example.com
User alice
Host app-* db-*
ProxyJump bastion
User alice
Host app-1
HostName 10.0.3.21
# then simply:
# ssh app-1
# rsync -av build/ app-1:/srv/app/Remember
- ssh -J / ProxyJump hops through a bastion end-to-end
- The bastion relays encrypted traffic and never holds your keys
- Prefer ProxyJump over agent forwarding (-A)
Watch out for
- Using ssh -A to every bastion; a compromised bastion can then use your agent.