Improved the "rsync through a firewall" methods using some ideas
authorWayne Davison <wayned@samba.org>
Thu, 20 Oct 2005 19:48:35 +0000 (19:48 +0000)
committerWayne Davison <wayned@samba.org>
Thu, 20 Oct 2005 19:48:35 +0000 (19:48 +0000)
from Matt McCutchen.

faqbody.html

index 7aa4a92e44b80dc98d9f8c8368b6df849a4d3316..5db71287df3047ce54056cd96741f003feb8cd4f 100644 (file)
@@ -46,12 +46,12 @@ daemon logs).
 <p>A good way to test if your remote-shell connection is clean is to try
 something like this (use ssh or rsh, as appropriate):
 
-<blockquote><pre>ssh remotemachine /bin/true &gt; test.dat</pre></blockquote>
+<blockquote><pre>ssh remotesystem /bin/true &gt; test.dat</pre></blockquote>
 
 <p>That should create a file called test.dat with nothing in it. If
 test.dat is not of zero length then your shell is not clean.  Look at the
 contents of test.dat to see what was sent. Look at all the startup files on
-remotemachine to try and find the problem.
+remotesystem to try and find the problem.
 
 <hr>
 <h3><a name=4>memory usage</a></h3>
@@ -84,50 +84,91 @@ less memory.  Unfortunately, such an rsync does not yet exist.
 <h3><a name=6>rsync through a firewall</a></h3>
 
 <p>If you have a setup where there is no way to directly connect two
-machines for an rsync transfer, there are several ways to use the firewall
-machine to act as an intermediary in the transfer.
+systems for an rsync transfer, there are several ways to use the firewall
+system to act as an intermediary in the transfer.
 
 <h4>Method 1</h4>
 
-<p>Use ssh to access the intermediary system and have it ssh into the
-actual target machine.
+<p>Use your remote shell (e.g. ssh) to access the intermediary system and
+have it use a remote shell to hop over to the actual target system.
 
-<p>To effect this extra ssh hop, you'll need to configure a authorization
-method that does not involve any user interaction (such as prompting for a
-password).  The easiest way to do this is to setup an ssh key (see the
-ssh-key manpage).  You can encrypt this key (which requires a passphrase to
-unlock it) as long as you have ssh-agent forwarding enabled -- this allows
-the ssh connection between the intermediary system and the target machine
-to authorize without a passphrase prompt because the authorization
-information is coming from your local machine via the ssh protocol (which
-has the benefit of not making intra-system logins password-less in
-general).  Another solution is to configure host-based authentication,
-which makes all logins between authorized machines automatically authorized
-(which may or may not be something that you are comfortable with).
+<p>To effect this extra hop, you'll need to make sure that the remote shell
+on the intermediary system does not involve any tty-based user interaction
+(such as prompting for a password) because there is no way for the
+intermediary system to access the user's tty.
 
-<p>You should then test that the forwarded ssh connection works without a
-prompt by running a command like this:
+<p>One way that works for both rsh and ssh is to enable host-based
+authentication, which would allow all connections from the intermediary to the
+target system to succeed (when the username remains the same).  However, this
+may not be a desirable setup.
 
-<blockquote><pre>ssh inter ssh target uptime</pre></blockquote>
+<p>Another method that works with ssh (and is also very safe) is to setup an
+ssh key (see the ssh-key manpage) and ensure that ssh-agent forwarding is
+turned on (e.g. "ForwardAgent&nbsp;yes").  You would put the public version
+of your key onto the intermediary and target systems, and the private key
+on your origin system (which I recommend you encrypt).  With this setup, a
+series of ssh connections that starts from the system where your private
+key is available will auto-authorize (after the first pass-phrase prompt on
+the first system).
+
+<p>You should then test that a series of ssh connections works without
+multiple prompts by running a command like this (put in the real "middle"
+and "target" hostnames, of course):
+
+<blockquote><pre>ssh middle ssh target uptime</pre></blockquote>
 
 <p>If you get a password/passphrase prompt to get into the intermediary
-system that's fine, but the extra hop need to occur without any extra user
+system that's fine, but the extra hop needs to occur without any extra user
 interaction.
 
-<p>Once that's done, you can do an rsync copy like this (one pull, one
-push):
+<p>Once that's done, you can do an rsync copy like this:
 
