SSH Multihop File Transfer: Direct SCP from Local to Remote via Intermediate Server


3 views

When working with chained SSH servers (A → B → C), the conventional approach involves two separate SCP operations:

# Inefficient way:
scp file.txt userB@serverB:/tmp/
ssh userB@serverB "scp /tmp/file.txt userC@serverC:/destination/"

This method exposes sensitive data on the intermediate server and requires multiple authentication steps.

OpenSSH 7.3+ introduced the -J (ProxyJump) flag for direct multihop transfers:

scp -J userB@serverB file.txt userC@serverC:/destination/

For older versions (7.2 and below), use the ProxyCommand alternative:

scp -o ProxyCommand="ssh -W %h:%p userB@serverB" file.txt userC@serverC:/destination

For frequent transfers, configure your SSH client:


Host serverC
  HostName serverC.example.com
  User userC
  ProxyJump userB@serverB
  # Alternative for older versions:
  # ProxyCommand ssh -W %h:%p userB@serverB

Now you can simply run:

scp file.txt serverC:/destination/

For multiple hops (A → B → C → D):

scp -J userB@serverB,userC@serverC file.txt userD@serverD:/destination/

When dealing with different ports:

scp -J userB@serverB:2222 -P 2222 file.txt userC@serverC:/destination/

1. Always use SSH keys instead of passwords
2. Consider adding ForwardAgent no to your config
3. Use -o StrictHostKeyChecking=yes for production environments

Permission denied: Ensure your public key is in ~/.ssh/authorized_keys on both servers
Host key verification failed: First establish direct SSH connection to cache host keys
Connection timeout: Check if intermediate servers allow TCP forwarding (sshd_config needs AllowTcpForwarding yes)

For more complex scenarios, consider:
- rsync with SSH proxy (works similarly to SCP)
- sshfs for mounting remote filesystems
- Ansible's synchronize module for orchestrated transfers


When working with remote servers in chained SSH environments, copying files directly from your local machine (Machine A) to a target server (Server C) through an intermediary (Server B) presents a common infrastructure challenge. The naive approach involves two separate operations:

# Inefficient two-step transfer
scp file.txt userB@serverB:/tmp/
ssh userB@serverB "scp /tmp/file.txt userC@serverC:/destination/"

OpenSSH provides the ProxyCommand directive that creates a tunnel through intermediary hosts:

scp -o ProxyCommand="ssh -W %h:%p userB@serverB" file.txt userC@serverC:/path/

Breaking this down:

  • -W %h:%p: Forwards the connection to the target host (%h) and port (%p)
  • The command establishes a transparent tunnel through serverB

For repeated use, add this to your ~/.ssh/config:

Host serverC-via-B
    HostName serverC
    User userC
    ProxyCommand ssh -W %h:%p userB@serverB

Now simply use:

scp file.txt serverC-via-B:/destination/

SSH Jump Host Feature

OpenSSH 7.3+ supports a cleaner syntax:

scp -J userB@serverB file.txt userC@serverC:/path/

Or in ~/.ssh/config:

Host serverC
    ProxyJump userB@serverB

Using rsync

For recursive directory transfers:

rsync -avz -e 'ssh -A -J userB@serverB' /local/path/ userC@serverC:/remote/path/

When implementing multi-hop transfers:

  • Use SSH agent forwarding (-A) cautiously
  • Consider using ~/.ssh/authorized_keys command restrictions
  • For sensitive environments, use VPNs instead of multi-hop SSH

Common issues and solutions:

  • Connection refused: Verify intermediate server allows port forwarding
  • Authentication failures: Ensure agent forwarding works (ssh -A)
  • Slow transfers: Try compression (-C) or alternative protocols like SFTP