SSH

De Justine's wiki
Aller à la navigation Aller à la recherche


Présentation de SSH

SSH est un protocole de conneixon sécurisée entre un client et un serveur. Il permet de chiffrer les communications. Plusieurs outils implémentent ce protocole, parmi lesquels OpenSSH est le plus répandu.

Initialement, avant l'arrivée de SSH on utilisait le protocole telnet qui n'est pas chiffré; cela posait problème. Quelques tentatives de telnet chiffré ont eu lieu mais n'ont pas abouti. SSH arriva en 1995, inventé par un finlandais qui fonda la société SSH Communications Security pour en tirer profit. Initialement libre, cette version devint de plus en plus propriétaire. Elle finit par être forkée par l'équipe d'openBSD, qui créa alors OpenSSH.

Elle a continué d'évoluer; elle est très largement déployée. L'équipe de dev d'OpenBSD conçoit deux versions : une pour OpenBSD et une mutliplateforme "dite portable". Les version portables comportent la lettre "p". En 2006, la version SSH2 fut standardisée par une équipe de l'IETF.

Les outils

Une installation classique comporte plusieurs outils :

  • Le client SSH : qui sert à se connecter
  • Le serveur SSHd : le daemon SSH n'est que rarement installé par défaut.
  • SCP : L'outil de copie de fichiers en ligne de commandes (acronyme de SSH Copy)
  • SFTP : Plus pratique à utiliser que SCP, il s'appuie sur FTP (ne pas confondre avec TFTP!).
  • ssh-keygen : L'outil de création et de gestion des clefs ssh
  • ssh-add : l'agent SSH, qui garde en mémoire les clefs privées chargées.

Les fichiers de configuration

Côté serveur

Sur la plupart des serveurs, le fichier de configuration se trouve dans /etc/ssh/sshd_config

Le D est pour Daemon. Par ailleurs côté serveur, pour chaque compte utilisateur la ou les clefs publiques doivent être stockées dans un fichier authorized_keys situé dans son dossier home. Par exemple, avec mon utilisatrice justine j'ai : /home/justine/.ssh/authorized_keys.

Côte client

Il se trouve dans /etc/ssh.ssh_config (sur une machine client et serveur à la fois, on a deux fichiers à ne pas confondre).

Chaque client peut apporter des ajustements à sa configuration SSH en créant un fichier nommé config et qui est dans son propre dossier .ssh :

/home/justine/.ssh/config

Celui-ci peut contenir les mêmes directives que celles du fichier de configuration client global, par exemple:

  • ForwardAgent yes : Ici l'agent SSH accompagnera nos connexions de poste en poste (si je fais du ssh de A vers B, puis de B vers C, etc). Si les directives ForwardAgent des postes A et B sont sur yes alors les clefs SSH seront utilisées avec l'agent pour toutes ces connexions.
  • PasswordAuthentication yes : On peut refuser l'authentification par mot de passe, auquel cas il faudra utiliser des clefs.
  • CheckHostIP yes : vérifie l'IP du serveur par sécurité.
  • StrictHostKeyChecking ask : Vérifie que l'hôte est connu.

Le fichier peut aussi contenir des directives pour chaque hôte auquel le client se connecte : alias, paramètres, etc... Par exemple :

ForwardAgent yes
ForwardX11 no
ForwardX11Trusted yes

host serveur1
   hostname 192.168.0.70
   user toto

host serveur2
   hostname 192.168.0.71
   port 2233
   user root

host serveur3 mon_serveur
   user root

Les logs

Le fichier de log du serveur est dans /var/log/auth.log.

On peut facilement voir les attaques de force brute avec la commande :

grep -i invalid /var/log/auth.log

Le niveau de verbosité du log est reglé dans le fichier de config par la directive LogLevel. Par défaut elle est sur INFO mais on peut la rendre plus verbeuse.


Connexion

La connexion se fait avec ssh user@serveur. On peut faire ssh serveur pour essayer de se connecter avec l'utilisateur actuel.

Connexion via un port non-standard :

La syntaxe est :

ssh user@ip -p port

