Table des matières

Configurer une authentification SSH avec certificat

Resources

Principes

L'utilisation de certificats permet de garantir l'identité du client et du serveur. OpenSSH permet de gérer des certificat dans un format spécifique. Ce ne sont pas des certificats x509.

OpenSSH gère des certificats dans un format spécifique qui ne sont pas des certificats x509 utilisables avec SSL/TLS.

La clé publique des utilisateurs et des serveurs doit être signée par la clé privée d'une autorité de certification spécifique à OpenSSH.

Configuration du serveur SSH (OpenSSH)

Le fichier de configuration du service SSH est /etc/ssh/sshd_config.

Lors de l'installation du serveur SSH ses clés privées et publiques sont générées sous plusieurs formats dans le dossier /etc/ssh, pour garder une comptabilité avec des clients plus anciens :

Dans le fichier de configuration du service SSH /etc/ssh/sshd_config, il est possible de fixer le type de clé côté serveur avec la directive HostKey.

Exemple :

HostKey /etc/ssh/ssh_host_rsa_key

La vérification de la configuration du service SSH se fait avec la commande suivante :

# /usr/sbin/sshd -d


Les éléments nécessaires

Génération de la paire de clés privée /publique de la CA OpenSSH

ssh-keygen permet de générer un paire de clés privée / publique pour gérer la CA OpenSSH. Les clés seront enregistrées dans le dossier /etc/ssh accessible uniquement avec les droits root.

Création en précisant :

Création de la paire de clé de type ecdsa pour la CA OpenSSH dans le dossier /etc/ssh :

ssh-keygen -f /etc/ssh/ssh_ca -C "CA for SSH" -N "Sio1234*"
  • Une passphrase permet de protéger la clé privée.

Format d’une clé publique ssh

Une clé publique SSH est une chaîne de texte en une seule ligne, avec plusieurs parties distinctes : <type> <clé encodée en base64> <commentaire facultatif>

Type : Spécifie l'algorithme utilisé pour générer la clé. Par exemple :

Clé encodée en base64 : chaîne encodée en Base64 représentant la clé publique.

Commentaire facultatif : information pour identifier la clé : nom d'utilisateur et l'hôte depuis lequel la clé a été générée.

Génération d'un certificat pour un serveur