-<blockquote><pre>rsync -av --rsync-path="ssh target rsync" inter:/source/ /dest/
-rsync -av --rsync-path="ssh target rsync" /source/ inter:/dest/</pre></blockquote>
-
-<p>These commands looks like they are copying to/from the "inter" host, but the 
-remote-rsync command that we it to run performs the extra hop to the real
-target system and runs the rsync command there.
+<blockquote><pre>rsync -av -e "ssh middle ssh" target:/source/ /dest/</pre></blockquote>
 
 <h4>Method 2</h4>
 
+<p>Assuming you're using ssh as your remote shell, you can configure ssh to
+forward a local-port through your intermediary system to the ssh port (22)
+on the destination system.
+
+<p>The first thing we need is an ssh configuration that will allow us to
+connect to the forwarded port as if we were connecting to the target system,
+and we need ssh to know what we're doing so that it doesn't complain about
+the host keys being wrong.  We can do this by adding this section to your
+~/.ssh/config file (substitute "target" and "target_user" as appropriate):
+
+<blockquote><pre>Host target
+  HostName localhost
+  Port 2222
+  HostKeyAlias target
+  User target_user
+</pre></blockquote>
+
+<p>Next, we need to enable the port forwarding:
+
+<blockquote><pre>ssh -fN -l userid_on_middle -L 2222:target:22 middle</pre></blockquote>
+
+<p>What this does is cause a connection to port 2222 on the local system to
+get tunneled to the intermediary system and then turn into a connection to
+the target system's port 22.  The -N option tells ssh not to run a command
+on the remote system, which works with modern ssh versions (you can run a
+sleep command if -N doesn't work).  The -f option tells ssh to put the
+command in the background after any password/passphrase prompts.
+
+<p>With this done, you could run a normal-looking rsync command to "target"
+that would use a connection to port 2222 on localhost automatically:
+
+<blockquote><pre>rsync -av target:/src/ /dest/</pre></blockquote>
+
+<p><b>Note:</b> starting an ssh tunnel allows anyone on the source system to
+connect to the localhost port 2222, not just you, but they'd still need to
+be able to login to the target system using their own credentials.
+
+<h4>Method 3</h4>
+
 <p>Install and configure an rsync daemon on the target and use an ssh
-tunnel to reach the rsync sever.
+tunnel to reach the rsync sever.  This is similar to method 2, but
+tunnels the daemon port for those that prefer to use an rsync daemon.
 
 <p>Installing the rsync daemon is beyond the scope of this document, but
 see the rsyncd.conf manpage for more information.  Keep in mind that you
@@ -137,19 +178,18 @@ protected port.
 <p>Once your rsync daemon is up and running, you build an ssh tunnel
 through your intermediary system like this:
 
-<blockquote><pre>ssh -fN -l userid_on_inter -L 8873:target:8873 inter</pre></blockquote>
+<blockquote><pre>ssh -fN -l userid_on_middle -L 8873:target:873 middle</pre></blockquote>
 
 <p>What this does is cause a connection to port 8873 on the local system to
-turn into a connection from the intermediary system to the target machine
-on port 8873.  (Port 8873 was chosen instead of the normal 873 port number
-because it does not require root privileges--use whatever port number you
-like.)  The -N option tells ssh not to run a command on the remote system,
-which works with modern ssh versions (you can run a sleep command if -N
-doesn't work).  The -f option tells ssh to put the command in the
-background after any password/passphrase prompts.
+turn into a connection from the intermediary system to the target system on
+port 873.  (Port 873 is the normal port for an rsync daemon.) The -N option
+tells ssh not to run a command on the remote system, which works with
+modern ssh versions (you can run a sleep command if -N doesn't work).  The
+-f option tells ssh to put the command in the background after any
+password/passphrase prompts.
 
 <p>Now when an rsync command is executed with a daemon-mode command-line
-syntax to the local machine, the conversation is directed to the target
+syntax to the local system, the conversation is directed to the target
 system.  For example:
 
 <blockquote><pre>rsync -av --port 8873 localhost::module/source dest/
@@ -174,11 +214,11 @@ binary in your path. There are 3 possible solutions:
 
 <li>install rsync in a "standard" location that is in your remote path. 
 
-<li>modify your .cshrc, .bashrc etc on the remote machine to include the path
+<li>modify your .cshrc, .bashrc etc on the remote system to include the path
 that rsync is in
 
 <li>use the --rsync-path option to explicitly specify the path on the
-remote machine where rsync is installed
+remote system where rsync is installed
 
 </ol>