Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How should ForceCommand be configured in order to allow the backup user to execute any rsync command? With ForceCommand set to /usr/bin/rsync I receive the error below: connection unexpectedly closed...

/etc/ssh/sshd_config on remote server hosting the files to be copied from:

Match User backup
    PasswordAuthentication no  
    PubkeyAuthentication yes  
    AllowTCPForwarding no  
    X11Forwarding no  
    ForceCommand /usr/bin/rsync  

rsync command running on the local server doing the copying from the remote server:

rsync -avzh --progress backup@hostname.domain:/opt/backups/automatic/cron/mysql/ /tmp/.  

rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(601) [Receiver=3.0.7]

If I configure ForceCommand to the exact rsync command such as the one below I am able to remotely rsync successfully as the backup user but for this project I don't want to have to use the full exact command as below:

ForceCommand /usr/bin/rsync --server --sender -vlwkDonecf.iLew . /opt/backups/automatic/cron/mysql/

If I configure ForceCommand to use a script such as the one below I am able to remotely rsync successfully. I'm curious why this works and /usr/bin/rsync doesn't?

Match User backup
    PasswordAuthentication no  
    PubkeyAuthentication yes  
    AllowTCPForwarding no  
    X11Forwarding no  
    ForceCommand /home/backup/cron/validate-rsync  

The validate-rsync script:

#!/bin/sh   
#script to validate rsync  
#script source: http://troy.jdmz.net/rsync/#validate-rsync  

case "$SSH_ORIGINAL_COMMAND" in   
*\&*)   
echo "Rejected"   
;;   
*\(*)   
echo "Rejected"   
;;   
*\{*)   
echo "Rejected"   
;;   
*\;*)   
echo "Rejected"   
;;   
*\<*)   
echo "Rejected"   
;;   
*\`*)   
echo "Rejected"   
;;   
*\|*)   
echo "Rejected"   
;;   
rsync\ --server*)   
$SSH_ORIGINAL_COMMAND   
;;   
*)   
echo "Rejected"   
;;   
esac   

My primary question is why doesn't ForceCommand /usr/bin/rsync work?

I'm also curious about the best way(s) to do this. I can't chroot the backup user because I'm copying from several different folders. I don't really want to have to use the full exact rsync --server --client etc. command because I'm copying several different folders and that seems excessive. I'm curious about the simplest/best way(s) to restrict the backup user to rsync.

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

The why is easy... ForceCommand does exactly what it says: You connect, it forces you to run that command no matter what you actually wanted to do. In this case, that command is /usr/bin/rsync with no flags.

rsync works by running another copy of rsync on the other side of the connection and talking to it over ssh. In this case though, it's unable to start the other side with the flags it needs because the command is replaced by /usr/bin/rsync

Your rsync-validate script is probably the best way to go about this. It checks the request to make sure it is a valid rsync server command, and only then does it run it. rsync probably could be modified to check the $SSH_ORIGINAL_COMMAND directly when its run without arguments, but there's probably a good security reason not to do so.

share|improve this answer
add comment

The ForceCommand option is meant to be used with a command that specifically understands that it's acting as an SSH gatekeeper. The original command is placed in the SSH_ORIGINAL_COMMAND environment variable.

share|improve this answer
    
It sounds like in the case of ForceCommand internal-sftp, internal-sftp understands that it's acting as an SSH gatekeeper? In contrast with ForceCommand /usr/bin/rsync whereas it sounds like ForceCommand /usr/bin/rsync doesn't understand that it's acting as an SSH gatekeeper and thus a script is required and use of $SSH_ORIGINAL_COMMAND is required? –  caleban Oct 21 '11 at 1:06
    
Yes, sort of. Internal subsystems are a special case. Good point. –  David Schwartz Oct 21 '11 at 1:10
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.