La clé privée de la CA (/etc/ssh/ssh_ca) va signer la clé publique du serveur (clé générée automatiquement lors de l'installation du service SSH). Pour cet exemple c'est la clé ecdsa qui sera signée.
Utilisation des paramètres suivants :

$ ssh-keygen -s /etc/ssh/ssh\_ca -I SSH-SERVEUR1-CERT \
-h -z 1234 \
-n localhost,10.0.0.102,www.serveurweb.fr \
/etc/ssh/ssh\_host\_ecdsa\_key.pub

Le certificat Serveur /etc/ssh/ssh_host_ecdsa_key-cert.pub a été créé.

Le paramètre -L permet d'afficher le contenu du certificat :

ssh-keygen -L -f /etc/ssh/ssh\_host\_ecdsa\_key-cert.pub
/etc/ssh/ssh_host_ecdsa_key-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com host certificate
        Public key: ECDSA-CERT SHA256:gncg0I1AzJaivFQL5mA7V2H/5c8CSY4kZEdyuCK6ySQ
        Signing CA: ECDSA SHA256:t225t0te+LcQXCo1og6TYAnD2PIQ/vnMo/nWL64bIaY (using ecdsa-sha2-nistp256)
        Key ID: "SSH-SERVEUR1-CERT"
        Serial: 1234
        Valid: forever
        Principals:
                localhost
                10.0.0.102
                www.serveurweb.fr
        Critical Options: (none)
        Extensions: (none)

Commentaires :

Le serveur doit être configuré pour présenter ce certificat à tout client qui voudra se connecter.

Pour cela modifier le fichier du service SSH /etc/ssh/sshd_config pour

# utiliser un certificat serveur
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

Le lancement en mode debug du service ssh montre le chargement de la clé privée et du certificat :

root@Serveur1:~# /usr/sbin/sshd -d
...
debug1: private host key #0: ecdsa-sha2-nistp256 SHA256:gncg0I1AzJaivFQL5mA7V2H/5c8CSY4kZEdyuCK6ySQ
debug1: host certificate: #0 type 6 ECDSA-CERT
...

Redémarre le service SSH sur le serveur

systemctl restart ssh

Il est maintenant possible pour un client SSH de se connecter à un serveur présentant un certificat signé par la CA :

  • sans devoir valider l'identité du serveur ;
  • sans enregistrement d'une nouvelle ligne dans le fichier known_hosts.

Pour indiquer qu'un serveur particulier, présentant un certificat sign par la CA OpenSSH n'est plus de confiance, il suffit d'ajouter dans le fichier known_hosts une ligne avec le marqueur @revoked associé à la clé publique du serveur.

Mise en place du certificat serveur au niveau du client

La configuration du client permet à celui-ci de faire confiance à n'importe quel serveur qui présente un certificat signé par une CA préalablement définie.

Pour cela, le fichier ~/.ssh/known_hosts doit contenir une ligne avec la directive @cert-authority et la clé publique de la CA qui est reconnue.

Le format d'une ligne est le suivant avec des quatre types d'information séparés par des espaces :

Récupérez la clé publique de la CA et ajoutez-là dans le fichier know_hosts puis compétez la ligne ajoutée pour ajouter les paramètres nécessaires (directive @cert-authority, hostnames). Cela devfraot resmebler à cela :

@cert-authority 10.* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPsbCPdkmh9SXN2b/WwU9dqQi7z+0W5YY3SblMHdIS7gkQ2/YcFfCs/f56cwIDc2pkNmuVoFDJPo2gg5khqYtDg= CA for SSH

En se connectant en mode verbeux, vous visualisez que le certifivatt présenté a bien été validé :

debug1: Server host certificate: ecdsa-sha2-nistp256-cert-v01@openssh.com SHA256:gncg0I1AzJaivFQL5mA7V2H/5c8CSY4kZEdyuCK6ySQ, serial 1234 ID "SSH-SERVEUR1-CERT" CA ecdsa-sha2-nistp256 SHA256:t225t0te+LcQXCo1og6TYAnD2PIQ/vnMo/nWL64bIaY valid forever
debug1: load_hostkeys: fopen /home/charles/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: Host '10.0.0.102' is known and matches the ECDSA-CERT host certificate.
debug1: Found CA key in /home/charles/.ssh/known_hosts:1


Génération d'un certificat utilisateur autosigné

$ ssh-keygen -s id_rsa -I charles-CERT id

Le paramètre -L permet d'afficher le contenu du certificat :

ssh-keygen -L -f id_rsa-cert.pub
id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:Dv79U+oPIbv5CGIiROMxM02479DZwaj3xOcYJKw1Bww
        Signing CA: RSA SHA256:Dv79U+oPIbv5CGIiROMxM02479DZwaj3xOcYJKw1Bww (using rsa-sha2-512)
        Key ID: "charles"
        Serial: 0
        Valid: forever
        Principals: (none)
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Commentaires :

Génération d'un certificat utilisateur signé par la CA OpenSSH

Génération du certificat utilisateur

Les certificats OpenSSH permettent d'ajouter :

Pour signer un certificat avec ssh-keygen, deux paramètres au minimum sont nécessaires :

Il est cependant indispensable de préciser :

Le nom du fichier de certificat est généré en ajoutant -cert.pub au nom de la clé publique. Sur le serveur ayant les clé de la CA OpenSSH, signez la clé publique de l'utilisateur :

ssh-keygen -s /etc/ssh/ssh_ca -I CHARLES-CERT \
-z 1
-n charles
 id_rsa.pub

Le paramètre -L permet d'afficher le contenu du certificat :

ssh-keygen -L -f /home/charles/id_ecdsa-cert.pub
/home/charles/id_ecdsa-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
        Public key: ECDSA-CERT SHA256:vq5uCGtqvFGK2CiBX07gtXvfZuGklvnrQ2IBqEoiuzA
        Signing CA: ECDSA SHA256:t225t0te+LcQXCo1og6TYAnD2PIQ/vnMo/nWL64bIaY (using ecdsa-sha2-nistp256)
        Key ID: "CHARLES-CERT"
        Serial: 1
        Valid: forever
        Principals:
                charles
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Commentaires :

Validation d'un certificat de client SSH

Il y a plusieurs méthodes :

Validation généralisée de certificats

Pour activer la validation généralisée des certificats, le fichier de configuration du serveur SSH /etc/ssh/sshd_config doit contenir la directive TrustedUserCAKeys qui précise le nom du fichier contenant la liste des clef publique des CA OpenSSH.

TrustedUserCAKeys /etc/ssh/ssh_ca_keys

IMPORTANT : le certificat du client ne sera considéré que si sa liste de nom-clés (principal) contient le nom du compte auquel il tente de se connecter.

SAUF si un fichier spécifique à chaque compte indique la liste des noms-clés acceptés. Directive AuthorizedPrincipalsFile dans sshd_config

L'utilisateur peut maintenant se connecter en SSH au serveur sans avoir au préalable fait renseigner sa clé publique dans le fichier authorized_keys du serveur

Révocation globale de clés

Au niveau du serveur SSH, la révocation de clés publiques se fait à l'aide de la directive RevokedKeys en précisantle nom du fichier global contenant la liste des clés qui doivent être refusées. Cela fonctionne pour toutes les clés publiques, même s'il n'y a pas de certificat associé à la clé.

TrustedUserCAKeys /etc/ssh/ssh_ca_keys
RevokedKeys /etc/ssh/ssh_revoked_keys

Utilisation du fichier authorized_principals

Sur le serveur SSH, l'accès à un autre compte utilisateur que ceux listés dans les principals de son certificat est possible en utilisant la directive AuthorizedPrincipalsFile dans le fichier de configuration du serveur SSH /etc/ssh/sshd_config :

AuthorizedPrincipalsFile .ssh/authorized_principals

Dans ce cas-là, le serveur vérifie qu'un nom de la liste des principals du certificat qu'on lui propose apparaît bien dans le fichier .ssh/authorized_principals du compte cible.

Depuis le paragraphe 5.1, le certificat de l'utilisateur cb contientles valeurs cb , borelly et root . Il suffit donc d'indiquer une de ces 3 valeurs dans le fichier authorizedprincipals ducompte auquel on désire accéder. Le mode debug du serveur SSH nous indique que ce fichier est maintenant bien analysé en premier lieu quand l'utilisateur cb tente de se connecter sur le compte de root avec ce certificat : root@pccb ~# echo borelly > /root/.ssh/authorizedprincipals root@pccb ~# /usr/sbin/sshd -d … Failed publickey

Mise en place côté client

Quand un client accepte pour la première fois la connexion à un serveur, il enregistre dans le fichier ~/.ssh/know_hosts une ligne avec la clé publique du serveur.

Lors d'une prochaine connexion, la clé présentée par le serveur sera comparée à celle déjà enregistrée afin d'éviter les attaques du type homme du milieu.

Le client gère la liste des serveurs connus dans son fichier ~/.ssh/hnow_hosts :

ssh-keygen -F @IP

Le client doit faire signer sa clé publique pour obtenir un certificat qui doit être placé dans le même répertoire que sa clé privé et publique.

cp client_key ~/.ssh/
cp client_cert.pub ~/.ssh/

Les permissions doivent être correctes :

chmod 600 ~/.ssh/client_key
chmod 644 ~/.ssh/client_cert.pub

Lors d’une connexion avec la clé privée, le certificat sera automatiquement présenté au serveur.

Le client ssh doit seulement indique quelle clé privée utiliser avec l’option -i

ssh -i ~/.ssh/client_key nomDNSserveur

Ainsi même s’il n’y a pas de clé publique client dans authorized_keys, l’authentification se fait. L’option -v permet de voir l’utilisation du certificat

ssh -v -i ~/.ssh/client_key nomDNSserveur

Vous pouvez utiliser aussi le fichier de configuration du client ssh

Host <nom_du_serveur> 
    HostName <adresse_du_serveur> 
    User <nom_utilisateur>
    IdentityFile ~/.ssh/client_key
    CertificateFile ~/.ssh/client_cert.pub

Les commandes utiles

$ ssh-keygen -y -f utilisateur-identite.pem > id_rsa.pub
$ openssl x509 -in charles-cert.pem -pubkey –noout > id_rsa.pem

noout permet d’avoir uniquement la clé publique sans le certificat

$ ssh-keygen -i -m PKCS8 -f id_rsa.pem > id_rsa.pub
$ openssl x509 -in pkicub-cert.pem -pubkey –noout > ca.pem
* Convertir la clé publique du format PEM au format openssh 
$ ssh-keygen -f ca.pem > ca.pub
journalctl -u ssh
ssh -v <nom_du_serveur>
echo "@cert-authority *.example.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQE..." >> ~/.ssh/known_hosts

Cela permet au client de faire confiance à tous les serveurs avec des certificats signés par cette CA.

openssl x509 -in filename.pem -text –noout

-noout pour ne pas afficher en base64 qui permet d’encode des données binaires ASCII

openssl x509 -in filename.pem -issuer –noout
openssl x509 -in filename.pem -subject –noout
openssl x509 -in filename.pem -fingerprint –noout
openssl x509 -in filename.pem –pubkey -noout –out id_rsa.pub

Notes

Configurer une authentification SSH avec des certificats (et non simplement des clés publiques/privées) est une méthode avancée qui repose sur un serveur d'autorité de certification (CA) pour signer les clés SSH. Voici un guide étape par étape pour mettre cela en place :

  1. Générer une paire de clés pour l'utilisateur Sur la machine client (utilisateur) :
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_cert

Cela crée :

2. Créer une autorité de certification (CA) Sur la machine administrateur (ou serveur CA) :

ssh-keygen -f /etc/ssh/ssh_ca -C "CA for SSH" -N ""

Cela crée :

3. Signer la clé publique de l'utilisateur Toujours sur la machine CA :

ssh-keygen -s /etc/ssh/ssh_ca -I user_cert -n nom_utilisateur -V +52w ~/.ssh/id_rsa_cert.pub

Cela génère un fichier idrsacert-cert.pub.

Visualiser le contenu du certificat :

ssh-keygen -L -f id_rsa_cert.pub
  1. Configurer le serveur SSH pour accepter les certificats Sur le serveur SSH (où l'utilisateur veut se connecter), ajoutez dans /etc/ssh/sshd_config :
TrustedUserCAKeys /etc/ssh/ssh_ca.pub

Puis redémarrez le service SSH :

sudo systemctl restart sshd
  1. Configurer le client SSH Sur la machine client, dans ~/.ssh/config :
Host monserveur
    HostName monserveur.exemple.com
    User nom_utilisateur
    IdentityFile ~/.ssh/id_rsa_cert
    CertificateFile ~/.ssh/id_rsa_cert-cert.pub
  1. Connexion
ssh monserveur

Script Bash automatisé pour configurer une authentification SSH avec des certificats :

Ce que fait le script :

Utilisation :

chmod +x configurer_authentification_ssh.sh

=== Étape 1 : Générer une paire de clés pour l'utilisateur ===

echo “[1/5] Génération de la paire de clés utilisateur…” USERKEYDIR=“$HOME/.ssh” USERKEYNAME=“idrsacert” mkdir -p “$USERKEYDIR” ssh-keygen -t rsa -b 4096 -f “$USERKEYDIR/$USERKEYNAME” -N “”

=== Étape 2 : Créer une autorité de certification (CA) ===

echo “[2/5] Création de l'autorité de certification…” CADIR=“/etc/ssh” CAKEYNAME=“sshca” sudo ssh-keygen -f “$CADIR/$CAKEY_NAME” -C “CA for SSH” -N “”

=== Étape 3 : Signer la clé publique de l'utilisateur ===

echo “[3/5] Signature de la clé publique utilisateur…” CERTID=“usercert” USERNAME=“$(whoami)” VALIDITY=“+52w” sudo ssh-keygen -s “$CADIR/$CAKEYNAME” -I “$CERTID” -n “$USERNAME” -V “$VALIDITY” “$USERKEYDIR/$USERKEYNAME.pub”

=== Étape 4 : Configurer le serveur SSH pour accepter les certificats ===

echo “[4/5] Configuration du serveur SSH…” sudo bash -c “echo 'TrustedUserCAKeys $CADIR/$CAKEYNAME.pub' » /etc/ssh/sshdconfig” sudo systemctl restart sshd

=== Étape 5 : Créer un fichier de configuration SSH côté client ===

echo “[5/5] Création du fichier de configuration SSH client…” CONFIGFILE=“$USERKEYDIR/config” SERVERALIAS=“monserveur” SERVER_HOST=“monserveur.exemple.com”

cat «EOF

> "$CONFIG_FILE"

H

ost $SERVERALIAS HostName $SERVERHOST

  User $USERNAME
  IdentityFile $USER_KEY_DIR/$USER_KEY_NAME
  CertificateFile $USER_KEY_DIR/${USER_KEY_NAME}-cert.pub

EOF

chmod 600 “$CONFIG_FILE”

echo “ Configuration terminée. Vous pouvez maintenant vous connecter avec : ssh $SERVER_ALIAS”

</code>