SSH : Secure Shell


A l'heure actuelle, la totalité des distributions GNU/Linux fournissent aussi bien le serveur que le client SSH. Du fait de cette grande diffusion, un certain nombre de documentations ont été écrites, aussi bien en français que dans toutes les autres langues. Il s'agit souvent, malheureusement, de papiers très théoriques, et l'utilisateur n'est guère avancé quant à l'utilisation effective de SSH.

Nous allons, avec cet article, tenter d'aborder l'aspect pratique de la mise en uvre d'un serveur
sshd ainsi que l'utilisation du client et des divers éléments de contrôle. Mais avant d'entrer dans le vif du sujet, passons tout de même par la case présentation, histoire de voir de quoi on parle.


SSH
SSH est un logiciel fournissant des fonctionnalités semblables à rlogin, rsh, rshd et rcp, mais dont les connexions entre les machines cliente(s) et serveur sont chiffrées. Le principal problème de ces équivalents historiques était de transmettre toutes les informations en clair sur le réseau (LAN ou Internet). Ceci ouvrait la porte à des attaques très importantes, puisqu'il suffisait à l'attaquant d'écouter le réseau avec un utilitaire adéquat (comme le simple tcpdump) pour non seulement assister en direct à tous les échanges entre clients et serveurs mais également, par la même occasion, voir tous les mots de passe transiter.

rlogin, rsh et rcp ne sont pas les seuls programmes à procéder de la sorte ; la majorité des protocoles traditionnels échangent toute information en clair sur le réseau. C'est le cas de FTP, HTTP, POP3, IMAP, NFS et tant d'autres. De base, SSH permet de remplacer les utilitaires fournissant une connectivité à distance pour le shell. Nous verrons plus loin dans cet article qu'il est parfaitement possible, grâce à SSH, de sécuriser des protocoles déjà existants.

Nous l'avons dit, SSH chiffre la communication pour éviter les écoutes passives. Mais SSH apporte d'autres fonctionnalités très intéressantes en termes de sécurité. Il propose par exemple un système d'authentification des machines en présence. Normalement, une machine est identifiée par une adresse ou un nom. Malheureusement, ces informations peuvent facilement être utilisées par un attaquant pour faire croire que sa machine est l'une des deux autorisées (client ou serveur). SSH permet d'ajouter une couche d'authentification en identifiant les parties en présence à l'aide d'une clef. Ainsi, si usurper une adresse ou un nom de machine est quelque chose de relativement facile, obtenir une clef est presque impossible.

Concernant le logiciel lui-même, SSH est originellement un logiciel propriétaire, certes libre d'utilisation dans un but non-commercial, mais cela n'est pas suffisant dans une optique qui est celle que nous défendons. Voilà pourquoi la quasi totalité des utilisateurs préfèrent OpenSSH, qui est une implémentation Libre (licence BSD). OpenSSH repose entièrement sur une bibliothèque de fonctions nommée OpenSSL et utilisable sous les termes d'une licence de type Apache.

OpenSSL contient tous les éléments cryptographiques nécessaires au fonctionnement d'OpenSSH.


Protocoles
Le protocole SSH existe en deux versions majeures. SSH1, le premier (historiquement) se décline en deux sous-versions notées 1.3 et 1.5. L'autre version du protocole, SSH2, est plus récente et corrige également quelques erreurs de conception. Sans rentrer dans le détail, SSH1 utilise un CRC (somme de contrôle) pour assurer l'intégrité des données transmises. Ce procédé étant trop faible, SSH2 l'a remplacé par un autre algorithme nommé HMAC. Autre changement majeur, SSH1 était monolithique alors que SSH2 divise le protocole en couches qui sont documentées dans des RFC différentes.

OpenSSH supporte aussi bien SSH1
(1.3 et 1.5) que SSH2 dans sa version la plus récente (OpenSSH 2.9.9).


Mise en uvre
Après cette brève introduction théorique, passons au côté pratique et commençons par installer les éléments nécessaires à OpenSSH dont la bibliothèque OpenSSL. Bien que certaines distributions possèdent un système de packaging extrêmement performant (comme la Debian), il est plus efficace que compiler vous-même les éléments dont vous avez besoin. Il est très important d'utiliser les toutes dernières versions disponibles car des bogues et des failles de sécurité (importantes ou non) sont découverts régulièrement.

Vous pourrez récupérer les sources mais également des packages pour votre distribution sur le serveur officiel :
www.openssl.com. Ici, nous considérerons une installation à partir des sources. Décompressez l'archive comme d'habitude avec :

$ tar xfzv openssh-2.9.9p2.tar.gz

Notez qu'une archive openssl-engine-0.9.6b.tar.gz est présente sur le serveur officiel. Il s'agit d'un module supplémentaire permettant le support de certains périphériques cryptographiques (CryptoSwift, Compaq Atalla et nCipher CHI pour le moment). Considérez ce module comme expérimental, bien que très stable. Ne possédant pas un seul des périphériques en question, nous n'avons pas procédé à des tests. Peut-être en parlerons-nous en un futur article.