Par exemple :

ssh justine@127.0.0.1 -p 2222

Knownhosts et identification

Pour éviter le spoofing, il est necéssaire de s'identifier et d'identifier les serveurs auxquels le client se connecte. Pour cela, le client va noter l'empreinte digitale du serveur dans un fichier auquel il accèdera à chaque fois qu'il se connectera sur le serveur. Il la comparera ensuite à chaque connexion. L'idéal est donc, avant la première connexion, de noter l'empreinte digitale du serveur afin de pouvoir l'accepter sans crainte. Par la suite, on sera alerté si elle change.

Pour connaître l'empreinte du serveur SSH il faut s'y rendre une première fois et noter le résultat de la commande:

ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub

Ici on prend l'empreinte de la clef RSA. On peut aussi prendre celle de la clef dsa :

ssh-keygen -lf /etc/ssh/ssh_host_dsa_key.pub

On obtient alors une longue suite de caractères hexadécimaux que l'on comparera avec la valeur donnée à la première tentative de connexion. L'utilisation de ces empreintes est un mécanisme de protection contre les attaques mitm. Cette empreinte est en réalité issue de la clef publique du serveur, obtenue en hachant une clef publique, à laquelle elles se rapportent.

Pour purger une ancienne empreinte digitale :

ssh-keygen -R @ipAncienServeur

 

En pratique

La première fois que l'on se connecte au serveur, on nous demande d'accepter son empreinte digitale. Il faut alors noter quelle empreinte est utilisé : RSA, DSA, ECDSA...

Ici, je vais partir du principe que l'on utilise une clef ECDSA.

Côté client on lance la commande :

ssh-keyscan -t ecdsa <@IPserveur>

On aura alors la clef publique du serveur.

Sur le serveur lui-même on lance la commande :

ssh-keyscan -t ecdsa localhost

On a alors sa "vraie" clef publique; on peut la comparer avec celle donnée au client.

RÉSUMÉ DES COMMANDES

Pour avoir l'empreinte d'une clef :

ssh-keygen -lf /etc/ssh/<clef> <IP> #Sur soi-même ou une autre machine

Pour voir la clef publique en entier:

ssh-keyscan -t <typedeclef> <IP> #Sur soi-même ou une autre machine

Pour rendre le fichier Knowhosts lisible :

Modifier la directive HashKnowHosts dans le fichier ssh_config

Copie de fichiers

SCP (Ssh CoPy)

Mélange de la commande cp et de la commande ssh.

La syntaxe fondamentale est la suivante :

scp <syntaxhighlight lang="unknown">source <destination></syntaxhighlight>

La source et/ou la destination peuvent être un serveur ssh. Dans ce cas il faut l'indiquer en mettant : à la fin du nom du serveur.

scp monfichier.txt serveurssh:

Sinon, je vais juste me retrouve avec un fichier nommé serveurssh. En gros, il faut retenir que la syntaxe est:

scp /chemin/du/fichier/local destination:/chemin/souhaité/nomdufichier #Le chemin destination est facultatif, mais il vaut mieux éviter de mettre un nom...

SFTP (Simple File Transfer Protocol) (Port 22)

On peut aussi passer par SFTP pour copier des fichier avec SSH. Cela se fait comme avec FTP, sauf qu'il est plus simple: on a que le port 22 à ouvrir. On peut utiliser Filezilla, dans lequel ça marche comme du FTP normal.

 


 

Principe des clefs SSH

Il est possible de se connecter à un serveur SSH à l'aide d'un mot de passe. Ce système a des incovénients :

  • Il faut retenir autant de mots de passe que de serveurs ...
  • Le mot de passe peut être forcé ou dévoilé...
  • Et je oit taper un mot de passe à chaque connexion.

Les clefs SSH permettent de se débarrasser de ce genre d'inconvénients. SSH utilise du chiffrement asymétrique, avec un principe de clef publique et de clef privée. La clef privée doit le rester.

 

Création d'une paire de clefs.

