guest@6admin.io:~$

SSH en 2021 : ce que treize ans ont changé depuis la série de 2008

La série SSH d’ici s’arrêtait en 2013: l’authentification par clefs en 2008 , l’authentification multiple en 2012 , la restriction de connexion et PKCS#8 en 2013 comme dernier acte. Huit ans plus tard, tout ce que ces articles faisaient avec de l’artisanat existe en primitives. Voici le mémo 2021, complet.

Les clés: Ed25519 et le couple FIDO2

ssh-keygen -t ed25519 -a 100 -C "logout@2021"
ssh-keygen -t ed25519-sk -a 100                  # clé hardware, touch obligatoire
ssh-add -K                                       # télécharge les resident keys de la YubiKey

Ed25519 pour tout ce qui est software: plus courte, plus rapide, plus résistante et -a 100 durcit le KDF contre le brute-forcing de la passphrase (l’héritage direct du PKCS#8 de 2013 , qui avait raison avant l’heure). Les clés -sk (OpenSSH 8.2, 2020) branchent une YubiKey: la clé privée ne quitte jamais le matériel, le protocole exige un touch physique. Et RSA? Le soleil se couche: OpenSSH 8.2 a désactivé ssh-rsa (SHA-1) dans CASignatureAlgorithms par défaut et l’annonce du retrait complet est déjà dans les release notes. En 2008, RSA 2048 était le luxe; en 2021, c’est la dette technique.

Les certificats: la réponse structurée à l’“authentification multiple”

L’article de 2012 grugeait avec plusieurs clés et force-command. L’outil qui rend ça propre s’appelle un certificat ssh:

# côté CA (une machine, un secret)
ssh-keygen -s ca_key -I "logout-access" -n prod,deploy -V +1d logout.pub
# côté serveur
echo "@cert-authority * <contenu de ca_key.pub>" > /etc/ssh/trusted-user-ca-keys.pem
# côté sshd
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
AuthorizedPrincipalsFile /etc/ssh/principals/%u

Une clé de CA signe des identités temporaires (-V +1d), avec des principals (les groupes: prod, deploy) et le serveur n’a plus une authorized_keys à 40 lignes: il fait confiance à une autorité. Révocation = ne pas renouveler. La rotation = resigner. Le mot de passe et la clé de longue durée disparaissent de l’équation et l’“authentification multiple” de 2012 devient un principals=.

Le durcissement sshd, la version 2021

# /etc/ssh/sshd_config.d/hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
ClientAliveInterval 120
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
MACs umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com

Rien d’exotique: chaque ligne supprime une option que 2008 laissait ouverte par confort. Le sshd_config.d/ (Include, OpenSSH 8.2+) permet de la versionner par machine sans fourcher le fichier principal.

Le client, la partie qui a le plus changé

# ~/.ssh/config
Include config.d/*

Host prod-jump
  HostName bastion.prod.example.tld
  User logout
  IdentitiesOnly yes

Host prod-*
  ProxyJump prod-jump              # le tunnel de 2008 devient une ligne
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 10m
  ServerAliveInterval 30
  ServerAliveCountMax 4
  HashKnownHosts yes
  StrictHostKeyChecking accept-new
  UpdateHostKeys yes

Trois héritages directs de la série: le ProxyJump (-J) tue le tunneling administratif en une option (plus de -L en cascade); ControlMaster/ControlPersist multiplexe les sessions sur une seule connexion TCP (le prix du TCP-over-TCP disparaît); et Match exec + Include permettent la config par contexte:

# ~/.ssh/config.d/work
Match host "github.com-work" exec "test -d ~/projets/company"
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

C’est l’héritier de la restriction de connexion de 2012 : les restrictions vivent désormais dans la config elle-même. Et à l’échelle, ça donne le split myflec : un ~/.ssh/config qui ne contient qu’un Include config.d/* et trois fichiers par contexte (work, private, lab), chaque bloc Host restant dans le fichier du contexte auquel il appartient. Deux règles rendent le montage tenable: IdentitiesOnly yes partout (sinon ssh essaie toutes les clés dans l’ordre et brûle des tentatives) et first match wins (les blocs spécifiques avant les wildcards, l’include s’expandant à son point d’inclusion). La convention de nommage suit: clés <forge>_<label>_<type> (github.com_perso_ed25519, company.work_companyuser_ed25519), alias d’hôte <forge>-<label> (git@github.com-work:owner/repo). Neuf ans après l’article de 2012, la config est devenue une donnée versionnée par contexte, plus un plat de spaghettis.

La morale, treize ans plus tard

En 2008, la clef publique était une conquête. En 2013, PKCS#8 protégeait la clef. En 2021, la clef ne quitte plus le matériel, l’identité se signe pour un jour et le serveur ne connaît que des certificats. La série continue; elle est juste passée de l’artisanat aux primitives. Prochain article de la série dans huit ans ou quand les clés FIDO2 deviendront aussi banales que les clefs Ed25519 le sont devenues.

[edit: 2026] L’implémentation Ansible de tout ceci: le rôle ssh .