Pour configurer et compiler les sources, nous utilisons le script fourni permettant de définir le type de plate-forme et le compilateur à utiliser :

$ ./config
$ make
$ su
$ make install
$ ldconfig
$ exit

Dans le doute, assurons-nous que tout est correctement installé et fonctionne :

$ /usr/local/ssl/bin/openssl version
OpenSSL 0.9.6b 9 Jul 2001

Ceci fait, nous pouvons passer à la compilation et installation d'OpenSSH :

$ tar xfzv openssh-2.9.9p2.tar.gz
$ cd openssh-2.9.9p2

Ici, un script de configuration automatique autoconf/automake permet de paramétrer les sources. Parmi les options disponibles, on notera la possibilité d'utiliser un support PAM (que la documentation donne comme étant plus efficace que dans la version commerciale de SSH). Si vous désirez activer le support PAM, il vous suffira d'ajouter le paramètre --with-pam lors de l'exécution du script ./configure. Cependant, les options par défaut devraient vous satisfaire :

$ ./configure

Au terme de l'exécution du script de configuration, vous verrez apparaître à l'écran un résumé de la configuration. Tout d'abord, vous serez renseigné sur l'emplacement des binaires et des différents éléments sur le système de fichiers :

OpenSSH has been configured with the following options:
User binaries: /usr/local/bin
System binaries: /usr/local/sbin
Configuration files: /usr/local/etc
Askpass program: /usr/local/libexec/ssh-askpass
Manual pages: /usr/local/man/manX
PID file: /var/run
sshd default user PATH: /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
andom number collection: Device (/dev/urandom)
Manpage format: doc

Ensuite viendront les différents supports disponibles :

PAM support: no
KerberosIV support: no
Smartcard support: no
AFS support: no
S/KEY support: no
TCP Wrappers support: no
MD5 password support: no
IP address in $DISPLAY hack: no
Use IPv4 by default hack: no
Translate v4 in v6 hack: yes

Enfin, vous pourrez voir les configurations relatives à la compilation proprement dite :

Host: i586-pc-linux-gnu
Compiler: gcc
Compiler flags: -g -O2 -Wall -Wpointer-arith -Wno-uninitialized
Preprocessor flags: -I/usr/local/ssl/include
Linker flags: -L/usr/local/ssl/lib
Libraries: -lz -lnsl -lutil -lcrypto -lcrypt

Vous pourrez obtenir la liste complète des paramètres permettant de changer cette configuration à l'aide de l'option --help. Si vous êtes satisfait de ces éléments, vous n'aurez plus qu'à lancer la compilation avec :

$ make
$ su
$ make install
$ exit

Nous disposons à présent d'une installation fonctionnelle d'OpenSSH qui supporte aussi bien le protocole SSH1 que le SSH2.

Vous trouvez dans le répertoire
contrib des sources d'OpenSSH un certain nombre de sous-répertoires nommés avec des noms de distributions GNU/Linux. Il s'agit des scripts d'init permettant de démarrer, de stopper et de recharger le service OpenSSH automatiquement. En fonction de votre distribution, placez le script adéquat dans le répertoire correspondant à votre distribution. Veillez à vérifier dans le script que les différents chemins correspondent effectivement à ceux où sont installés les binaires OpenSSH.


Les clefs
Pour OpenSSH, qui supporte en même temps les deux protocoles (SSH1 et SSH2), il est nécessaire de passer par l'étape de création des paires de clefs publique/privée. Au terme de la procédure make install, vous avez dû voir apparaître une ligne concernant la génération de clefs. Nous allons cependant reprendre cette étape à la main afin de bien comprendre les implications sous-jacentes.

Le protocole SSH1 utilise une paire de clefs de type
rsa1, alors que le protocole SSH2 permet au choix l'utilisation de paires de type dsa ou rsa (ne confondez pas rsa et rsa1). Nous devons donc, dans un premier temps, générer une paire de clefs pour l'hôte où nous venons d'installer OpenSSH. Pour cela, nous utiliserons le bien nommée ssh-keygen :

IMPORTANT : Les paires de clefs de l'hôte ne doivent avoir AUCUNE PHRASE DE PASSE ! De plus, vous devrez préciser les chemins et les noms des fichiers à créer.

$ su
$ ssh-keygen
Generating public/private rsa1 key pair.
Enter file in which to save the key (/root/.ssh/identity): /etc/ssh_host_key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /etc/ssh_host_key.
Your public key has been saved in /etc/ssh_host_key.pub.
The key fingerprint is:
15:16:40:57:ed:98:5a:a4:bf:d4:6a:1b:49:64:cc:5e root@morgane

Nous procédons de même en générant une paire de clefs dsa et rsa pour le protocole SSH2.

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa): /etc/ssh_host_dsa_key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /etc/ssh_host_dsa_key.
Your public key has been saved in /etc/ssh_host_dsa_key.pub.
The key fingerprint is:
bc:de:e0:55:93:60:46:0c:38:4c:71:03:68:57:6e:1e root@morgane

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /etc/ssh_host_rsa_key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /etc/ssh_host_rsa_key.
Your public key has been saved in /etc/ssh_host_rsa_key.pub.
The key fingerprint is:
74:23:9e:a8:e8:26:a5:08:04:83:40:de:ab:a6:c6:85 root@morgane

