I often have the case that I have to make a lot of hops to the remote host, just because there is no direct routing between my client and the remote host. When I need to copy files from a remote host two or more hops away, I always have to:

client$ ssh host1
host1$ ssh host2
host2$ scp host3:/myfile .
host2$ exit
host1$ scp host2:myfile .
host1$ exit
client$ scp host1:myfile .

Back when uucp still was being used this would be as simple as a

uucp host1!host2!host3 /myfile .

I know that there's uucp over ssh, but unfortunately I don't have the proper privileges on those machines to set it up. Also, I'm not sure if I really want to fiddle around with customer's machines.

Does anyone know of a method doing this tasks without the need to setup a lot of tunnels or deploying new software to remote hosts? Maybe some kind of recursive script which clones itself to all the remote hosts, doing the hard work for me?

Assume that authentication takes place with public keys and that all hosts do SSH Agent Forwarding.

Edit: I'm not looking for a way to automatically forwarding my interactive sesssion to the nexthop host. I want a solution to copy files bangpath-style using scp via multiple hops without the need to install uucp on any of those machines. I don't have the (legal) rights or the privileges to make permanent changes to the ssh-config. Also, I'm sharing this username and hosts with a lot of other people. I'm willing to hack up my own script, but I wanted to know if anyone knows something which already does it. Minimum-invasive changes to hosts on the bangpath, simple invocation from the client.

Edit 2: To give you an impression of how it's properly been done in interactive sessions, have a look at the GXPC clustershell. This is basically a Python-script, which spwans itself over to all remote hosts which have connectivity and where your ssh-key is installed. The great thing about it is, that you can tell "I can reach HostC via HostB via HostA." It just works. I want to have this for scp.

  • Have you tried using the proxycommand option os SSH? This will permit you to go from a to c directly usually. serverfault.com/questions/72343/ssh-relay-server-with-openssh/… – Zoredache Oct 5 '12 at 18:51
  • @Zoredache Yes, I know about that, but I'm not the only one using those hosts as this user. It should be minimally invasive. That's why I'm thinking of a recursive, self-propagating shell-script which does the work. I'm keen to brew my own, but I first wanted to check if someone already made one. – Alexander Janssen Oct 5 '12 at 18:57
  • If lots of people are using that host, then teach them how to use the proxy command, or if they are all on your network, then why not just publish a system wide ssh_config to all the client machines? If all the hosts are under your control, then consider setting up puppet or something, then you can publish a configuration file to every machine. – Zoredache Oct 5 '12 at 19:20
  • As I said, "I don't have the proper privileges on those machines to set it up" - those machines aren't mine. Also, host1 is not only a jumphost for host2, but also for several other hosts. I'm looking for a general solution - scp like uucp. Also, I only want copying files, not interactive sessions gained by easy config-tweaks. For the latter, this website is a good reference. – Alexander Janssen Oct 5 '12 at 19:31
  • «That's why I'm thinking of a recursive, self-propagating shell-script which does the work» — ergh, it's en.wikipedia.org/wiki/Morris_worm — isn't it? ☺ – poige Oct 8 '12 at 19:06

Even though you specifically mention that this is not what you are looking for, I'm going to insist that you try this because setting up a script on every host in the path to your destination is more complex and time consuming.

If you are on host laptop and you wish to copy something to host webserver, but you can access webserver only through companygatweay.org, then all you need to do is:

laptop$   ssh -L4444 companygateway.org:webserevr:22

This will open up port 4444 on your local machine directly through to the webserver on port 22.

copying with scp to webserver would look like:

laptop$    scp -P 4444 /some/files/here localhost:/to/some/files/on/webserver

to copy from the webserver:

laptop$    scp -P 4444 localhost:/tmp/remote/files /home/localusername/downloads
  • Oh, I know about that - that works perfectly. It starts getting interesting if you need to cross more than one hop. Usually it goes like this: localhost->my_corp_jumphost->vpn->customer_jumphost->cluster_head_node->clusternode . Quite a few hops and messing around with tunnels starts getting really nasty after a while. Actually I have a similar setup in my localhost's ssh_config file, "RemoteForward 3128, ForwardAgent yes, LocalForward 2222:jumphost:22" and a few others. – Alexander Janssen Oct 16 '12 at 16:34

ssh host1 ssh host2 ssh host3 cat /myfile > myfile ? :)

UPD. (2014-01-20): Recently I came across man dbclient which mentions: «…

-B endhost:endport — "Netcat-alike" mode, where Dropbear will connect to the given host, then create a forwarded connection to endhost. This will then be presented as dbclient's standard input/output.

Dropbear will also allow multiple "hops" to be specified, separated by commas. In this case a connection will be made to the first host, then a TCP forwarded connection will be made through that to the second host, and so on. Hosts other than the final destination will not see anything other than the encrypted SSH stream. A port for a host can be specified with a slash (eg matt@martello/44 ). This syntax can also be used with scp or rsync (specifying dbclient as the ssh/rsh command). A file can be "bounced" through multiple SSH hops, eg

         scp -S dbclient matt@martello,root@wrt,canyons:/tmp/dump .

Note that hostnames are resolved by the prior hop (so "canyons" would be resolved by the host "wrt") in the example above, the same way as other -L TCP forwarded hosts are. Host keys are checked locally based on the given hostname.

  • You know... sometimes the easy things just work. Thanks for sorting my brain out :) – Alexander Janssen Oct 8 '12 at 20:16
  • It's not exactly what I'm looking for, I'll reward the bounty anyway. (as soon as SF let 's me...) – Alexander Janssen Oct 8 '12 at 20:24
  • @AlexanderJanssen, atually there's plenty of time till the end of bounty, so let's see — there might be something else to learn from ;) – poige Oct 8 '12 at 21:23
  • As Ярослав Рахматуллин (hope the russian charset isn't messed up) pointed out correctly in his answer below, messing around with self-replicating shellscripts is messy. Your answer is useful and also pretty beautiful at the same time - I don't know why I didn't think of that first. I think I'll just use exactly that what you gave and wrap it up so that I can use my beloved uucp hashpath style. :-) – Alexander Janssen Oct 16 '12 at 16:39
  • @AlexanderJanssen, hi! See the UPD. ) – poige Jan 20 '14 at 6:33

If your version of scp comes from a reasonably recent version of openssh then you may be able to use the ProxyJump option: scp -o Proxyjump=firsthop.example.com,secondhop.example.com /path/to/file destination.example.com:/where/to/put/it This relies on forwarding one ssh connection over the other but in a transient fashion rather than by setting up a listening port. Because of this it doesn't require any special set up on the intermediate hosts other than sshd allowing the ability to make connections to remote ports.

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.