Cela se fait avec la commande ssh-keygen. Je vais d'abord me rendre dans mon dossier ~/.ssh pour ensuite créer ma paire de clefs :

ssh-keygen

Par défaut, c'est une clef RSA. On me propose un dossier et un nom que je peut changer. Il me faut ensuite rentrer un mot de passe.  Une fois cela fait, j'ai ma paire de clefs:

  • Une clef privée , par défaut nommée: id_rsa
  • Une clef publique, par défaut : id_rsa.pub

Charger une clef privée

Pour utiliser ponctuellement une clef privée, on peut y faire appel lors de la conneixon ssh avec l'option -i suivi du fichier de clef. Par exemple :

ssh -i.ssh/clefprivee toto@serveur

Mais on va devoir le refaire à chaque fois. Il est plus intéressant d'utiliser l'agent ssh; une fois une clef chargée dans la mémoire de celui-ci, la clef y reste tant que la session est ouverte. L'agent SSH m'accompagne pendant toute ma session sur l'ordinateur, chaque fois que je me connecte à un serveur SSH il vérifie si une clef chargée en mémoire peut être utilisée. Si c'est le cas, la connexion est directe, sans mot de passe. Sinon, si la clef locale ou distante n'est pas la bonne, on passera par un mot de passe.e

On peut charger une clef privée avec ssh-add:

ssh-add ~/.ssh/maclefprivee

Copier la clef publique sur le serveur

Pour un utilisateur donné, sur le serveur SSH, la clef publique autorisée à se connecter est dans le fichier authorized_keys. Ce fichier peut contenir plusieurs clefs publique, par exemple si un seul client veut utiliser plusieurs clefs privées, ou avec une clef privée par personne, etc.

On a deux possibilités pour ça :

  • La plus simple : ssh-copy-id
  • La seconde : scp

Avec ssh-copy-id :

Pour copier ma clef publique clef.pub vers le serveur avec l'identité justine :

ssh-copy-id -i clef.pub justine@serveur

La clef publique sera alors intégrée sur le serveur, dans le fichier ~/.ssh/autorized_keys

 

Avec scp:

On peut utiliser scp mais c'est moins bien : déjà on risque d'écraser un fichier authorized_keys qui serait présent, et la commande est moins intuitive je trouve. En plus, il faut faire attention à ce que le fichier authorized_keys côté serveur soit positionné au bon endroit. Quel intérêt d'utiliser cette commande, sérieux? Enfin, la voilà quand même:

scp clef.pub paul@magma:.ssh/authorized_keys

Le fichier en lui-même

C'est la destination par défaut des clefs publiques avec OpenSSH (cela est paramétré dans ssh_config, qui doit contenir AuthorizedKeysFile %h/.ssh/authorized_keys).

 

 

D'autres commandes pour aller plus loin :

Pour charger une clef, depuis le dossier la contenant:

ssh-add

De mếme que l'on peut charger une clef dans l'agent ssh, on peut les décharger :

ssh-add -D

Pour décharger une clef en particulier:

ssh-add -d /chemin/de/la/clef

Pour lister les clefs chargées:

-L montre les clefs publiques:

ssh-add -L

-l montre les empreintes des clefs chargées:

ssh-add -l

On peut changer la passphrase d'une clef, on utilise deux arguments : -p pour indiquer un changement de mot de passe et -f pour indiquer quelle clef doit être changée:

ssh-keygen -p -f /chemin/clef/privée

Les tunnels

Principe : le protocole SSH propose de créer des tunnels chiffrés dans lesquels transitent d'autres protocoles. C'est du port forwarding; lorsqu'une connexion de transfert de port est établie, on appelle cela un tunnel SSH. SSH permet donc de sécuriser des protocoles non sûrs. Exemple tiré du cours :

RTENOTITLE

On a trois types de Port Forwarding :

  • Local : Les connexions issues du client sur un port spécifique sont transmises via le serveur SSH à un serveur destination sur un port spécifique
  • Remote : Un client distant se connecte au serveur SSH distant aussi; La connexion passe dans un tunnel vers le client local, lequel retransmet au serveur local qui est la destination finale et qui ne peut pas être accédé depuis le web.
  • Dynamic : Les connexions issues de différents programmes sont transmises via le client SSH puis le serveur SSH pour arriver au serveur de destination. 

 

