I'm trying to download files using rsync with rsync running in daemon mode over SSH on the server and get the following error on the client:

rsync -a myserver:/remote/path/ localdestdir/
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(176) [Receiver=3.1.1]

The server has this in .ssh/authorized_keys for the user:

command="rsync --config=/path/to/engine-rsyncd.conf --server --daemon ." ssh-rsa ...

I've read all I could find about this problem and, as everyone suggests, checked that the shell is clean and IT IS CLEAN:

ssh myserver false >out.tmp

creates a zero-length file out.tmp (if I remove the "command=..." from authorized_keys on the server).

I also tried setting the user's shell to rssh instead of bash on the server - same thing.

Both client and server are running Ubuntu 16.04, so they have the same version of rsync (3.3.1, protocol 31).

What else could it be? I tried enabling verbose logging in rsync and SSH and the logs don't give me any clue. The rsync daemon doesn't log anything more than

2018/02/12 15:14:24 [6215] connect from clienthostname
  • So when you removed the command= and tried running rsync again, what happened? – Michael Hampton Feb 12 '18 at 17:27
  • Without command= rsync works. (I'm just trying to make it more secure by preventing that user from doing anything other than rsyncing a particular directory.) – EM0 Feb 13 '18 at 8:18
  • That's why rsync is complaining, then. It expects to start the rsync daemon on the remote end itself. – Michael Hampton Feb 13 '18 at 18:59
  • Oh! Then how do I get it to use the one already running on the remote end (over SSH)? I was following gist.github.com/trendels/6582e95012f6c7fc6542 and it said to run rsync -av --rsh=ssh remote_host::home destination/ on the client, which is basically what I'm doing (I tried adding --rsh=ssh and that made no difference). – EM0 Feb 14 '18 at 8:59
  • Try increasing the verbosity of rsync (see the man page). – Martin Schröder Feb 24 '18 at 0:33

You problem in this case is not that the shell is not clean, but that the client rsync can execute the command it needs to execute on the server. If you use the command="rsync..." in authorized_keys, then that is the command that sshd will execute, regardless of the command that is passed by the client.

The client rsync will call ssh with these arguments:

ssh myserver rsync --server --sender -de.LsfxC . /remote/path/`.

Note that --sender is part of these options, because you want the server to send you files. It is not present if the server should receive files. Note also that --daemon is not present in the options to rsync. As the option --config is only relevant together with --daemon, it can also be removed from your command entry.

Is I already mentioned, the command will be executed exactly as it is in the authorized_keys file. That means that all arguments that are passed from the client will be ignored. So if you really want to use command in authorized_keys, you have to specify the exact options that rsync would supply to the ssh client, and that means you can use rsync only to receive files from exactly the path the is specified in authorized_keys. If you supply different options to the rsync on the client, they will not be effective on the server and therefor may or may not work depending on whether the effect of these options is implemented on the client or on the server side of rsync. So you should consider whether you really want that.

Edit You can use a script as the command and examine the SSH_ORIGINAL_COMMAND environment variable to call rsync as needed. As the remote path is the last argument, you might just want to check whether it starts with the right prefix and doesn't contain any "/.." that would go to the parent directory.

| improve this answer | |
  • I see, thanks. This makes sense, but it's not the answer I was hoping for! Is there any way I can restrict the user to rsyncing from a particular directory, while allowing them to specify sub-directories? E.g. I want them to rsync from anywhere under /remote/path, but the client will really want to rsync only /remote/path/one or /remote/path/two on any given call. – EM0 Jul 20 '18 at 11:58
  • @EM0 I added a suggestion about using SSH_ORIGINAL_COMMAND – RalfFriedl Jul 21 '18 at 18:35

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.