I have 3 computers/servers, let's call them as computer A, computer B and computer C.

  • Computer A has access via ssh to computer B.
  • Only computer B has access via ssh to computer C.
  • Computer A doesn't have access to computer C directly.

So, I want to rsync directories from computer A to computer C, using computer B(since only computer B has access via ssh to computer C). I want to use rsync in a simple way, like this:

rsync -options /path_to_local IpComputerC:/path_to_remote

I'm thinking on a ssh tunnel, but I don't know if I have to make a local port forwarding or a remote port forwarding, or if I have to make two tunnels: one from A to B and other from B to C?

Any suggestions?? I'd be really grateful.

**UPDATE: I dit it!! I created an ssh tunnel with local port forwarding, which means that I used a local port from the machine A to connect with a remote port on the machine C through the machine B. The syntax for the command is:

ssh -f -N -L local_port_machineA:ip_machineC:remoteport_machineC user_machineB@ip_machineB

In my case, remoteport_machineC shoul be port 22, because I want to rsync directories through ssh.

After that, we can execute the rsync command from the machine A, in this way:

rsync -avz -e "ssh -p local_port" /source_directory username_machineC@localhost:/target_directory

That's all. Additionally, you can add more options in the part inside the quotes, such as keys or files, etc.**


Much simpler than other suggestions: use rsync's -e | --rsh option:

rsync -azv -e 'ssh -o "ProxyCommand ssh -A proxy -W %h:%p"' foo/ dest:./foo/

Note that I'm using -A (agent forwarding) but it should also work with password authentication if you don't use keys, and, of course, you can replace proxy with B and dest with C in your example.

If by chance you don't have a new enough ssh version (>= 5.3, IIRC), you can use netcat instead of -W option to ssh:

rsync -azv -e 'ssh -o "ProxyCommand ssh -A proxy nc %h %p"' foo/ dest:./foo/
| improve this answer | |
  • My server "C" is a port on localhost on B (that is, there is a reverse tunnel set up from C to B). How can I rsync from A to C? That is, I need to specify different ports on B and C. – CPBL Oct 28 '18 at 3:56
  • Not quite enough information to know exactly how to address your situation. What is being tunneled over ssh (your "reverse tunnel")? Is it ssh? If so, you need only replace the (standard) port with the reverse tunnel endpoint port you specified. – crimson-egret Oct 29 '18 at 14:31
  • Here's my answer to my comment above: rsync -avzhP -e "ssh -A serverB ssh -p 9222" localfilename localhost:remotefilename where the tunnel of serverC ends on port 9222 on serverB – CPBL Oct 29 '18 at 18:13

One solution would be a crontab on your "jump node" (Computer B in this scenario).

A --> B (manually initiated, or could also be done via crontab on nodeA)

rsync -avzP --progress /path/to/transfer/ user@nodeB:/transfer/share/

B --> C (create a crontab to run every 15 mins)

sudo crontab -e
*/15 * * * * rsync -avzP --progress /transfer/share/ user@nodeC:/destination/share/

You might wish to further secure this by locking down access via a "service account" (AKA: ProdID) with limited access. Alternately you could use a SSH key to get around a password prompt at login.


supplemental information

Have you considered a remote NFS share (offered by nodeC, remotely mounted on nodeB, and targeted by the rsync from nodeA)? In this scenario, the remote NFS share (from NodeC) would be mounted on NodeB (and would appear as a standard file-system from the OS perspective). As such, it would be accessible within the connection scenario you describe, without consuming DISK on NodeB. Thus, you would be able to adapt the 'rsync' syntax above to point at the remote NFS share mounted on NodeB to ultimately "pass-thru" onto NodeC. There may also be security concerns you will wish to consider.

| improve this answer | |
  • inversecow, thanks for your response. Yes, you're right, but the problem is the storage capacity on server B due to the high amount of information that have to be passed. The idea is that the information pass from A to B and then from B to C, without using storage capacity in server B. For all of this reasons, I think that I should implement a ssh tunnel. – ehuarotop Aug 28 '15 at 19:27
  • No need for intermediate storage or the delays of cron. Use rsync --rsh; see other answer. – crimson-egret Sep 1 '15 at 14:10

NFS solution




NodeC: enable NFS, create NFS share, set non-root permissions (RHEL 5.x in this example, other distros will be subtly different)

sudo /sbin/chkconfig portmap on
sudo /sbin/chkconfig nfs on
sudo /sbin/service portmap start
sudo /sbin/service nfs start

sudo chown "nobody:users"   /final/destination/share
sudo chmod 775 /final/destination/share

sudo vi /etc/exports
    /final/destination/share    NodeC_IP(rw)    NodeB_IP(rw)    
sudo /usr/sbin/exportfs -ra

NodeB: mount destination share automatically

sudo mkdir -p /transfer/share/name
sudo vi /etc/fstab
    NodeC_IP:/final/destination/share   /transfer/share/name    nfs defaults
sudo mount -a

NodeA: schedule an rsync job (15 min frequency in this example)

# manual method
/usr/bin/rsync -avzP --progress /transfer/share/local/ user@nodeB:/transfer/share/name/

# scheduled method
sudo crontab -e
    */15 * * * * /usr/bin/rsync -avzP --progress /transfer/share/local/ user@nodeB:/transfer/share/name/
| improve this answer | |
  • While it may work, it involves a lot of overhead (nfs) and delays (cron). See my one-line answer using --rsh option to rsync. – crimson-egret Aug 31 '15 at 19:29

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.