I have read several articles how to automatically backup files with Rsync and public key authentication. All of them are very similar. I just finished setting up everything and everything works fine but... I just found an article which says it's not secure. I did the following:

  1. On backup server I generated public and private keys.
  2. I copied public key to the remote (original) servers directory: /var/sites/.ssh (file authorized_keys). The directory is owned by "user12"
  3. I added the following to the authorized_keys file: from="BACKUP.SERVERS.IP.ADDRESS",command="/root/validate_rsync"
  4. I created a file /root/validate_rsync with the following content:

    echo $SSH_ORIGINAL_COMMAND >> /var/log/synchronize-log.log
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    echo "Rejected"
    rsync\ --server*) 
    echo "Rejected"

I run the rsync command:

rsync -avzp --del -e "ssh -p 2211" user12@ORIGINAL.SERVERS.IP:/var/sites/photos/ /var/sites/sync/photos

I got error message: permission problems with file /root/validate_rsync. I moved the file /root/validate_rsync to /var/sites/validate_rsync and chowned it to user12:user12

Now synchronization works. But I found an article which says it's insecure:

1- the validate_rsync command itself should not be owned nor writeable by the userid that executes the rsync command. Otherwise, rsync can be used to overwrite the validation script with another script that doesn't validate, or even execute arbitrary commands.

2- similarly, the authorized-keys file should not be owned or writeable by the rsync user, otherwise rsync can be used to overwrite that file, with one that removes the requirement to run validate-rsync, or with one that runs some other command instead.


What can I do? If validate_rsync is owned by root, the synchronization does not start because user12 can't access root's files. If authorized-keys file will be owned by another user I will not be able to login with username user12.

My questions:

  1. Where should I put validate_rsync and authorized-keys files, in which directory? What permissions and ownerships should they have?

  2. Is there some way how to tell to the validate_rsync file to allow to synchronize only 2 folders: /var/sites/photos/, /var/sites/photos2/

  • 1
    github.com/scponly/scponly – dmourati Sep 16 '14 at 16:00
  • I don't see why you need a validate-sync script anyway. If you are using rsync as a backup, you could just use a forced command that specifies rsync --server (Possibly with some further options too) – Cameron Kerr Sep 17 '14 at 19:22
  • @CameronKerr, although not really needed, it gives you more flexibility if you want to allow a rsync command with different options. – Migtor Sep 18 '14 at 9:37

Those security concerns are right. So, to answer your first question: to make it work as you like, you should put validate_rsync in a directory where user12 has execute permission, but not write. The very same validate_rsync file should have read and execute permissions for the user, but of course not write. The issue here is that /root by default is accessible only by root user, you need a path where each directory has execute permission for user12. For example, you could copy validate_rsync to /usr/local/bin and make it owned by root. As long as user12 can execute and read, it's OK.

You don't need to protect your authorized_keys file. It would be better to force user12 to run a command by configuration, putting in sshd_config the following:

Match user user12
  ForceCommand /usr/local/bin/validate_rsync

I think this solution is better than tinkering with authorized_keys.

Also, in your validate_rsync I would quote $SSH_ORIGINAL_COMMAND (safer), and I would change your case sentence to check the validty of the command for a regular expression using grep; easier, more compact and more powerful:

echo "$SSH_ORIGINAL_COMMAND" >> /var/log/synchronize-log.log
if echo "$SSH_ORIGINAL_COMMAND" | grep -qE '[&;<>`|]'; then
  echo Rejected
elif [[ "${SSH_ORIGINAL_COMMAND:0:14}" == "rsync --server" ]]; then
  echo Rejected

To answer your second question, as you are logging the SSH_ORIGINAL_COMMAND, you can run a test with the directories you want to consider and then examine the SSH_ORIGINAL_COMMAND you are getting. Then you could make validate_rsync to validate just that command.

| improve this answer | |
  • Sorry, that is the PS, these are alternative solutions that I put in previous edits of the answer, but I suggest you use the solution in the answer instead: putting Match user in sshd_config. Sorry, the response was a bit confusing, I'm going to delete the PS. – Migtor Sep 18 '14 at 9:34
  • 1. I copied file validate_rsync to /usr/local/validate_rsync. It's owned by root and permissions 754. Can't synchronize - permission denied. 2. Your first solution of authorized_keys was better. Unfortunately, I didn't copy it. I also need to login as user12 with username and password to upload files vis sftp to /var/sites/. If I add ForceCommand, I need to create another user for this purpose, but all uploaded files then will be owned by this user, not by user12. Everything too complicated. – tfegc Sep 18 '14 at 11:33
  • 1. Which group? Why not permissions 755? 2. Why do you think authorized_keys solution was better? It was more complicated and less safe, it didn't have any benefit. You don't need to use sftp to upload files, rsync can be used for that as well. – Migtor Sep 18 '14 at 11:51
  • 755 for validate_rsync solved permission problem. I can't upload files from my home computer (windows) to the server (debian) using rsync. Then I need a special software. It's much easier using sftp. I think I will leave authorized_keys file where is it. This file contains line from="BACKUP_SERVER_IP". I changed line rsync\ --server*) to rsync\ --server\ --sender\ -vlogDtprze.iLsf\ .\ /var/sites/photos/*). Actually, I don't understand how someone else using rsync command could change `authorized_keys file. Maybe I need to open a new question. We have too many comments and I it will be – tfegc Sep 18 '14 at 12:14
  • You could use rsync to replace your authorized_keys file if you have permissions on it and if you are not restricting which paths to synchronize in validate_rsync. – Migtor Sep 19 '14 at 8:53

To protect the authorized_keys file, I came across this solution: https://superuser.com/questions/852434/how-to-protect-authorized-keys-file

It's pretty common to simply remove write-access to that file if you're not planning to change it often.

chmod 400 ~/.ssh/authorized_keys

Now, of course, that write access could be added back in by a malicious script, so you need to set the file and its parent directory to be immutable:

sudo chattr +i ~/.ssh/authorized_keys
sudo chattr +i ~/.ssh
| improve this answer | |

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.