All links of one day
in a single page.
<Previous day - Next day>

rss_feedDaily RSS Feed
floral_left The Daily Shaarli floral_right
——————————— Tuesday 19, January 2021 ———————————

Si VPN TLS Cisco ASA + openconnect = « Server certificate verify failed: signer not found », pense à fournir le certificat x509 intermédiaire

Résumé : si t'utilises un Cisco ASA pour fournir un service de VPN TLS et que des utilisateurs GNU/Linux qui utilisent openconnect rencontrent l'erreur « Server certificate verify failed: signer not found », vérifie que ton ASA envoie bien le certificat x509 intermédiaire en sus de son certificat client / feuille au client lors de l'échange TLS.



Nous utilisons notre Cisco ASA pour fournir un VPN TLS. Il se présente auprès des clients VPN avec un certificat x509. Le nôtre expire dans 24 jours. Donc on le renouvelle. Sauf que ça ne fonctionne pas : impossible de charger ce certificat dans ASDM. Aucun message d'erreur explicite.

Nous achetons nos certificats x509 en passant par un groupement d'organisations. Ce dernier a fait le choix de changer d'autorité de certification. Le certificat x509 de la nouvelle autorité encapsule une clé RSA de 3072 bits (contre 2048 bits pour l'ancienne) et il est signé en utilisant la fonction de condensation SHA-384 (contre SHA-256 pour l'ancien). J'imagine que l'une de ces propriétés ne convient pas à notre Cisco ASA dont le logiciel n'est plus à jour (son remplacement est en cours, mais ça traîne au-delà de nos prévisions pessimistes qui nous ont conduit à ne plus renouveler le support de l'ASA).



Pour dépanner, nous décidons d'utiliser un certificat Let's Encrypt. Car, au niveau technique c'est ce qu'on a toujours eu : RSA 2048 bits + SHA-256. De plus, c'est la manière la plus simple et rapide (pas de procédure d'achat à déclencher, on tire un certificat, on teste et on voit direct le résultat). Notre ASA accepte le certificat. \o/ Victoire ?

Sur un système GNU/Linux, nous conseillons le client VPN openconnect, une implémentation libre pour plusieurs VPN TLS (Cisco, Juniper, etc.) qui s'intègre à GNOME network-manager. Depuis le changement de certificat x509, nos utilisateurs reçoivent une erreur :

$ sudo openconnect vpn.monorganisation.example
POST https://vpn.monorganisation.example/
Connected to 192.0.2.1:443
Négociation SSL avec vpn.monorganisation.example
Server certificate verify failed: signer not found

Certificate from VPN server "vpn.monorganisation.example" failed verification.
Reason: signer not found
To trust this server in future, perhaps add this to your command line:
    --servercert pin-sha256:xAj8efLob9rYcspJ8p+2J+K9qTJlgsW1m300Ls+VyCs=
Enter 'oui' to accept, 'non' to abort; anything else to view: oui

Même erreur avec openconnect sur Android. Aucune erreur avec winwin + AnyConnect. Aucune erreur sur Apple (Mac OS, IOS), mais c'est normal : nous préconisons l'utilisation d'IPSec.



Qu'est-ce qui ne va pas ?

$ openssl s_client vpn.monorganisation.example:443
CONNECTED(00000003)
depth=0 CN = vpn.monorganisation.example
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = vpn.monorganisation.example
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:CN = vpn.monorganisation.example
   i:C = US, O = Let's Encrypt, CN = R3
---

Hum. Le VPN envoie uniquement son certificat (dit aussi certificat client ou certificat feuille). Celui-ci est signé par un certificat intermédiaire (dans le cas de Let's Encrypt, et jusqu'en 2025, il se nomme « R3 ») qui n'est pas communiqué par le serveur. Or, un certificat intermédiaire est jamais livré dans un catalogue / magasin des autorités de certification, car ce n'est pas son rôle. Donc, la bibliothèque TLS (OpenSSL pour openssl s_client et GnuTLS pour openconnect) échoue sur la vérification du certificat feuille.

Pour que le VPN ASA envoie aussi le certificat intermédiaire, il suffit d'ajouter ce dernier dans ASDM => « Configuration » => « Device Management » => « Certificate Management => CA Certificates ».

Plus d'erreur. \o/

$ openssl s_client vpn.monorganisation.example:443
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = vpn.monorganisation.example
verify return:1
---
Certificate chain
 0 s:CN = vpn.monorganisation.example
   i:C = US, O = Let's Encrypt, CN = R3
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:O = Digital Signature Trust Co., CN = DST Root CA X3



Pourquoi ça fonctionnait avec AnyConnect ? Peut-être que celui-ci désactive la vérification du pair lors de l'échange TLS ou qu'il est moins stricte, ce qui est une très mauvaise idée dans tous les cas.

-