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