Nous avons à présent toutes les clefs d'hôtes nécessaires au fonctionnement d'OpenSSH :

$ ls /etc/ssh*
/etc/ssh_host_dsa_key
/etc/ssh_host_dsa_key.pub
/etc/ssh_host_key
/etc/ssh_host_key.pub
/etc/ssh_host_rsa_key
/etc/ssh_host_rsa_key.pub

Les clefs privées ne possèdent pas de suffixe et les clefs publiques possèdent un suffixe .pub. Vous reconnaîtrez aisément les différents types de clefs par le biais du nom de chaque fichier. Notre hôte est prêt pour l'exécution du serveur sshd que nous lançons avec le script d'init adéquat (en fonction de votre distribution).

Passons maintenant à l'utilisateur. Il conviendra à chaque utilisateur de générer ses paires de clefs de la même manière que nous venons de le faire. Seule différence, il ne sera pas nécessaire de préciser un emplacement spécifique puisque les valeurs par défaut feront l'affaire. Chaque utilisateur générera les trois types de clefs (
rsa1, dsa et rsa) afin de pouvoir communiquer avec n'importe quelle implémentation récente ou non de SSH.

Voici les fichiers qui seront créés dans le répertoire personnel de l'utilisateur :
.ssh/id_dsa
.ssh/id_dsa.pub
.ssh/id_rsa
.ssh/id_rsa.pub
.ssh/identity
.ssh/identity.pub

Quelques explications sont maintenant nécessaires pour bien comprendre ce que nous avons fait. Chaque utilisateur possède une paire de clefs (peu importe leur type). Pour se connecter à un serveur sshd, il peut choisir deux façons de le faire : soit utiliser ses clefs, soit utiliser son mot de passe puisqu'il possède un compte sur la machine distante. Nous verrons plus loin les différentes manières de vous authentifier auprès du serveur et comment configurer ce dernier.


Fichiers de configuration
Il existe deux fichiers de configuration distincts, ssh_config pour le client et sshd_config pour le serveur. Chacun de ces fichiers peut être personnalisé par l'ajout ou la suppression de lignes de configuration. Le fichier de configuration du serveur doit être placé à l'endroit spécifié dans le résumé de la configuration donné à la suite du ./configure des sources. Ce fichier est commun à toute la machine et ne devra être modifié que par l'administrateur.

Le fichier de configuration du client SSH, en revanche, peut être placé dans le même répertoire, mais l'utilisateur pourra glisser dans le
.ssh de son répertoire personnel un fichier config qui écrasera les valeurs du fichier global.

Des exemples des deux fichiers de configuration sont livrés avec les sources d'OpenSSH. Il vous suffira de les placer dans le répertoire adéquat et de les éditer pour vous en servir comme base de travail.

Dans un premier temps, attachons-nous au fichier de configuration du serveur :

- La première chose à faire est de renseigner le serveur sur le port à utiliser et les protocoles SSH que nous souhaitons supporter :

Port 22
Protocol 2,1

Nous pourrions par exemple ne supporter qu'un seul protocole afin de simplifier la gestion des clients et des connexions. Un autre paramètre intéressant est :

ListenAddress <IP>

Celui-ci permet, dans le cas d'une machine possédant plusieurs interfaces réseau, de n'écouter que les connexions entrantes par l'interface possédant cette adresse IP.

- Nous définissons ensuite les fichiers où se trouvent les différentes clefs de l'hôte :

HostKey /etc/ssh_host_key
HostKey /etc/ssh_host_rsa_key
HostKey /etc/ssh_host_dsa_key

Vous reconnaîtrez sans doute les fichiers que nous avons générés avec ssh-keygen dans l'étape précédente.

- Le protocole SSH1
ne prévoit pas automatiquement de changement de clef de session en cours de connexion. Il est cependant possible de demander au serveur OpenSSH de le faire avec :

KeyRegenerationInterval 3600
ServerKeyBits 768

Nous spécifions un intervalle de temps en secondes et une taille de clef.

- Viennent ensuite des paramètres concernant l'authentification avec, dans l'ordre, le temps accordé à la procédure de login et le refus ou l'autorisation au
root de se connecter :

LoginGraceTime 600
PermitRootLogin yes

Ici, le root a parfaitement le droit de se connecter à notre serveur et nous estimons que 600 secondes sont largement suffisantes pour qu'un utilisateur ait le temps de se loguer.

- Nous entrons à présent dans le vif du sujet avec tout ce qui concerne les méthodes d'authentification des utilisateurs. Tout d'abord, nous devons choisir si, dans le cas du protocole SSH1,
nous désirons une authentification RSA. Cette ligne ne concerne que le protocole SSH1 et permet de choisir entre une utilisation des clefs (rsa1) ou une authentification par mot de passe classique :

RSAAuthentication yes

Vous vous en serez douté, un yes autorise l'authentification rsa1 alors qu'un no l'interdit.

