193

I have two remote hosts.
host1-> 10.3.0.1
host2-> 10.3.0.2
Both run an ssh server.

The ssh server listens on port 22 in host1 and on port 6969 in host2. Now, using my local machine, I need to copy something from host1 to host2 without logging into either host1 or host2 via ssh. Something like,

scp user@10.3.0.1:/path/to/file user@10.3.0.2/path/to/file

How can I do this, please note that the two hosts use different ports for ssh.

2
  • Are you asking if you can transfer from a remote host to a remote host, or are you asking how to do it without having to supply a password? Dec 10, 2013 at 14:22
  • While the -P flag exists to specify the port to use, in case of remote-to-remote transfer, ssh as no defined behaviour on how to specify per-host port...
    – mveroone
    Dec 10, 2013 at 15:14

6 Answers 6

301

In the past, the way in which scp worked, when called (naively) to copy files between remote systems, was very inconvenient: if you wrote, for instance

    scp user1@remote1:/home/user1/file1.txt user2@remote2:/home/user2/file1.txt

scp would first open an ssh session on remote1, and then it would run scp from there to remote2. For this to work, you would have to set up the authorization credentials for remote2 on remote1.

The modern way to do it, instead, ("modern" because it was implemented only a few years ago, and perhaps not everybody has a -3-capable scp) requires two steps.  The first necessary step is to use ~/.ssh/config to set up all options for the connection to both remote1 and remote2, as follows:

    Host remote1.example.org
    Port 2222
    IdentityFile /path/to/host1-id_rsa

    Host remote2.example.org
    Port 6969
    IdentityFile /path/to/host2-id_rsa

This way it becomes possible to pass all necessary options to the command without ambiguities: for instance, if we had said on the CLI use port 2222 without the above configuration, it would have been unclear whether we were referring to remote1 or to remote2, and likewise for the file containing the cryptgraphic keys. This way the CLI remains tidy and simple.

Secondly, use the -3 option, as follows:

    scp -3 user1@remote1:/home/user1/file1.txt user2@remote2:/home/user2/file1.txt

The -3 option instructs scp to route traffic through the PC on which the command is issued, even though it is a 3rd party to the transfer. This way, authorization credentials must reside only on the issuing PC, the third party.

6
  • 17
    For future reference: If you copy a file between two hosts that share an identity file (like an EC2 instance), then you don't need the config file. One -i argument is sufficient to connect to both hosts. Aug 8, 2014 at 8:13
  • 1
    Also worth noting, for Google Compute Engine, there is support for adding to your ~/.ssh/config file: cloud.google.com/compute/docs/gcloud-compute but I don't think that AWS has the same support
    – modulitos
    Dec 28, 2014 at 8:36
  • 2
    Since you won't see the output as you normally do, a tip is to enable the verbose mode with -v.
    – holmberd
    May 23, 2019 at 21:49
  • This post clearly says: "routing the traffic through the third PC", but I, at least, didn't parse it to mean: "This will be extremely slow". If that's what you need you'll have to set up remote1 with the relevant credentials. It's a one-off thing though, then it'll work.
    – Fons MA
    Jul 29, 2020 at 8:04
  • 1
    @FonsMA quite often, it's better to be slower than to give credentials to servers that shouldn't have them.
    – Shautieh
    Jul 26, 2021 at 14:47
34

The source and target can be specified as a URI in the form scp://[user@]host[:port][/path]

so you can run:

scp -3 scp://user@10.3.0.1:22/path/to/file scp://user@10.3.0.2:6969/path/to/file
3
  • 4
    This is THE answer. Please note that the path starts after the first /, so if you want an absolute path you'll put // after the port (eg. scp://user@10.3.0.1:22//etc/*), or it would be interpreted as local to user's home. You can use -v to see what files are being transferred, very useful when using wildcards.
    – Vanni
    Jun 4, 2020 at 13:17
  • 1
    @Vanni, words do not describe how much your simple comment o if you want an absolute path you'll put // after the port (eg. scp://user@10.3.0.1:22//etc/*), or it would be interpreted as local to user's home just helped....I've wasted nearly a complete day pulling my hair out because of precisely that. I must have read the rest of the internet about SCP before finding this...Thanks!!
    – Chris
    May 16, 2021 at 10:18
  • @Chris I'm glad it helped! :)
    – Vanni
    May 16, 2021 at 15:32
8

Last time I tried this, scp wasn't able to do that. Your command line looks okay. This workaround will work:

ssh -p port_on_machine1 user@machine1 "cat /path/to/file/one"|ssh -p port_on_machine2 user@machine2 "cat >/path/to/file/two"
2
  • my scp man page says "Copies between two remote hosts are also permitted." Dec 10, 2013 at 14:23
  • 2
    Thanks, it is good to hear. To scp you can give a -P flag (it was written by some BSD people, this because its argument handling is so tragic :-( ), but it seems you can't specify different ports on the remote hosts. I am sorry, but I think, only this workaround lefts (or there are a lot of trickier solutions, using ssh but avoiding scp - for example, sftpfs, but they are not the simplest). I extended my workaround with the port settings.
    – peterh
    Dec 10, 2013 at 15:11
5

In my case, I was doing a remote to remote copy, withouth the -3 argument. The port given with the '-P' parameter works with the 1st server, but port 22 is used with the 2nd one.

ssh -P 1234 user@server1.mydomain.com user@server2.otherdomain.com

The solution is to edit the /etc/ssh/ssh_config file in server1 and add these lines:

Host *.otherdomain.com
   Port  1234

In this way, the port 1234 is used for both of them. It could be different too.

This solution has better throughput than previous solutions, because communitation is direct.

1
  • 1
    perez is there a way to achieve scp through two different ports for the two different remote machines from the comman line?
    – Red Bottle
    Aug 30, 2018 at 9:26
1

I know, this topic is a few years old, but OpenSSH 8.4 (released 2020-09-27) added agent forwarding to scp and sftp.

Now it's possible to copy a file from one remote to another, without routing through your local machine or provide credentials on the first host, to authenticate against the second host.

scp -A user1@remote1:/home/user1/file1.txt user2@remote2:/home/user2/file1.txt

Warning! Using agent forwarding is a security issue, when the first host is compromised or when you are affected from a mitm attack.

0

You can also provide the SOURCE and DESTINATION identity files in the CLI options -o IdentityFile rather than setting these up in .ssh/config. This is handy for e.g. a one-off -3 copy

scp -3 -o IdentityFile=~/.ssh/source.key -o IdentityFile=~/.ssh/dest.key source-user@example.com:/path/to/file dest-user@destination.com:/dest/location/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.