Jump Hosts: Multi-Hop SSH

Build a three-VM lab and connect to a target through two SSH jump hosts from your Mac.

Before you run

Use a private test environment. Replace example IP addresses with the actual VM addresses. Verify each SSH host key through Multipass before trusting it. ProxyJump authenticates each hop from your Mac; it does not require a private key on a jump host. The jump hosts must allow TCP forwarding, and each hop must be able to reach the next. Keep a recovery session available before changing firewall rules.

Examples

Install Multipass, create three Ubuntu VMs, and record their actual IP addresses.

brew install --cask multipass
multipass launch --name jump1
multipass launch --name jump2
multipass launch --name target
multipass list

Create a dedicated key on the Mac. Choose a passphrase and do not overwrite an existing key.

ssh-keygen -t ed25519 -f ~/.ssh/securepipes_lab_ed25519

Copy only the public key to each VM. These commands create the temporary file securepipes-lab.pub in each Ubuntu home directory; check that it does not already exist before running them.

for vm in jump1 jump2 target; do
  multipass exec "$vm" -- test ! -e /home/ubuntu/securepipes-lab.pub || break
  multipass transfer ~/.ssh/securepipes_lab_ed25519.pub "${vm}:/home/ubuntu/securepipes-lab.pub" || break
  multipass exec "$vm" -- sh -c 'umask 077; mkdir -p "$HOME/.ssh"; chmod 700 "$HOME/.ssh"; cat "$HOME/securepipes-lab.pub" >> "$HOME/.ssh/authorized_keys" && chmod 600 "$HOME/.ssh/authorized_keys" && rm "$HOME/securepipes-lab.pub"' || break
done

Compare your public key fingerprint with the installed keys. The authorized_keys file may contain other keys too.

ssh-keygen -lf ~/.ssh/securepipes_lab_ed25519.pub
multipass exec jump1 -- ssh-keygen -lf /home/ubuntu/.ssh/authorized_keys
multipass exec jump2 -- ssh-keygen -lf /home/ubuntu/.ssh/authorized_keys
multipass exec target -- ssh-keygen -lf /home/ubuntu/.ssh/authorized_keys

Obtain each server host key fingerprint through Multipass. Compare it with the fingerprint shown by SSH before accepting a new host key.

multipass exec jump1 -- sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
multipass exec jump2 -- sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
multipass exec target -- sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

Add these entries to ~/.ssh/config on your Mac using your actual VM IPs. Preserve existing entries; place these before any matching Host * defaults. Adjust IdentityFile if you chose another key path.

Host jump1
  HostName 192.168.252.2
  User ubuntu
  IdentityFile ~/.ssh/securepipes_lab_ed25519
  IdentitiesOnly yes

Host jump2
  HostName 192.168.252.3
  User ubuntu
  IdentityFile ~/.ssh/securepipes_lab_ed25519
  IdentitiesOnly yes

Host target
  HostName 192.168.252.4
  User ubuntu
  IdentityFile ~/.ssh/securepipes_lab_ed25519
  IdentitiesOnly yes

Test direct access first, then connect through both jump hosts. Accept a host key only after verifying its fingerprint. In Secure Pipes, configure the same two jump hosts in order for the target connection.

ssh jump1
ssh jump2
ssh target
ssh -J jump1,jump2 target

Optional controlled-lab test: only if the target can distinguish the Mac source IP from jump2, and an existing UFW policy permits SSH, allow jump2 before denying the actual Mac source IP. Replace both placeholders. Do not enable or change a production firewall based on this example; keep console access and remove the rules after testing.

# On the target VM, replace the placeholders first:
sudo ufw status numbered
sudo ufw insert 1 allow from <JUMP2_IP> to any port 22 proto tcp
sudo ufw insert 2 deny from <MAC_SOURCE_IP> to any port 22 proto tcp

After the optional firewall rules, direct SSH should fail while ProxyJump succeeds. Remove the two rules using the same actual IP addresses, then verify access again.

ssh target
ssh -J jump1,jump2 target
# On target, remove the lab rules:
sudo ufw delete deny from <MAC_SOURCE_IP> to any port 22 proto tcp
sudo ufw delete allow from <JUMP2_IP> to any port 22 proto tcp

Authoritative references

Reviewed October 27, 2026