- Voici l'équivalent pour le protocole SSH2
avec authentification par clefs rsa ou dsa :

PubkeyAuthentication yes

- Cette option qui va suivre ne devrait en aucun cas être mise à yes. Elle permet, en effet, une méthode d'authentification qui est loin d'être satisfaisante en termes de sécurité. Le principe est le même que pour le mécanisme rhost où, une fois les deux machines en présence sûres de leur identité, la connexion s'établit sans aucune vérification supplémentaire. OpenSSH, avec le protocole SSH1 ou SSH2, permet de faire la même chose de manière beaucoup plus sécurisée et surtout, avec une gestion des utilisateurs. Vous comprendrez alors que nous ne souhaitons pas faire usage de cette fonctionnalité :

RhostsAuthentication no

D'ailleurs, par la même occasion, nous ne prenons pas même le temps de lire les fichiers en cause :

IgnoreRhosts yes

Nous ne voulons pas même de la version utilisant un système rshost basé sur RSA :

RhostsRSAAuthentication no

Idem pour le protocole SSH2 :

HostbasedAuthentication no

- Nous avons parlé de l'authentification RSA (SSH1) et Pubkey (SSH2), mais dans la phase de test, en cas de problème, nous souhaitons disposer d'une solution de rabattage utilisant le bon vieux système de mots de passe :

PasswordAuthentication yes

Cependant, nous ne sommes pas assez fous pour autoriser la connexion sur des comptes ne possédant pas de mot de passe :

PermitEmptyPasswords no

- Il nous reste à configurer quelques éléments concernant les fonctionnalités à disposition après la phase d'authentification. Nous commençons par autoriser le tunneling de l'affichage X11 déporté et le display à mettre en place (voir article sur le déportage d'affichage dans le présent numéro) :

X11Forwarding yes
X11DisplayOffset 10

Toujours concernant la session alors qu'elle est déjà ouverte, l'option suivante permet, si elle est activée, d'envoyer régulièrement un message afin de tester la connexion. Ceci permet d'éviter que, si le client disparaît, la connexion reste ouverte indéfiniment :

KeepAlive yes


Côté client, le fichier
/usr/local/etc/ssh_config ou ~/.ssh/config peut parfaitement être vide. Dans ce cas, le client essayera de s'adapter au mieux aux fonctionnalités du serveur.

Donc, en principe, vous pouvez vous passer de personnaliser le fichier de configuration du client. Cependant, la structure du fichier de configuration permet d'automatiser un grand nombre d'éléments et ce, en fonction du serveur que vous allez contacter.

Le mot clef
Host suivi d'un nom de machine (tel qu'utilisé sur la ligne de commande de ssh ou de scp) définit un jeu de paramètres spécifiques à cet hôte. La portée de Host est déterminée par la présence d'une autre occurrence du mot clef ou la fin du fichier de configuration. Les caractères jokers * et ? permettent de définir des motifs. Un simple * définira une configuration globale pour tous les hôtes distants.

Imaginons que nous accédions à une machine
raven utilisant une ancienne version d'OpenSSH et une machine morgane qui utilise une implémentation du protocole SSH2. Nous aurons donc dans notre fichier de configuration :

Host morgane
         port 22
        
Protocol 2
         PubkeyAuthentication yes
         PasswordAuthentication yes

Host raven
         port 22
        
Protocol 1
         RSAAuthentication yes
         PasswordAuthentication yes

Ici, par mesure de sécurité, nous estimons que la première méthode d'authentification à tester est le mécanisme des clefs. Si cela échoue, nous nous rabattons sur le mécanisme classique à mot de passe. Bien sûr, dans un cas de mise en production, nous ne prendrions pas de telles initiatives. L'erreur ne peut être tolérée.

D'autres paramètres utiles peuvent êtres ajoutés dans ce fichier de configuration. Imaginons, par exemple, que nous n'utilisions pas la même paire de clef publique/privée avec tous les hôtes distants. Nous pouvons facilement spécifier ce genre de choses en précisant quel fichier doit être lu :

Pour
morgane :

IdentityFile ~/.ssh/morgane/id_dsa
IdentityFile ~/.ssh/morgane/id_rsa

Pour raven :

IdentityFile ~/.ssh/raven/identify

Il est ainsi possible d'organiser une arborescence complète dans le répertoire ~/.ssh afin de garder une certaine cohérence dans la configuration, tout en n'utilisant pas les mêmes clefs pour tous les hôtes distants. Un autre paramètre intéressant vous permettra de définir un utilisateur pour la connexion ssh :

User moimeme

La syntaxe de connexion du client
ssh prend en effet un paramètre -l utilisateur spécifiant le compte distant à utiliser. Il est également possible de le spécifier directement dans le nom de la machine à la manière d'une adresse email : utilisateur@machine. Ce paramètre User vous évitera d'utiliser le paramètre -l sur la ligne de commande si votre compte distant n'est pas le même que sur la machine locale.


Les paramètres en ligne de commande
Le client ssh utilise la configuration fournie dans l'ordre suivant :

