Secure rsync via ssh as root

Securing Rsync as Root

From http://positon.org/rsync-command-restriction-over-ssh

Storage Server

  • Create rsa key if none yet
    • Check: cat ~/.ssh/id_rsa.pub
    • If none, create:  ssh-keygen -t rsa -b 4096 -o -a 64
  • Key exchange with client
    • ssh-copy-id -p 2222 www.example.com">user@www.example.com
    • If you want to to a manual key exchange:
      • On the machine you want to connect from:
        • cat ~/.ssh/id_rsa.pub
          • Copy the key
      • On the machine you want to connect to:
        • vi ~/.ssh/authorized_keys
          • Paste the key and save
  • Find out rsync server command via the option -e'ssh -v' by issuing a normal rsync ssh call:
  • Abort with CTRL-C after a short time
  • Note the line starting with "debug1: Sending command:"
    • debug1: Sending command: rsync --server --sender -vnlHogDtprze.iLsf --numeric-ids . /root/

Client - Server to be backed up:

  • vi /root/.ssh/authorized_keys
    • Find line for server (above)
    • Prepend to that line using the rsync server command from above:
      • restrict,from="123.123.123.123",command="rsync --server --sender -vnlHogDtprze.iLsf --numeric-ids . /root/"
    • Example for full line:
      • restrict,from="123.123.123.123",command="rsync --server --sender -vnlHogDtprze.iLsf --numeric-ids . /root/" ssh-rsa AAAAB3N...PC+v root@server.example.com
    • Allow multiple IPs / networks:
      • from="1.2.3.0/24,44.55.66.77"

    • All options: http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT

Storage Server

 

Details for rsync sender command

  • Run rsync with "-e 'ssh -v" option. Note the "sending" command, e.g.:
    • rsync --server --sender -vnlHogDtprze.iLsfxC --ignore-errors --numeric-ids --inplace . /
      • v = verbose
      • n = dryrun

Using Multiple commands with $SSH_ORIGINAL_COMMAND

http://binblog.info/2008/10/20/openssh-going-flexible-with-forced-commands/
https://www.thomas-krenn.com/de/wiki/Ausf%C3%BChrbare_SSH-Kommandos_per_authorized_keys_einschr%C3%A4nken

Scenario: Computer "apple" wants to execute commands as root on "orange".

Desired commands on "apple"

  • ssh root@orange ls -ls
  • rsync -a root@orange:/srv/ /backup/orange_srv/

Setup on "orange"

  • vi /root/.ssh/forced_commands_apple.sh
    • #!/bin/sh
      #
      
      # Secure SSH_ORIGINAL_COMMAND by stripping all characters except alphanum + space
      export VAR_CLEAN="`echo "${SSH_ORIGINAL_COMMAND}" | tr -cd '[:alnum:] [:space:]'`"
      
      # Debugging to find out rsync ssh commands.
      echo "`/bin/date`: $SSH_ORIGINAL_COMMAND" >> /tmp/ssh-command-log
      echo "`/bin/date`: $VAR_CLEAN" >> /tmp/ssh-command-log
      
      case "${VAR_CLEAN}" in
              "do this")
                      echo "hello"
                      ;;
              "do that")
                      echo "hello"
                      ;;
              *)
                      echo "Sorry. Only limited commands are available to you."
                      exit 1
                      ;;
      esac
  • chmod 700 /root/.ssh/forced_commands_apple.sh
  • vi /root/.ssh/authorized_keys
    • Prepend to correct line for "apple"
      • restrict,from="123.123.123.123",command="/root/.ssh/forced_commands_apple.sh"

Now we need to find out the correct "clean" command string.

Execute the desired commands on "apple":

  • ssh root@orange ls -ls
  • rsync -a root@orange:/srv/ /backup/orange_srv/

Now the "clean" command strings can be found in /tmp/ssh-command-log.
The "clean" string is used in the case comparison, and the original command in the clause. See example below.

  • cat /tmp/ssh-command-log
    • Die Apr  4 09:24:27 CEST 2017: ls -ls
      Die Apr  4 09:24:27 CEST 2017: ls ls
      Die Apr  4 09:25:41 CEST 2017: rsync --server --sender -logDtpre.iLsfx . /srv/
      Die Apr  4 09:25:41 CEST 2017: rsync server sender logDtpreiLsfx  srv
    • The "clean" command string is each second line without any special characters
  • vi /root/.ssh/forced_commands_apple.sh
    • #!/bin/sh
      #
      
      # Secure SSH_ORIGINAL_COMMAND by stripping all characters except alphanum + space
      export VAR_CLEAN="`echo "${SSH_ORIGINAL_COMMAND}" | tr -cd '[:alnum:] [:space:]'`"
      
      # Debugging to find out rsync ssh commands.
      #echo "`/bin/date`: $SSH_ORIGINAL_COMMAND" >> /tmp/ssh-command-log
      #echo "`/bin/date`: $VAR_CLEAN" >> /tmp/ssh-command-log
      
      case "${VAR_CLEAN}" in
              "ls ls")
                      ls -ls
                      ;;
              "rsync server sender logDtpreiLsfx  srv")
                      rsync --server --sender -logDtpre.iLsfx . /srv/
                      ;;
              *)
                      echo "Sorry. Only limited commands are available to you."
                      exit 1
                      ;;
      esac
  • rm /tmp/ssh-command-log

If you modify the command, or want to add a new one you have to repeat the whole process.