Afin d’effectuer la sauvegarde d’un serveur par un autre, il est courant d’utiliser un couple de clé SSH publique/privée sans mot de passe.
Tout commence par la génération du couple de clé :
fhh@mafalda ~ $ ssh-keygen -b4096 -C "Clé de sauvegarde" -f ~/.ssh/Saves Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): # rien Enter same passphrase again: # rien Your identification has been saved in /home/fhh/.ssh/Saves. Your public key has been saved in /home/fhh/.ssh/Saves.pub. The key fingerprint is: 80:f8:8e:69:e3:95:6a:98:a7:d3:e4:89:53:be:dc:68 Clé de sauvegarde The key's randomart image is: +--[ RSA 4096]----+ ... +-----------------+ fhh@mafalda ~ $ ls .ssh/Saves* .ssh/Saves .ssh/Saves.pub |
… et ce poursuit par la copie de la clé publique (.ssh/Saves.pub) dans le fichier « .ssh/authorized_keys » du serveur à sauvegarder :
fhh@mafalda ~ $ cat .ssh/Saves.pub | ssh srv.rez0.lan 'cat >> .ssh/authorized_keys' Password: fhh@mafalda ~ $ ssh -i .ssh/Saves srv.rez0.lan 'cat .ssh/authorized_keys' ... ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde |
… pour finir par l’ajout de la clé associée au serveur dans « .ssh/config » :
fhh@mafalda ~ $ cat .ssh/config ... Host=srvtobackup1 Hostname=srv.rez0.lan User=fhh Port=22 Compression=yes IdentityFile=~/.ssh/Saves ... fhh@mafalda ~ $ ssh srvtobackup1 fhh@srv ~ $ |
Le travail consiste ensuite à sécuriser cet accès au serveur à sauvegarder avec ce couple de clé :
- seul le serveur de sauvegarde devra être autorisé à ce connecter avec la clé privée.
- seul les commandes effectuant la sauvegarde devront être autorisée par cette connexion.
Toutes ces restrictions ce mettent en place sur le serveurs à sauvegarder directement dans le fichier « .ssh/authorized_keys ».
Limiter les machines autorisées à ce connecter avec la clé privée
Le champs « from=XXX » sur le serveur à sauvegarder restreint l’accès par cette clé aux machines spécifiées. »XXX » peu désigner :
- le FQDN d’une machine, ex : machine.rez0.lan (seul cette machine sera authorisée à ce connecter en utilisant cette clé) ;
- une adresse IP, ex : 10.0.2.2 (comme pour le FQDN mais avec l’IP) ;
- une plage IP, ex : 10.0.2.* (toutes les machines de cette plage pourront utiliser cette clé pour ce connecter) ;
- un domaine, ex : *.rez0.lan (comme pour la plage IP mais avec le domaine) ;
- une liste restrictive de machine, ex : « *.rez0.lan, !ns1.rez0.lan » ;
- des noms de machines utilisant les jokers habituels, ex : « ns?.rez0.lan ».
En reprenant notre exemple, seul la machine « mafalda.rez0.lan » doit être autorisée à ce connecter au serveur devant être sauvegardé :
fhh@mafalda ~ $ ssh srvtobackup1 fhh@srv ~ $ vi .ssh/authorized_keys ... ## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>) from="mafalda.rez0.lan" ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde ... fhh@srv ~ $ exit Connection to srv.rez0.lan closed. fhh@mafalda ~ $ ssh srvtobackup1 fhh@srv ~ $ |
mais depuis une autre machine disposant également de la clé privée et des mêmes paramètres dans « .ssh/config », le mot de passe est demandé :
fhh@asus ~ $ ssh srvtobackup1 Password: |
Limiter les fonctionnalités de la clé
La clé étant destinée uniquement à lancer une sauvegarde, les fonctionnalités tel que le X11 forwarding ou le port forwarding peuvent être suspendues. En fonction de l’utilisation faite de la clé, l’accès à un tty peut également être suspendu afin de ne plus offrir un shell interactif.
Avec une configuration du type :
fhh@srv ~ $ cat .ssh/authorized_keys ... ## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>) from="mafalda.rez0.lan",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde ... |
Nous obtenons un comportement plutôt restrictif :
fhh@mafalda ~ $ ssh srvtobackup1 PTY allocation request failed on channel 0 Killed by signal 15. fhh@mafalda ~ $ ssh srvtobackup1 'ls' 0493.pdf fic1.txt ... |
mais pas encore suffisamment :
fhh@mafalda ~ $ ssh srvtobackup1 '/bin/bash' ls 0493.pdf fic1.txt ... cat /etc/passwd root:x:0:0:Compte administrateur local:/root:/bin/bash ... |
Limiter les commandes utilisable
Le couple de clé généré est, nous l’avons déjà dit, destiné à sauvegarder les données du serveur « SRV » au travers du réseau. La commande qui sera passée au serveur à sauvegardé sera donc toujours la même et, pour des raisons de sécurité, il est préférable de n’autoriser le lancement QUE de cette commande. Malheureusement, SSH ne dispose pas d’un système de restriction nous permettant de sélectionner les commandes lancées sur une connexion. En revanche, l’option command= »string » lance automatiquement UNE commande à chaque connexion utilisant le couple clés privée/publique auquel elle est appliquée.
Par exemple :
## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>) from="mafalda.rez0.lan",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="ls" ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde |
retourne le retour de « ls » quelque soit les paramètres passés lors de la connexion :
fhh@mafalda ~ $ ssh srvtobackup1 'cat /etc/passwd' 0493.pdf fic1.txt ... fhh@mafalda ~ $ ssh srvtobackup1 'cat /bin/bash' 0493.pdf fic1.txt ... |
Pour restreindre l’accès à une commande autorisées, nous lançons un script shell, dès l’établissement de la connexion, qui examine la chaîne de caractère passée en argument à SSH, la valide (afin d’éviter une attaque par injection, ex : si « ls* » est seul autorisé, la commande « ls ; /bin/bash » l’est aussi), et, si elle est valide l’exécute.
Voici une proposition de script :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!/bin/bash # Commande autorisée : AUTHORIZED_CMD="ls /tmp/" # Validation de la commande : case "$SSH_ORIGINAL_COMMAND" in # Si elle contient des caractère sensible, on la logue, on la rejette # et on sort : *\&* | *\(* | *\{* | *\;* | *\<* | *\`* | *\|* ) logger "BAD SSH SEQUENCE : \"$SSH_ORIGINAL_COMMAND\"." ; echo "Rejected" ; exit 1 ; ;; # Si la commande autorisée match, elle est exécutée et sort : ${AUTHORIZED_CMD}) logger "SSH EXECUTING \"$SSH_ORIGINAL_COMMAND\"" ; $SSH_ORIGINAL_COMMAND ; exit $? ; ;; *) # Tout autre commande est rejetée et loguée : logger "BAD SSH SEQUENCE : \"$SSH_ORIGINAL_COMMAND\"." ; echo "Rejected" ; exit 1 ;; esac # Si on en arrive là, il y a un problème : logger "ERROR SSH : \"$SSH_ORIGINAL_COMMAND\"" ; echo "Error" exit 1 ; |
Télécharger le script « ssh-validation ».
Qui donne à l’exécution :
fhh@mafalda ~ $ ssh srvtobackup1 'ls /tmp/' conftest19483 test fhh@mafalda ~ $ ssh srvtobackup1 'ls -al /tmp/' Rejected |
et dans les logs :
... Sep 17 19:41:11 srv logger: SSH EXECUTING "ls /tmp/" ... Sep 17 19:41:14 srv logger: BAD SSH SEQUENCE : "ls -al /tmp/". ... |
Ce script n’est qu’une base, toute proposition d’amélioration est la bienvenue.