1 - les paramètres en ligne de commande ;
2 - les informations spécifiques à l'utilisateur du fichier
~/.ssh/config ;
3 - la configuration globale du système dans le fichier
/usr/local/etc/ssh_config.

Nous pouvons donc à tout moment surpasser les informations des deux fichiers de configuration en fournissant des arguments sur la ligne de commande. Voici quelques-uns des paramètres utilisables :

-i renseigne sur le fichier de clef à utiliser (équivalent du IdentityFile) ;
-v permet d'activer le mode bavard (nous verrons plus amplement l'utilité de ce paramètre dans le paragraphe traitant de la résolution des problèmes) ;
-l précise le nom du compte distant à utiliser si celui-ci n'est pas le même qu'en local ;
-1 ou -2 permettent de forcer respectivement l'utilisation du protocole SSH1 ou SSH2 ;
-F permet de spécifier un fichier de configuration alternatif ;
-x et -X permettent respectivement de désactiver ou d'activer le tunneling X11 (affichage X déporté).


Connexion par mot de passe
Ici, pas grand-chose à dire ou faire. Configurez simplement PasswordAuthentication à yes dans sshd_config et dans votre ssh_config, et le tour est joué. Lancez votre client ssh ainsi :

$ ssh utilisateur@machine

ou

$ ssh machine

Si le compte est identique, saisissez votre mot de passe normal.
Cette méthode d'authentification n'apporte pas d'autre avantage que d'être compatible avec la méthode
rlogin ou rsh et ce, avec une communication chiffrée.


Connexion par paires de clef
Qu'il s'agisse du protocole SSH1 ou SSH2, il est possible de s'authentifier auprès du serveur en utilisant les clefs que vous avez générées en début d'article. Chaque paire est composée d'une partie privée et d'une partie publique.

Le système de clefs asymétriques repose sur un principe simple :

Ce qui est chiffré avec la clef publique ne peut être déchiffré qu'avec la clef privée correspondante. Il n'est pas possible (dans un temps humainement calculable) de dériver la clef privée à partir de la clef publique.

Pour bien comprendre le schéma de fonctionnement, il suffit de connaître le dialogue qui s'établit lors de la connexion du client sur le serveur :

Avec le protocole SSH1, le client va se connecter au serveur. Ce dernier va chercher dans un fichier spécifique une clef publique correspondant au client. Il va alors lui envoyer un défi en chiffrant un nombre aléatoire avec la clef publique en question.

Le client va la recevoir et déchiffrer le message pour obtenir le nombre aléatoire en clair qu'il renverra au serveur. Si le serveur, en comparant le nombre aléatoire d'origine et le nombre renvoyé par le client, vérifie la similitude, le client peut se connecter.

Avec le protocole SSH2,
le système est légèrement différent, bien qu'il repose sur le même principe de clefs asymétriques. Lorsque le client se connecte au serveur, il faut négocier un identificateur de session en utilisant l'algorithme Diffie-Hellman (voir Linux Mag 30). Cet algorithme permet de ne faire circuler à aucun moment l'identifiant de session sur le réseau. Un espion écoutant la communication ne pourra pas déduire l'identifiant sans résoudre une équation extrêmement complexe. Cet identifiant est un nombre que le client va alors signer avec sa clef privée. Le serveur, dès réception de cette signature, va la vérifier à l'aide de la clef publique du client dont il dispose. Si la signature est bonne, le client peut ouvrir un shell distant.

Dans les manipulations de configuration, l'utilisation de l'un ou l'autre des protocoles se résume aux fichiers clefs à utiliser. Vous l'aurez sans doute compris grâce aux explications qui viennent d'être données : le serveur doit disposer de la clef publique du client.

Les clefs publiques des clients pouvant se connecter au serveur sont placées dans un fichier
~/.ssh/authorized_keys dans le répertoire personnel correspondant au compte que le client souhaite utiliser sur le serveur.

Sur le poste client, l'utilisateur dispose normalement (s'il a généré les trois types de paires de clefs) de trois fichiers portant un suffixe
.pub dans son répertoire ~/.ssh. Il s'agit des clefs publiques associées à ses clefs privées. Le nom des fichiers fournit une indication sur le type de clef. id_dsa.pub, id_rsa.pub et identity.pub sont respectivement les clefs publiques de type dsa et rsa pour SSH2 et rsa1 pour SSH1.

Pour que le client puisse se connecter en utilisant sa clef, il suffit de placer le contenu de l'un de ces fichiers dans le
authorized_keys du serveur. Ainsi, lors de la connexion, le serveur pourra vérifier l'identité du client.

Prenons un exemple pratique, soit les fichiers de configuration suivants :

Sur le serveur

Port 22
Protocol 2
HostKey /etc/ssh_host_key
HostKey /etc/ssh_host_dsa_key
HostKey /etc/ssh_host_dsa_key
LoginGraceTime 600
PermitRootLogin yes
PubkeyAuthentication yes
RhostsAuthentication no
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PasswordAuthentication no
PermitEmptyPasswords no
X11Forwarding yes
X11DisplayOffset 10
KeepAlive yes

