Problématique :
Dans un certain nombre de cas on souhaite pouvoir faire des transferts de données ou exécuter des commandes sur un serveur depuis des scripts PHP situés sur un autre serveur. Par exemple depuis un serveur B ("local"), on veut pouvoir déclencher via une interface web une sauvegarde d’une base de données d’un serveur A ("distant") puis récupérer le fichier de sauvegarde sur B. Dans ce cas il est donc nécessaire de pouvoir établir une connexion SSH entre B et A à l’aide du script PHP qui gère l’interface web de B.
Bien évidemment autant A que B ont une configuration SSH qui n’accepte pas l’authentification par mot de passe "en clair" (cf Sécurisation SSH poussée : authentification par clé RSA) : il va donc être nécessaire d’utiliser une clé publique pour l’établissement de la connexion.
Ensuite, une fois la connexion SSH établie, on peut utiliser des commandes bash sur le serveur "distant", réaliser des transferts de fichiers par SCP (ou SFTP)... le jeu de fonctions PHP disponibles est relativement vaste : fonctions shell2 de PHP, on peut aussi (ré)utiliser des scripts sh.
Pré-requis :
Il est nécessaire d’avoir créé et configuré une paire de clé SSH privée/publique selon la méthode exposée dans Sécurisation SSH poussée : authentification par clé RSA et réparties de la manière suivante :
- la machine "locale" (B), sur laquelle le script PHP de connexion est placé, doit posséder le fichier de clé privée, stocké dans un répertoire non-accessible via le web (bien sûr !) /home/mon_user/.ssh/id_rsa par exemple, avec des droits les plus restreints possibles (lecture seule obligatoirement...). Elle doit également posséder une copie du fichier de clé publique (id_rsa.pub). Pour simplifier l’explication suivante, supposons qu’elle est située dans le même répertoire que la clé privée : /home/mon_user/.ssh/id_rsa.pub
- cette machine devra avoir OpenSSH installé et PHP compilé avec la bibliothèque ssh2
- sur la machine "distante" (A) on aura un utilisateur ayant le minimum de droits nécessaires pour accomplir les opérations requises (user_B par ex pour la suite), lequel aura dans le sous-répertoire .ssh de son répertoire perso le fichier de clé publique : /home/user_B/.ssh/id_rsa.pub. Bien évidemment on aura également intégré cette clé dans la liste des clés autorisées de /.ssh/authorized_keys avec la commande :
- cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
A partir de cette configuration 3 étapes permettent d’interconnecter les 2 machines par un script PHP : (tous les extraits de code suivants sont à placer dans un fichier PHP sur le serveur B)
1re étape : établir la connexion
Pour une machine A ayant comme FQDN "machine.mon-site.tld", et utilisant le port 22 pour le SSH, le script minimum serait :
On peut faire un peu plus "riche" en fournissant un avertissement en cas de problème de connexion :
- // Notification à l'utilisateur si le serveur termine la connexion
- function ma_deconnexion_ssh($raison, $message, $language) {
- $raison, $message);
- }
2nde étape : vérifier l’identité de la machine
Si l’on veut vraiment respecter les règles de sécurité, il est maintenant nécessaire de tester si le serveur connecté est bien la machine voulue (histoire d’éviter les attaques du type "Man in the middle"...). Pour cela on va comparer "l’empreinte" retournée par le serveur connecté avec la valeur connue pour la machine A.
Commençons par récupérer cette "empreinte" pour avoir la valeur qui servira de référence par la suite :
L’affichage retourné par le echo correspond donc à la clé de référence du serveur B : par exemple pour la suite 5172E2D339863712D3D26D4860D976CD
On peut donc maintenant ajouter à notre fichier de connexion la vérification de cette clé :
- ...
- $fingerprint = '5172E2D339863712D3D26D4860D976CD';
- die ('<br />problème d\'identification du serveur: la signature reçue ne correspond pas à son empreinte enregistree!') ;
3me étape : authentification par clé publique
Pour réaliser le processus d’authentification on teste maintenant la clé privée du serveur B en fonction de la clé publique (id_rsa.pub que possède A pour authentifier l’utilsateur user_B) :
- ...
- '/home/mon_user/.ssh/id_rsa.pub',
- '/home/mon_user/.ssh/id_rsa', 'passphrase_de_la_cle_privee'))
Et ensuite ?
Une fois la connexion SSH établie sur A par le script PHP on peut :
- soit échanger des fichiers par le protocle SCP (ou SFTP) :
- // envoyer un fichier truc.local de B vers A (truc.distant)
- // télécharger un fichier machin.distant depuis A vers B (machin.local)
- soit exécuter des commandes sh sur le serveur A avec :
- $commande = 'ls -l';
- //exécution commande shell sur la machine A
- echo "<br />erreur d'execution de la commande $commande";
Si l’on veut récupérer les sorties des commandes passées (retours et/ou erreurs) http://linux.jpvweb.com/mesrecettes... propose une méthode élégante pour le faire...