Administration Unix - CM séance 18
18. Services réseau
18.1. Service ssh
Le terme ssh (Secure Shell) désigne un protocole et des outils pour effectuer des échanges sécurisés avec une machine distante.
ssh est à l'origine un produit commercial (1995) ; l'implémentation libre OpenSSH (1999) est devenue la norme.
18.1.1. Présentation
Le protocole ssh
permet :
- d'établir une console distante (commande
ssh
), - d'exécuter des commandes à distance (
ssh
), - de transférer des fichiers (
scp
,sftp
), - de rediriger un environnement graphique (
ssh -X
ou-Y
), - de véhiculer un autre protocole dans un tunnel (
ssh -L
ou-R
), - etc.
Il est décrit par des RFCs :
- 4251 architecture générale du protocole
- 4252 protocole d'authentification
- 4253 protocole de transport sécurisé
- 4254 protocole de connexion
- ... (voir fin de
man ssh
)
Les commandes principales de la famille ssh
sont :
ssh commande principale (remplace rlogin, telnet, ...)
sftp copie de fichier interactive (remplace ftp)
scp copie de fichier directe (remplace rcp)
ssh-keygen génère des clés d'identification
ssh-copy-id copie des clés d'identification
Il y a d'autres utilitaires qui s'appuient sur ssh
, par exemple :
rsync copie ou mise à jour de fichiers
autossh maintient une connexion et un tunnel ssh
Les paquets usuels sont :
openssh-client commandes ssh
openssh-server serveur ssh et configuration
rsync
autossh
La configuration se fait via plusieurs fichiers auto-documentés (il y a beaucoup de réglages possibles) :
/etc/ssh/sshd_config configuration du serveur
/etc/ssh/ssh_config connexions pour tous les utilisateurs
~/.ssh/ssh_config configuration pour un utilisateur
(raccourcis, logins, ports, etc)
18.1.2. Première connexion
Soit l'utilisatrice alice
loguée sur la machine alpha
, et qui veut se connecter
via ssh
en temps que bob
sur la machine beta
; elle tapera :
alice@alpha$ ssh bob@beta
Lors de la première connexion il y a un message :
The authenticity of host 'beta' can't be established.
ECDSA key fingerprint is SHA256:zViBXDMc/LFRWTv6BLwIcAwudYfnEa6rxWX14imXUSg.
Are you sure you want to continue connecting (yes/no)? yes
(il faut taper yes
).
Warning: Permanently added 'beta' (ECDSA) to the list of known hosts.
bob@beta$
Une "trace" numérique de la machine beta est alors rajoutée dans le fichier
~/.ssh/known_hosts
sur 1 ligne (assez longue) :
alice@alpha$ cat ~/.ssh/known_hosts
....
|1|muvGH5EqgJBxd3m+Z+DfJ4l+G3g=|k4qxnZ5gbIgXl5uDNiEI+fo92Vk= \
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA...
...5seTj1jYtA/OsYi+SbctCA9kPLQ6uQ9IZHnMJsGo=
....
Lors de chaque connexion, la trace sera comparée, pour prouver que c'est bien
la machine beta
.
Cette trace est en réalité composée de 2 parties :
- des informations (adresse IP, port, ...) hachées (pour ne pas révéler d'informations sur les adresses distantes à un attaquant éventuel) ;
-
la clé publique de la machine distante :
bob@beta cat /etc/ssh/ssh_host_ecdsa_key.pub ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA... ...5seTj1jYtA/OsYi+SbctCA9kPLQ6uQ9IZHnMJsGo= root@beta
Bien que la ligne identifiant le host soit automatiquement rajoutée par ssh
,
on peut aussi l'obtenir par :
alice@alpha$ ssh-keyscan -H -t ecdsa beta
# beta:22 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
|1|r6IPhNUs2BzFApmCIkkP6OEWCCs=|/EWjzRPS+xxaw1rBFYexBQkeI1k= \
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA...
...5seTj1jYtA/OsYi+SbctCA9kPLQ6uQ9IZHnMJsGo= root@beta
⟶ permet de scripter une mise à jour de known_hosts
(rq : la partie hachée |1|...=
change chaque fois).
Si la clé publique de beta
change (réinstallation, ...) ou est usurpée, il y
aura un message d'erreur :
bob@beta$ sudo apt purge openssh-server
bob@beta$ sudo apt install openssh-server # réinstallation
....
Creating SSH2 ECDSA key; this may take some time ...
256 SHA256:+tPdpt7VECZMysTP5/mYvqqxJBemU/iTdkAkpKlky7s root@beta (ECDSA)
....
alice@alpha$ ssh bob@beta
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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 a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:+tPdpt7VECZMysTP5/mYvqqxJBemU/iTdkAkpKlky7s.
Please contact your system administrator.
Add correct host key in /home/alice/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/alice/.ssh/known_hosts:23
remove with:
ssh-keygen -f "/home/alice/.ssh/known_hosts" -R "beta"
ECDSA host key for beta has changed and you have requested strict checking.
Host key verification failed.
Solutions conseillées :
- éditer
known_hosts
, supprimer la ligne n°23
, ou - appeler la commande
ssh-keygen
affichée ci-dessus (c'est équivalent).
Il peut y avoir plusieurs lignes incriminées, dans ce cas recommencer jusqu'à ce que ça marche.
Autres solutions :
- appeler
ssh -o StrictHostKeyChecking=no bob@beta
(aucune protection), ou - supprimer
known_hosts
(violent, on perd tous les hosts).
18.1.3. Authentification
L'authentification pour le protocole ssh
se fait soit par un mot de passe,
soit par une paire de clés (publique-privée).
-
par mot de passe : le mot de passe de l'utilisateur sur la machine distante est demandé pour chaque commande
ssh
/scp
/sftp
. C'est pénible pour l'utilisateur, et problématique pour les scripts. -
par clé : la clé publique de l'utilisateur est explicitement autorisée sur une machine distante ; l'utilisateur n'a plus besoin de s'authentifier.
Étape 1 : générer une clé
alice@alpha$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/alice/.ssh/id_rsa):
Created directory '/home/alice/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/alice/.ssh/id_rsa.
Your public key has been saved in /home/alice/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:huBCqb6v0vAxfGPGV0mpcyAJTlxSq90Ea5cRqpxJjUg alice@alpha
The key's randomart image is:
+---[RSA 2048]----+
| E+++.o. . |
|.+.=o=.oo |
|. * B.++ . |
| = O =o.+ |
|..B.o o+S |
|o +.* .. |
| = * o |
|. + |
|.oo. |
+----[SHA256]-----+
⟶ génération de
~/.ssh/id_rsa clé privée, PERSONNE ne doit accéder à ce fichier
~/.ssh/id_rsa.pub clé publique
alice@alpha$ cat ~/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
...
at2h0o3GCmd5ROlcqwAAAA50aGllbEBuYWtlZGViMQECAw==
-----END OPENSSH PRIVATE KEY-----
alice@alpha$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgM+9gAZRA1Vlt4Q5lClJFRtgFRqxwYejxIii
... gMbtIRKeG/wFA9o8h1bLpnq8+h/ alice@alpha
La clé privée et la clé publique forment un couple lié par une propriété mathématique ; la robustesse tient en ce qu'il est impossible de déduire la clé privée de la clé publique.
Il existe plusieurs types de clés, on peut le spécifier par
$ ssh-keygen -t type
où type
est parmi
dsa faible, déprécié depuis openssh 7.0
rsa par défaut, fonctionne partout
ecdsa relativement récent, non accepté partout ; clés plus courtes
ed25519 le plus récent et robuste, non accepté partout
On peut aussi spécifier la taille de la clé en nombre de bits (les choix dépendent du type) :
$ ssh-keygen -t rsa -b 4096
Une clé de chaque type peut être créée (ssh-keygen -A
), la paire sera stockée
dans les fichiers ~/.ssh/id_<type>
et ~/.ssh/id_<type>.pub
.
Compléments : on peut retrouver le hash et le randomart d'une clé publique avec
$ ssh-keygen -lvf fichier_clé.pub
et afficher le randomart d'un host à la connexion avec l'option
$ ssh -o VisualHostKey=yes user@cible
Étape 2 : recopie de la clé
La deuxième étape consiste à envoyer la clé publique de l'utilisateur sur la machine distante :
ssh-copy-id -i clé_publique [user_distant@]machine_distante
Suite de notre exemple :
alice@alpha$ ssh-copy-id -i ~/.ssh/id_rsa.pub bob@beta
Source of key(s) to be installed: "/home/alice/.ssh/id_rsa.pub"
1 key(s) remain to be installed -- if you are prompted now it is to install
the new keys
bob@beta's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'bob@beta'"
and check to make sure that only the key(s) you wanted were added.
alice@alpha$$ ssh bob@beta
Welcome to beta.
Last login: Mon Mar 8 15:24:42 2021 from alpha
bob@beta$ cat ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgM+9gAZRA1Vlt4Q5lClJFRtgFRqxwYejxIii
... gMbtIRKeG/wFA9o8h1bLpnq8+h/ alice@alpha
Remarques :
-
sur certains vieux systèmes il n'y a pas la commande
ssh-copy-id
; dans ce cas il suffit de copier à la main sa clé publique dans le fichierauthorized_keys
. -
lors de la création de la clé on peut donner une passphrase (= un mot de passe sur 1 ou plusieurs mots) ; ce passphrase est alors demandé à chaque connexion.
On peut ensuite mémoriser le mot de passe le temps d'une session avec
ssh-agent
/ssh-add
:ssh-agent
est en général déjà lancé avec la session graphique en local, c'est lui qui stocke les clés et passphrase pourssh
;ssh-add
transmet des clés/passphrase àssh-agent
:
alice@alpha$ ssh bob@beta Enter passphrase for key '/home/alice/.ssh/id_rsa': alice@alpha$ ssh-add ~/.ssh/id_rsa # ou : ssh-add Enter passphrase for /home/alice/.ssh/id_rsa: Identity added: /home/alice/.ssh/id_rsa (alice@alpha) alice@alpha$ ssh bob@beta Welcome to beta!
On peut enlever l'autorisation :
alice@alpha$ ssh-add -d ~/.ssh/id_rsa Identity removed:/home/alice/.ssh/id_rsa (alice@alpha) alice@alpha$ ssh bob@beta Enter passphrase for key '/home/alice/.ssh/id_rsa':
-
ssh-keygen
permet aussi de gérer des certificats pour des authentifications groupées.
18.1.4. Port ssh
Par défaut, le port du protocole ssh
est le port 22
.
Pour des raisons de sécurité, le port est parfois changé (c'est le cas pour le sas d'accès aux machines de TP à AMU).
Les commandes ssh
ont une option pour spécifier le port distant :
ssh -p port ...
scp -P port ... # -P en majuscule
sftp -P port ... # idem
On peut aussi spécifier le port et d'autres informations dans : (man ssh_config
)
/etc/ssh/ssh_config
~/.ssh/config
Par exemple si on a :
alice@alpha$ cat ~/.ssh/config
Host beta2
HostKeyAlias beta2 # nom utilisé dans known_hosts
HostName beta # vrai nom de la machine, pour l'atteindre
Port 22000
User bob
alors
alice@alpha$ ssh beta2
sera presque équivalent à
alice@alpha$ ssh -p 22000 bob@beta
18.1.5. Tunnel ssh
La commande ssh
permet de créer des tunnels (aussi appelés : redirections
de port, ou port forwarding).
Étant donné 3 machines A, B, C, un tunnel ssh
de A via B vers C
A <===================> B <----------------------> C
tunnel ssh crypté protocole quelconque
est un canal crypté entre A et B, tel que les paquets envoyés depuis A seront acheminés à B, puis envoyés par B à destination de C (et vice-versa).
Pour le mettre en place il faut choisir des ports :
démon
ssh sshd quelconque
A <===================> B <----------------------> C
portA portB (portB') portC
portA
est le port local, portC
est le port distant, portB
est le port
sshd
.
On peut choisir arbitrairement le port local, pourvu qu'il soit libre et > 1024.
La commande pour créer le tunel est
$ ssh -L portA:C:portC [-p portB] [user_b@]B
On peut alors appeler dans un autre terminal :
$ commande -p portA [user_c@]localhost
Comme le ssh
de la première commande est en écoute sur le portA
local, il
demandera à sshd
sur B de se connecter à C sur le portC
en temps que
user_c
, et de lui transmettre les paquets.
ssh
supporte le multiplexage : on peut faire simultanément plusieurs connexions
sur le portA
local.
On peut donc aussi "emboîter" des tunnels :
A <========> B <--------> C
A <=======================> C <--------> D
A <======================================> D <--------> E
Les tunnels ssh
sont extrêmement utiles : ils permettent
- d'accéder à des machines normalement inaccessibles via des sas ;
- de crypter des protocoles normalement en clair (attention, que la partie
matérialisée par
<====>
) ; - de créer et arrêter dynamiquement des tunnels.
Exemple 1
Connexion ssh
sur gamma
:
alice@alpha <==========> bob@beta <----------> carole@gamma
10000 22 22
Terminal 1 :
alice@alpha$ ssh -L 10000:gamma:22 bob@beta
Terminal 2 :
alice@alpha$ ssh -p 10000 carole@localhost
alice@alpha$ sftp -P 10000 carole@localhost
Exemple 2
Connexion http
(port 80) sur delta
:
alice@alpha <==========> bob@beta <----------> delta
11000 5022 80
Terminal 1 :
alice@alpha$ ssh -L 11000:delta:80 -p 5022 bob@beta
Terminal 2 :
alice@alpha$ wget http://localhost:11000/chemin/fichier
Compléments :
-
il est possible de créer des "tunnels inverses" avec
ssh -R
; -
il est possible de tunneler l'affichage X11 avec
ssh -X
oussh -Y
; -
on peut spécifier des redirections de port dans
ssh_config
; -
il est possible de créer un VPN sur
ssh
(man ssh
à la fin) ; -
la commande
autossh
permet de maintenir des tunnels et les relancer si besoin ; -
les commandes
sshfs
etfuse
permettent à un user de monter un système de fichiers distant viassh
(paquetsshfs
) :$ mkdir point_montage && sshfs [user@]hostname:[directory] point_montage $ fusermount -u point_montage && rmdir point_montage # démontage
Ne pas utiliser
sudo
devantsshfs
si on veut utiliser l'authentification par la clé publique de l'utilisateur (ce serait celle de root). -
la commande
rsync
s'appuie surssh
et permet de faire des transferts et mises à jour de fichiers et répertoires très efficaces (elle compare des dates et des empreintes MD5).
18.2. La résolution de noms
Elle permet d'associer un nom à une adresse IP.
18.2.1. Présentation
Il est possible d'associer quelques noms de machines à des adresses IP dans un fichier local ; mais au niveau de l'internet c'est impossible (taille, réseau décentralisé et changeant, répartition de charge, etc).
C'est pourquoi la résolution de nom s'appuie sur un système hiérarchique de domaines et un réseau distribué de serveurs de noms ; on appelle cet ensemble le DNS (Domain Name System, 1983).
-
Le système de noms de domaine est une hiérarchie telle que :
-
la racine est notée
.
(à la fin, souvent omise) -
le nom complet est appelé le FQDN (Full Qualified Domain Name)
machine[.sous-domaines].domaine.tld.
-
les domaines immédiatement sous la racine sont appelés domaine de premier niveau (TLD, Top Level Domain) :
.org
,.com
,.fr
, etc -
les TDL sont gérés par des organismes agréés par l'ICANN (AFNIC pour
.fr
, Verisign pour.com
, etc) -
les enregistrements de noms de domaines dans un TLD sont confiés à des sociétés agréées, appelées des registrars (Gandi, Nordnet, Ovh, ...).
-
-
Le réseau de serveurs du DNS :
-
est distribué, pour résister aux pannes et attaques, et limiter la taille de leur base de données ;
-
lorsqu'un client veut obtenir une adresse, il demande à un serveur DNS récursif, qui soit lui répond s'il a l'adresse en cache, soit demande de proche en proche à d'autres serveurs.
-
des serveurs racine répondent aux requêtes de premier niveau (TLD) et les redirige vers des serveurs du TLD concerné ;
-
Une association nom = adresse IP est faite à la base dans 1 ou 2 serveurs DNS ; ont dit qu'ils font autorité pour ce nom.
-
Des outils de test permettent d'interroger les DNS (paquet dnsutils
) :
traceroute
, dig
, whois
, ...
Voir : https://fr.wikipedia.org/wiki/Domain_Name_System
18.2.2. Configuration d'un client
Le nom de la machine est le contenu du fichier : /etc/hostname
.
Le comportement de la machine pour obtenir des informations (noms d'hôtes,
utilisateurs, mots de passe, etc) est conditionné par le fichier :
/etc/nsswitch.conf
(Name Service Switch : man nsswitch.conf
).
Ce fichier contient par exemple :
passwd: compat
group: compat
shadow: compat
hosts: dns [!UNAVAIL=return] files
networks: nis [NOTFOUND=return] files
ethers: nis [NOTFOUND=return] files
protocols: nis [NOTFOUND=return] files
rpc: nis [NOTFOUND=return] files
services: nis [NOTFOUND=return] files
La première colonne contient un nom de base de données ; la suite d'une ligne définit l'ordre dans lequel il faut chercher les informations.
Par exemple pour la résolution des noms en adresse IP :
hosts: files dns
signifie qu'il faut d'abord regarder dans la base locale, et sinon, utiliser le DNS ;
hosts: dns [!UNAVAIL=return] files
signifie qu'il faut d'abord utiliser le DNS, et que si les DNS ne sont pas injoignables de façon permanente, alors on arrête maintenant la recherche ; sinon, on regarde la base locale.
Dans le cas où la recherche de noms est faite dans la base locale (cas files
),
cette base est le fichier /etc/hosts
qui contient des lignes sous la forme :
ip nom_hôte alias...
Par exemple :
127.0.0.1 localhost # loopback
127.0.1.1 tesla.dil.univ-amu.fr tesla # idem
::1 ip6-localhost ip6-loopback # idem en IPV6
192.168.20.40 xubuntu2004 xubu1 # une VM
186.2.163.31 sci-hub.do moscow.sci-hub.do zero.sci-hub.do # sci-hub
Le DNS est configuré dans le fichier : /etc/resolv.conf
qui contiendra des directives de la forme : (man resolv.conf
)
search mondomaine1 mondomaine2
nameserver 127.0.1.1
Ce fichier peut être modifié dynamiquement par le système pour
permettre de travailler avec des connexions via plusieurs interfaces, ou lorsque
les serveurs de noms sont obtenus pas DHCP :
- par
networkmanager
- par
resolvconf(8)
Remarque : la commande getent
(get entry : man getent
) permet d'interroger
les bases définies dans nsswitch.conf
:
$ getent passwd
$ getent passwd thiel
$ getent hosts
$ getent hosts linuxfr.org
$ getent rpc
$ getent services ssh
18.2.3. Configuration d'un serveur bind
Paquets bind9
, voire bind9-doc
et dnsutils
.
Configuration : fichier /etc/bind/named.conf
.
Sous Debian et dérivés, ce fichier est éclaté dans :
named.conf fichier principal, appel les autres
named.conf.options options de configuration
named.conf.local définition des zones du DNS local
named.conf.local.default-zones définition de zones par défaut
et des Ressources Records (RRs) qui contiennent les informations des zones
locales et inverses, définies dans named.conf.local
.
Le statut et démarrage du serveur est obtenu par systemctl
:
$ systemctl status bind9
$ systemctl start|stop|restart|reload bind9
Exemple de fichier named.conf
:
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
Exemple de fichier named.conf.options
:
# définit le groupe d'hôtes "internals" ; ses autorisations seront ensuite
# données dans le bloc options.
acl internals { 127.0.0.0/8; 192.168.0.0/16; };
options {
# Répertoire de travail de bind
directory "/var/cache/bind";
# contrôle le comportement de retransmission d'une directive forwarders :
# - first : les serveurs de noms dans forwarders sont d'abord interrogés
# avant que named le fasse lui-même ;
# - only : ne consulte que les forwarders.
forward only;
# Liste d'IP valides de serveurs de noms pour la résolution
forwarders { 192.168.1.1; };
# interfaces réseaux par lesquelles on accepte des requêtes
listen-on { 127.0.0.1; 192.168.10.50; 192.168.20.50; }
listen-on-v6 { none; };
# autorise uniquement ces hôtes à interroger ce serveur,
# par défaut tous ; l'inverse est : blackhole { ... };
allow-query { internals };
# idem pour faire des demandes récursives
allow-recursion { internals };
};
Il y a de nombreuses choses à configurer, voir :