Sur le client

Host *
PubkeyAuthentication yes
IdentityFile ~/.ssh/id_dsa
IdentityFile ~/.ssh/id_rsa
Port 22
Protocol 2

Nous utilisons un protocole SSH2 (Protocol 2) et souhaitons une authentification par paires de clefs. Notez que nous avons délibérément mis PasswordAuthentication à no afin que la seule méthode d'authentification utilisable soit l'utilisation des clefs. Dans la configuration du client, nous paramétrons dans le même esprit sans oublier de spécifier nos fichiers de clefs.

L'étape suivante consiste tout simplement à copier le contenu d'un des fichiers de clef publique (suffixe
.pub) dans le fichier authorized_keys du serveur. La clef publique d'un client peut parfaitement être envoyée en clair, par email par exemple, à l'administrateur du serveur. En effet, comme son nom l'indique, seule la clef privée doit rester secrète pour garantir la sécurité du système.

ATTENTION : Il est important de faire le point sur un élément très important à propos des clefs privées. Alors que la clef publique peut être facilement échangée par des méthodes tout à fait classiques, la clef privée doit être protégée avec la plus grande attention. Lors de la génération des paires de clefs, l'utilitaire ssh-keygen vous a demandé de saisir une phrase de passe. Cette phrase protège votre clef privée. Vous pourriez parfaitement vous abstenir d'utiliser cette protection en utilisant une phrase de passe vide. Cependant, il faut bien comprendre les implications d'un tel choix :

1 - Avec un simple mot de passe, vous courrez le risque que celui-ci soit deviné (s'il est mal choisi) ou que, plus simplement, quelqu'un vous observe en train de le saisir.
2 - Avec une clef privée sans mot de passe, une personne ayant accès à votre compte peut copier la clef et s'en servir pour accéder à votre compte sur le serveur SSH. En clair, le simple fait que votre clef arrive entre de mauvaises mains compromet la sécurité, c'est-à-dire si votre ordinateur client est visité.
3 - Avec une clef privée protégée par une phrase de passe, il faut à l'attaquant non seulement accéder au fichier de clefs pour voler la clef privée, mais il lui faut également trouver la phrase permettant de l'utiliser.

Maintenant, tout dépend de ce que vous souhaitez mettre en uvre. L'utilisation de clefs privées sans phrase de passe doit être limitée aux cas où vous souhaitez automatiser une procédure de transfert de fichiers ou un accès aux serveurs. En effet, il n'existe qu'un seul moyen d'utiliser une phrase de passe dans une procédure automatique :
ssh-agent. Cet utilitaire permet, entre autres choses, de saisir la phrase de passe à votre place. Nous en parlerons plus loin dans l'article.

Cet exemple peut facilement être adapté à l'utilisation du protocole SSH1
en remplaçant les entrées correspondantes dans les fichiers de configuration. Les manipulations de copie de clefs publiques sont identiques.

Dernière précision, il est possible de configurer plusieurs fichiers
authorized_keys distincts. Il suffit pour cela d'utiliser le mot clef AuthorizedKeysFile dans le fichier de configuration du serveur sshd. Un certain nombre de caractères servent de caractères de remplacement. Ainsi, %u sera complété avec le nom d'utilisateur et %h par le répertoire personnel de l'utilisateur en question. Cela permettra une gestion plus souple que les fichiers authorized_keys placés dans les différents répertoires des utilisateurs.


Un petit mot sur rhost
Nous en avons déjà parlé, l'authentification utilisant rshost n'est pas recommandée. Cependant, ceci peut servir comme un atout supplémentaire pour s'assurer de l'identité des deux machines en présence. Nous avons généré en tout début d'article des paires de clefs pour la machine. Celles-ci servent à identifier clairement le serveur dans une utilisation classique.

En vous connectant pour la première fois à un serveur SSH, vous risquez de voir apparaître le message suivant :

The authenticity of host '193.252.208.169 (193.252.208.169)' can't be established.
RSA key fingerprint is 74:23:9e:a8:e8:26:a5:08:04:83:40:de:ab:a6:c6:85.
Are you sure you want to continue connecting (yes/no)?

Il vous faudra, en principe, téléphoner à l'administrateur du serveur pour qu'il vous confirme l'empreinte (fingerprint) de la clef RSA. Dans la pratique, cela est assez rare. L'administrateur récupérera le fingerprint avec :

$ ssh-keygen -l -f /etc/ssh_host_rsa_key
1024 74:23:9e:a8:e8:26:a5:08:04:83:40:de:ab:a6:c6:85 /etc/ssh_host_rsa_key.pub

A partir du moment où vous acceptez la clef du serveur (en répondant yes à la question), celle-ci sera stockée dans un fichier ~/.ssh/known_hosts regroupant les clefs des hôtes connus.

Si, lors d'une prochaine connexion, la clef transmise par le serveur ne correspond pas à celle du fichier
known_hosts, un message d'avertissement bloquera la tentative de connexion. Un changement de clefs peut provenir du fait que l'administrateur du serveur SSH ait généré de nouvelles clefs, mais surtout que quelqu'un essaie de détourner votre connexion dans le but d'une attaque de type Men In The Middle (voir le Linux Mag hors série numéro 8).

Voici un exemple d'avertissement de ce type :

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA1 host key has just been changed.
The fingerprint for the RSA1 key sent by the remote host is
14:2a:17:b7:61:c1:41:f4:2d:54:b0:53:ae:a2:e4:76.
Please contact your system administrator.


L'agent d'authentification
Si vous utilisez SSH plusieurs fois par jour, il est parfois pénible d'avoir à saisir la phrase de passe à chaque connexion. Dans ce cas, vous pouvez solutionner le problème en utilisant l'agent d'authentification. ssh-agent est un programme qui se charge de faire ces manipulations à votre place.

Le principe est le suivant : lors de votre tout premier login sur votre machine, l'agent d'authentification est lancé. Vous pouvez alors transmettre vos différentes clefs à ce dernier avec la commande
ssh-add. Si les clefs sont protégées par un mot de passe, ssh-add vous les demandera et les transmettra à l'agent.

Il est important de noter qu'en tuant l'agent avec
ssh-agent -k, il perdra toutes les clefs qu'il possède. C'est d'ailleurs le but : aucune clef ou phrase de passe n'est stockée sur le système de fichiers et les données ne sont valables que pour une seule session.

Ainsi, durant toute la durée de votre session sur la machine locale, vous profiterez des services fournis par l'agent, mais attention : laisser votre poste sans surveillance présente un danger important pour la sécurité. Si l'agent est en cours d'exécution, n'importe qui peut accéder aux serveurs SSH sans avoir à saisir votre phrase de passe.

L'utilisation de l'agent
ssh est plus sûre que la mise en uvre de clefs sans protection par phrase de passe, mais cela ne me semple pourtant pas suffisant. Par mesure de sécurité et en fonction de l'endroit d'où vous vous connectez, il est préférable de prendre la peine de saisir manuellement vos phrases de passe.

Lors de son lancement, l'agent d'authentification vous fournira plusieurs variables d'environnement qui seront utilisées par
ssh et ssh-add :

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XXcbVSOc/agent.19446; export SSH_AUTH_SOCK;
SSH_AGENT_PID=19447; export SSH_AGENT_PID;
echo Agent pid 19447;

Avec la commande ssh-agent sans argument, vous obtiendrez les différentes déclarations de variables d'environnement à utiliser (un simple copier/coller fera l'affaire). Une solution plus simple consiste à utiliser le paramètre bash qui vous lancera un shell bash ou X qui lancera votre session XFree86.