SSHREMOTE.jpg

 

Créer un tunnel SSH:

Cela se passe comme une connexion normale mais en rajoutant une option -L, sur laquelle on doit préciser :

  • Un port local sur lequel on se connectera pour atteindre finalement le port du serveur visé
  • Le serveur visé
  • Son port

ssh -L port_local:host:port_distant login@serveur_ssh


Exemple

J'ai un serveur web (@IP : 18.5.1.2) que je veux rendre accessible de l'extérieur, mais seulement par une connexion via SSH; cette même machine contient aussi un serveur SSH. Pour cela, il suffit de commencer par n'autoriser dans la configuration Apache que les connexions depuis localhost, c'est-à-dire depuis la machine elle-même. Ensuite, il suffit sur cette même machine de créer un tunnel redirigeant le port 8080 vers le port 80, en lancant cette commande depuis mon client:

ssh-L 8080:localhost:80 18.5.1.2

À partir de ce moment, le tunnel est créé entre le client et le serveur web, pour accéder au serveur je n'aurais qu'à rentrer dans le navigateur de mon client la commande :http://127.0.0.1:8080.

Autre exemple : j'ai la même situation, sauf que cette fois-ci le serveur web est dans le lan (10.0.0.1) et n'est pas la même machine que le serveur SSH (1.2.3.4), je vais lancer cette commande depuis mon poste client:

ssh -L 8080:10.0.0.1:80 user@1.2.3.4

Il est possible de faire bénéficier aux autres machines du réseau du client, du tunnel ainsi créé: on utilise pour cela l'option -g lors de la commande de création du tunnel. Les autres machines du réseau du client pourront passer par lui pour se connecter au serveur.

Enfin, pour créer un tunnel dynamique:

ssh -D 8080 user@192.1.2.3

Ici, toutes les requêtes arrivant sur le client sur son port 8080 seront redirigées vers le serveur SSH (192.1.2.3), et éventuellement vers un autre serveur, web par exemple. C'est ce qu'on appelle un proxy socks : la liaison entre le client et le serveur SSH est chiffrée, mais pas celle entre le serveur SSH et le serveur web. Il faut bien garder en tête que c'est un proxy et pas vraiment un VPN.

Un exemple : j'ai mon PC (192.168.1.42), un routeur / serveur SSH (192.168.1.20 et 172.16.0.1) et un serveur web (172.16.0.10).

  • Sur mon PC, je fais : ssh -D 8080 justine@192.168.1.20
    • Tout ce qui arrive sur mon port 8080 sera renvoyé vers le serveur SSH
  • Sur mon PC, je lance Firefox et je lui rentre un proxy socks : 127.0.0.1 port 8080
  • Depuis mon PC, je peux alors accéder au serveur web, en rentrant son adresse IP.

Ce n'est ni plus ni moins qu'un proxy, un peu à l'arrache; si les tunnels et les proxy SOCKS sont utiles pour faire ce genre de choses rapidement, ça ne remplace sûrement pas un VPN ! Le tunnel n'est utilisable que vers une seule machine, et le proxy SOCKS demande de configurer un proxy, ce qui n'est pas toujours évident à faire à l'échelle d'un OS.

Gestion des tunnels gSTM

Déporter plusieurs ports d'un serveur ou plusieurs serveurs vers un client à la main peut vite devenir fastidieux. Il existe un outil graphique de gestion des tunnels SSH : gSTM. Il permet de définir plusieurs sites et pour chaque site, plusieurs paramètres de connexion et l'ensemble des tunnels.

Déport graphique

SSH permet également de déporter l'affichage graphique d'une application, lancée sur le serveur SSH, elle sera affichée sur le client. On parle alors de X11 Forwarding. Par exemple:

