3

I have a group of servers all properly configured with SSH agent forwarding. It is a typical bastion server style configuration where the only machine you can connect to from the outside is server A. From server A you can use agent forwarding to connect to servers B, C, D, etc. It is all working perfectly.

Sometimes I want to copy a file from my local machine to server B. In order to do this I have to first scp the file to server A. Then ssh to server A and scp the file to server B. Then I delete the file from server A.

Is there a way to copy the file directly from my computer to server B via server A in just one command executed on my local machine?

Apreche
  • 1,405
  • 5
  • 17
  • 20

4 Answers4

3

If your sshd is configured to allow TCP forwarding then you can set up a tunnel from your computer to B via A and then use it to copy things through. Create the tunnel

ssh -f -L 2050:B:22 A -N
  • -f background the ssh command so you get your terminal back to use.
  • -L 2050:B22 bind localhost port 2050 to host B port 22
  • -N do not execute a remote command.

then to copy from your computer to B

scp -P 2050 filetocopy localhost:/destination/path 

EDIT: If you use

ssh -L 2050:B:22 A -N &

Then you will be told the PID of the ssh command when it backgrounds.

user9517
  • 115,471
  • 20
  • 215
  • 297
1

Put something like this into .ssh/config:

Host B-p C-p D-p
        ProxyCommand ssh -W %h:%p A.example.com
Host B-p
        Hostname B.example.com
Host C-p
        Hostname C.example.com
Host D-p
        Hostname D.example.com

and just ssh or scp to/from B-p. You can omit the -p suffix and configure the ProxyCommand directly on the B.example.com etc. if you are always "outside".

This incurs a little traffic overhead between your machine and the bastion host, but works without agent forwarding.

1

I have a similar (even more complex) case recently and managed to solve the problem.

The short answer: use ProxyCommand instead of agent forwarding.

The long story:

In my case four hosts are involved:

  • Linux desktop in my office
  • Linux VPN server somewhere on the Internet
  • Linux home server in my apartment
  • Linux laptop in my apartment

The router in my apartment gets no public address from the ISP, so home laptop and home servers are both behind double-NAT, no way I can do port forwarding or something because I cannot control ISP devices. For some reason, the home server is always connected to a VPN server with public address. This way I can ssh -A into the VPN server, and ssh -A into home server and finally ssh into my home laptop.

But sometimes I need to transfer files. I do not want to rsync / scp multiple times hop by hop.

ProxyCommand comes to rescue. Put these in the ~/.ssh/ssh_config:

# Host A is a VPN gateway with public address.
Host a.example.org
  HostName 1.2.3.4

# Host B is a home server / gateway with no public address.
# It's connected to host A via VPN.
Host b.example.org
  HostName 10.255.255.100
  ProxyCommand ssh -W %h:%p a.example.org

# Host C is my home laptop.
Host c.example.org
  HostName 192.168.2.100
  ProxyCommand ssh -W %h:%p b.example.org

# vim: ft=sshconfig:

This could be indefinitely chained. You can keep chaining host D, host E, etc as long as your hosts have fast connections. There is no need to do ssh -L or ssh -D hop by hop manually and connect through non-standard ports. I can now do ssh c.example.org directly from anywhere as long as I can connect to a.example.org. Of course other SSH-based protocols like Rsync, SCP, SFTP, etc are automatically supported.

Zhuoyun Wei
  • 380
  • 2
  • 4
  • 11
0

You might use tar to copy the file:

tar cC SRC-DIR SRC-FILE | ssh A.example.com ssh B.example.com tar xC DST-DIR

Be sure to add the correct amount of quoting to DST-DIR if required; it will be interpreted by three shells.

Using ssh and tar is very flexible, for example when scp refuses to work with two remote locations.