Tunneling SSH
En plus de fournir l'équivalent des commandes rcp, rlogin et rsh de manière chiffrée avec une authentification bien plus sécurisée, les protocoles SSH permettent la mise en uvre du tunneling de manière relativement simple. Lorsque que vous ouvrez une session sur un hôte ssh, vous pouvez également ouvrir un canal de communication sécurisé pour tous les autres protocoles.

Il est indéniable que la plupart des protocoles envoient les informations en clair sur le réseau. L'astuce ici est de se servir du canal ouvert par
ssh pour encapsuler les informations en clair et les faire transiter d'une machine à l'autre.

Prenons un exemple concret avec un serveur POP3. Celui-ci est par exemple accessible avec
telnet sur le port 110 :

$ telnet machine 110

On utilise alors les commandes POP3 pour s'authentifier (login et mot de passe) sur le serveur et lister le contenu de la boîte POP3 sur le serveur distant. Le problème est que tout ce que vous allez taper et lire sur votre session telnet peut être espionné par un autre utilisateur. Pire encore, on peut avoir détourné le flux de données vers une autre machine en vous laissant croire que vous vous connectez réellement à votre serveur POP3 habituel.

La technique consiste alors à utiliser SSH pour faire transiter ces informations. Une fois la connexion établie, un port arbitrairement choisi sur la machine locale sera utilisé pour la communication. Les informations circulant sur ce port seront prises en charge par SSH et transmises au serveur SSH distant qui les communiquera au serveur POP3 en local. Si cela vous semble complexe, l'exemple suivant va immédiatement clarifier les choses :

Dans un premier
xterm, lancer la connexion ssh :

$ ssh -L 4000:machine:110 machine

-L est ici le paramètre important (L comme Local) ; nous spécifions que nous voulons utiliser le port 4000 de la machine en local comme point d'accès sécurisé vers machine sur le port distant 110.

Nous répétons
machine pour établir la connexion. Selon votre procédure d'authentification, entrez votre mot de passe ou votre phrase de passe (ou rien du tout). Dès lors, tous les logiciels qui accéderont à localhost:4000 accéderont en fait de manière sécurisée à machine:110.

Vous pouvez faire le test très simplement en ouvrant un
telnet dans un autre xterm de cette manière :

$ telnet localhost 4000

Vous accéderez effectivement au serveur POP3 distant au détail près que tout passe par SSH, est donc chiffré et "inespionnable".