ssh -c blowfish -X -C -f user@serveur firefox
  • -X pour faire du déport d'affichage
  • -c blowfish: pour choisir le chiffrement utilisé pour coder l'affichage
  • -C compression gzip ou non (utile si le débit est faible)
  • -f : Détacher l'affichage du shell ssh

Ici, firefox se lancera sur le serveur SSH mais s'affichera sur le client.

Quelques outils annexes

Screen (le multiplexeur de terminaux)

Le paquet s'appelle juste "screen".

Screen est un "multiplexeur de terminaux". Il offre plusieurs possibilités :

  • Ouvrir plusieurs shell dans une console (comme terminator)
  • Ouvrir un terminal et s'en déconnecter en le laissant tourner
  • Partager un terminal entre plusieurs utilisateurs

Screen n'affiche pas les terminaux en même temps comme terminator : sur ce point là il est moins bien je trouve. Il permet simplement de passer de l'un à l'autre. Il a cependant l'avantage considérable de fonctionner sans interface graphique. Il est surtout utile avec SSH : par exemple, je peux me connecter à un serveur, lancer une instance screen et la détacher pendant qu'elle tourne en effectuant une tâche longue; ensuite je n'ai plus qu'à éteindre mon client, partir et revenir le lendemain pour la retrouver.

Screen utilise deux notions : les sessions et les écrans. Une session peut contenir plusieurs écrans. À chaque écran correspond un shell; on peut lancer plusieurs sessions sur une même machine, mais je ne vois pas trop l'intérêt à priori.

Screen nomme ses sessions en leur donnant des numéros qui n'ont pas l'air d'avoir de logique particulière. Il nomme ses écrans 0, 1, 2, 3...

Il se lance avec la commande screen.

Les commandes :

  • Créer un nouvel écran : ctrl+a puis c
  • Quitter une session sans la fermer : ctrl+a puis d
  • Reprendre un écran que l'on a détaché (sinon ça marche pas!): screen -r (préciser le numéro si on a plusieurs sessions)
  • Connaître la liste des sessions en cours : screen -ls
  • Partager une session screen (sur un autre terminal du même utilisateur): screen -x <numéro de session>
  • Connaître la liste des écrans dans une session : ctrl+a puis w
  • Changer de screen: ctrl+a puis le numéro de l'écran

Le "partage de session" ne se fait pas entre plusieurs utilisateurs UNIX : il se fait entre plusieurs shell connectés avec un même utilisateurs (c'est du multi-monitor)

LShell (Limited Shell)

LShell est un shell au même titre que bash, ksh, etc...

Il permet de proposer des directives de configuration propres à chaque utilisateur, par rapport à ce que celui-ci peut ou ne peut pas faire. Par exemple : on peut empêcher d'utiliser certains commandes, en local et/ou à distance, l'autoriser à utiliser certaines commandes sans sudo, etc... Il est surtout utile pour créer des scripts shell : là ou certains scripts shell nous obligent à stocker des mots de passe en clair à l'intérieur avec bash, avec LShell on peut modifier les droits de l'utilisateur pour qu'il n'ait le droit de faire que ce que qu'il a besoin de faire, sans avoir à utiliser sudo, par exemple.

Le fichier de config est dans /etc/lshell.conf

Voici un exemple de configuration :

''[light_user]''

''allowed :['upgrade','update']''

''aliases :{'update':'sudo apt-get update', 'upgrade':'sudo apt-get upgrade'}''

''sudo_commands :['apt-get update', 'apt-get upgrade']''

''overssh : ['update','upgrade']''

Un tel utilisateur ne pourra effectuer que deux commandes : update et upgrade, qui sont ici des alias de sudo apt-get upgrade et sudo apt-get update; ces commandes devant habituellement être lancées en tant que root, on les met dans la directive sudo_commands.

Enfin le dernier bloc, overssh, autorise l'utilisateur à exécuter ses commandes en les exécutant à travers une connexion ssh.


Documents annexes:

Les recommandations de l'ANSSI sur SSH

<pdf>Fichier:NT_OpenSSH.pdf</pdf>

 

Un article sur l'entropie :

http://www.deltasight.fr/entropie-linux-generation-nombres-aleatoires/