De la même manière, à partir du serveur POP3, vous pouvez permettre à un client SSH de faire de même. Le paramètre devient
-R (comme Remote):

$ ssh -R 4000:machine:110 machine

La syntaxe est la même, mais à ce moment-là, vous permettrez à l'utilisateur sur machine d'utiliser localhost:4000 pour accéder à votre serveur POP3 de manière sûre.


Résolution des problèmes
Il est fort probable qu'en installant et en utilisant pour la première fois OpenSSH (ou toutes autres implémentations), vous vous mélangiez les pinceaux entre les différents paramètres et protocoles. Dans la majorité des cas, l'utilisation du mode bavard est suffisant pour immédiatement repérer le problème. Ajoutez alors simplement le paramètre -v sur la ligne de commande de ssh pour voir apparaître la plupart des informations concernant la connexion. Si cela n'est pas suffisant, vous pouvez répéter l'argument plusieurs fois afin d'augmenter le niveau d'information à afficher.

Une autre solution consiste à configurer, côté serveur cette fois, quelques lignes dans le fichier de configuration
sshd_config. Vous afficherez ainsi toutes les informations utiles dans le journal d'activité système :

SyslogFacility AUTH
LogLevel INFO

SyslogFacility permet de choisir le type de message à employer (DAEMON, USER, AUTH, LOCAL0 à LOCAL7) et LogLevel spécifie le niveau d'information à mettre dans le log (QUIET, FATAL, ERROR, INFO, VERBOSE ou DEBUG). En phase de résolution de problème, c'est bien sûr DEBUG qui est à utiliser.

Dernier point important : nous avons rencontré des problèmes sur une machine utilisant GCC en version 3.0. Les symptômes se résumaient à l'impossibilité de saisir la phrase de passe en utilisant le protocole SSH2 (clefs
dsa ou rsa). Il n'y avait aucun souci avec SSH1 ou l'authentification par mot de passe. Ce problème a été signalé très récemment sur la liste de diffusion OpenSSH et concernerait un bogue dans le compilateur GCC 3.0. Le problème ne concerne pas directement OpenSSH mais les bibliothèques OpenSSL. Si ces dernières ont été compilées avec GCC 3.0, le problème surgit dans OpenSSH qui, lui, peut être compilé avec n'importe quelle version de GCC. Après vérification, nous en sommes arrivés aux mêmes conclusions. Par conséquent, si vous utilisez un GCC 3.0, il vous faudra compiler OpenSSL avec l'ancienne version stable (GCC 2.95.3).


Faciliter les choses avec le port forwarding
Si vous utilisez SSH dans un environnement professionnel pour accéder à votre machine personnelle à la maison (et inversement), il est fort probable que vous aurez à faire face au problème du firewall. En effet, pour vous connecter de votre lieu de travail à la maison, vous devrez sans doute vous connecter à la machine NAT chez vous pour ensuite rebondir sur votre station de travail. Cela devient rapidement très pénible.

Mais vous pouvez contourner ce problème grâce au port
forwarding. La technique consiste, sur la machine passerelle, à détourner les connexions entrantes sur un port spécifique vers une autre machine (du réseau local) sur le port ssh (22).

Voici un premier exemple sur une machine utilisant un kernel de la série 2.2 :

$ ipmasqadm portfw -P tcp -L xxx.xxx.xxx.xxx 2222 -R 192.168.0.25 22

Nous utilisons ici le module portfw (port forward) pour détourner toutes les connexions arrivant sur xxx.xxx.xxx.xxx:2222 vers 192.168.0.25:22 en protocole TCP.

Voici la version kernel 2.4 :

$ iptables -t nat -I PREROUTING -p tcp -i eth0 --dport 2222 -j DNAT --to 192.168.0.25:22

Les paramètres sont plus ou moins les mêmes, à la différence que nous pouvons préciser ici l'interface et non pas l'IP, ce qui peut être très avantageux dans le cas d'une connexion Internet avec un IP fourni dynamiquement par le provider.

Vous n'aurez plus, ensuite, qu'à préciser le port
2222 pour la connexion avec le paramètre -p pour ssh et -P pour scp. Je tiens ici à remercier Galadril et psike du chan #parinux pour ses informations.

Et voilà, les informations pratiques de cet article devraient vous permettre de faire vos premiers pas avec OpenSSH. Un certain nombre de sujets n'ont pas été couverts comme SFTP
(un FTP sécurisé SSH), mais vous trouverez sans doute facilement les informations dans les pages de manuel des différents utilitaires OpenSSH.


Liens
OpenSSL
http://www.openssl.com

OpenSSH
http://www.openssh.org

Implémentation propriétaire de SSH
http://www.ssh.com/

L'article sur SSH de Bernard Perrot dans le Linux Magazine hors série 8

Le livre sur SSH à paraître premier semestre 2002 chez O'Reilly

Le site de référence pour être tenu à jour des failles découvertes dans SSL/SSH
http://www.securityfocus.com
Copyright (c) Linux Magazine France
Permission vous est donnée de distribuer des copies exactes de cette page tant que cette note de permission et le copyright apparaissent clairement.