Debugger une connexion SSL avec Openssl

Les certificats et leur gestion restent toujours un peu obscur pour un grand nombre de personnes. Bien qu’il soit assez facile de configurer apache et mod_ssl avec un certificat auto-signé, il peut en être tout autre avec des certificats signés par une autorité de certification reconnue type thawte, Verisign,…. Ajoutez à cela la gestion des certificats clients, on peut rapidement en perdre la tête.

je vais vous présenter différentes façons de débugger une connexion SSL depuis un poste client avec Openssl. Vous saurez ainsi rapidement si votre web server est bien configuré, c’est à dire si les certificats, et donc la chaine de certification, présentés à votre navigateur sont ceux attendus, et si des certificats clients sont exigés.

Pré-requis

Le cas de figure présenté ici consiste en :

– une Autorité de Certification (AC) auto-signée
– un certificat serveur signé par l’AC
– un certificat client signé par l’AC
– un apache + mod_ssl configuré pour exigé un certificat client signé par l’AC

Si ce n’est pas déjà fait, téléchargez OpenSSL sur votre poste !!

Vérification de la connexion SSL

Ici, nous vérifions, dans un premier temps, que la connexion SSL fonctionne, en gros, que nous avons configuré correctement notre web server.

$ openssl s_client -connect neosec.batard.eu:443
CONNECTED(00000003)
depth=1 /C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
verify error:num=19:self signed certificate in certificate chain
verify return:0
835:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s3_pkt.c:1061:SSL alert number 40
835:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s23_lib.c:188:

openssl s_client -connect host:port lance une com SSL vers le serveur (host) sur le port 443, port par défaut de SSL. Changez le si nécessaire.

Nous pouvons constater assez facilement que nous avons réussi à monter une com SSL grâce à CONNECTED(00000003). Cependant, la négociation SSL n’est pas arrivée à son terme d’après le message d’erreur sslv3 alert handshake failure.
Nous allons tenter de trouver pourquoi.

Visualiser le handshake SSL

L’option que je vais vous présenter permet de visualiser le handshake SSL dans son ensemble en hexadécimal.
Ci-dessous, le schéma d’un handshake SSL réussi:

SSL Handshake

Schéma d’une négociation SSL

Pour plus d’informations sur le détail de chaque phase, un petit tour sur Wikipedia s’impose.

$ openssl s_client -connect neosec.batard.eu:443 -msg
CONNECTED(00000003)

>>> SSL 2.0 [length 007d], CLIENT-HELLO
01 03 01 00 54 00 00 00 20 00 00 39 00 00 38 00
...
...
aa ea 7b 8b fe a2 c7 57 a3 da 77 3e 52

<<< TLS 1.0 Handshake [length 004a], ServerHello
02 00 00 46 03 01 4d 7b 5c aa 1f cd d9 b3 35 31
c2 41 7a e3 b1 0d 59 24 7f 95 4a 99 57 f5 b5 07
ba 94 44 ce 40 3a 20 3c 12 10 64 58 43 99 c3 4b
03 59 d5 b6 3c ba 7c 8d a3 78 9a 9e 87 fb 6b d8
ad 5b b0 87 f5 22 2d 00 39 00

<<< TLS 1.0 Handshake [length 09c2], Certificate
0b 00 09 be 00 09 bb 00 04 f4 30 82 04 f0 30 82
...
...
91 2f 73 5d 25 8d 4c 0c bb 23 63 7c a1 92 a3 1f
a3 6a

depth=1 /C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
verify error:num=19:self signed certificate in certificate chain
verify return:0

<<< TLS 1.0 Handshake [length 020d], ServerKeyExchange
0c 00 02 09 00 80 d6 7d e4 40 cb bb dc 19 36 d6
...
...
a5 89 36 49 8e 50 e3 f3 11 79 8b 3d c0 14 72 6f
c9 64 e3 6c d7 2c 84 bc 2f cd 90 2b 94

<<< TLS 1.0 Handshake [length 0093], CertificateRequest
0d 00 00 8f 05 03 04 01 02 40 00 87 00 85 30 81
...
...
77 65 62 6d 61 73 74 65 72 40 62 61 74 61 72 64
2e 65 75

<<< TLS 1.0 Handshake [length 0004], ServerHelloDone 0e 00 00 00 >>> TLS 1.0 Handshake [length 0007], Certificate
0b 00 00 03 00 00 00

>>> TLS 1.0 Handshake [length 0086], ClientKeyExchange
10 00 00 82 00 80 3c 4c f3 f0 d8 ed 65 e7 23 d5
..
..
92 fb 15 b5 e9 28 e8 ee de 84 d8 6d c7 c2 b0 8e
fd e5 e1 b2 b3 70
>>> TLS 1.0 ChangeCipherSpec [length 0001]
01

>>> TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c 63 40 d7 34 d5 5b 8c 02 2b da d6 e6

<<< TLS 1.0 Alert [length 0002], fatal handshake_failure
02 28

698:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s3_pkt.c:1061:SSL alert number 40
698:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s23_lib.c:188:

Nous pouvons voir qu’ici, le serveur a bien présenté son certificat et qu’il a été accepté par le client. Or, l’opération se termine par un fatal handshake_failure.

Identifier les certificats requis par un serveur lors d’une authentification cliente

prexit, ma commande préférée. OpenSSL n’affiche pas toutes les informations lorsqu’une session SSL échoue. Cette option permet de palier à ce problème. Voici comment.

$ openssl s_client -connect batard.eu:443 -prexit
CONNECTED(00000003)

depth=1 /C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
verify error:num=19:self signed certificate in certificate chain
verify return:0
823:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s3_pkt.c:1061:SSL alert number 40
823:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-35/src/ssl/s23_lib.c:188:
---
Certificate chain
0 s:/C=FR/ST=Ile-de-France/O=Batard/CN=www.batard.eu/emailAddress=webmaster@batard.eu
i:/C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
1 s:/C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
i:/C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE8DCCA9igAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCRlIx
...
...
A3r15TfDatqGp8tnTeyJ8FoB6KA=
-----END CERTIFICATE-----
subject=/C=FR/ST=Ile-de-France/O=Batard/CN=www.batard.eu/emailAddress=webmaster@batard.eu
issuer=/C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
---
Acceptable client certificate CA names
/C=FR/ST=Ile-de-France/L=Villejuif/O=Batard/CN=batard.eu/emailAddress=webmaster@batard.eu
---
SSL handshake has read 3275 bytes and written 210 bytes
---

Une information importante nous intéresse particulièrement ici. Acceptable client certificate CA names nous indique clairement les certificats clients trustés par le serveur. Il suffit alors de vérifier le certificat client présenté au serveur et le tour est joué.

Résoudre les problèmes de « unable to verify the first certificate »

Lors d’une connexion avec openssl s_client, vous rencontrerez sûrement le message suivant :

 Verify return code: 21 (unable to verify the first certificate) 

Cela signifie qu’openssl n’a pas réussi à valider la chaîne de certification, c’est à dire le certificat serveur + l’autorité de certification.

Pour vérifier la chaîne de certification, ajoutez la directive -CAfile à openssl pour lui préciser quelle est l’autorité de certification du certificat serveur. Utile dans le cas où openssl n’a pas dans son référentiel le certificat racine du certificat serveur. Cette directive ne sert que pour des tests.

Exemple:

openssl s_client -connect monsite.com:443 -CAfile mofichierCA.pem

Assurez vous également que le serveur renvoie bien la chaîne de certification complète dans le cas d’un AC de type distribuée avec différentes AC intermédiaires comme Verisign.Verisign propose différents types de certificats qui sont générés par des AC intermédiaires également différentes. Par conséquent, l’utilisateur final, humain ou machine, n’a aucune connaissance de l’AC ayant généré le certificat serveur. C’est pour cette raison que c’est au serveur de l’envoyée en même temps que son propre certificat. Vous pouvez le vérifier via la log suivante

depth=n 

où n est la profondeur dans la hiérarchie de certificat. certificat serveur -> certificat intermédiaire -> certificat racine.
La directive apache permettant d’envoyer la chaîne de certification est

 SSLCertificateChainFile 

Lien Permanent pour cet article : https://www.batard.eu/2011/03/debugger-une-connexion-ssl-avec-openssl/

(4 commentaires)

Passer au formulaire de commentaire

    • AmandaG on 16 janvier 2012 at 10 h 18 min
    • Répondre

    Bonjour,
    Pour tester la configuration de mon serveur Apache 2.2.21, j’ai essayé de m’y connecter depuis mon browser (https://nomdemonserveur). Ca marche sans problème mais quand j’essaie avec Openssl, le handshake SSL échoue

    $ openssl s_client -connect nomdemonserveur:443
    verify error:num=19:self signed certificate in certificate chain
    verify return:0
    5152:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s
    3_pkt.c:1102:SSL alert number 40
    5152:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:182

    En décortiquant un peu tout ça avec les options proposées + haut, je soupçonne lecertificat auto-signé de mon CA d’être à l’origine du problème

    >>> TLS 1.0 ChangeCipherSpec [length 0001]
    01
    >>> TLS 1.0 Handshake [length 0010], Finished
    14 00 00 0c 3a 5b ba 15 3f 5b 68 f1 91 e7 55 5f
    <<< TLS 1.0 Alert [length 0002], fatal handshake_failure
    02 28
    CONNECTED(00000003)
    **************
    Verify return code: 19 (self signed certificate in certificate chain)

    Pourriez vous me donner une indication?

    Par avance merci.

    • on 23 janvier 2012 at 11 h 44 min
    • Répondre

    Effectivement le certificat auto-signé est à l’origine de cette erreur. Cependant, il ne s’agit ici que d’un avertissement.
    La connexion SSL se fait correctement puisque nous avons ici un CONNECTED. Avec une chaîne de certification complète AC+certificat serveur le message ne devrait plus apparaître.

    • duret on 6 décembre 2016 at 15 h 27 min
    • Répondre

    Bonjour,

    Comment pourriez-vous traduire cette erreur. Je n’y arrive toujours pas depuis 2 jours. Je vous remercie par avance

    openssl s_client -connect 172.16.0.31:1765 -prexit
    CONNECTED(00000003)
    depth=1 C = FR, O = Orange, OU = FR 89 380129866, CN = Orange Internal G2 Server CA
    verify error:num=20:unable to get local issuer certificate
    verify return:0
    140299794462536:error:1409441B:SSL routines:SSL3_READ_BYTES:tlsv1 alert decrypt error:s3_pkt.c:1193:SSL alert number 51
    140299794462536:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:

    Certificate chain
    0 s:/C=FR/ST=Ht-Garonne/L=Toulouse/O=SopraSteria/OU=SIRH/CN=Sopra/emailAddress=123@sopra.com
    i:/C=FR/O=Orange/OU=FR 89 380129866/CN=Orange Internal G2 Server CA
    1 s:/C=FR/O=Orange/OU=FR 89 380129866/CN=Orange Internal G2 Server CA
    i:/C=FR/O=Orange/OU=FR 89 380129866/CN=Orange Internal G2 Root CA
    2 s:/C=FR/O=Orange/OU=FR 89 380129866/CN=Orange Internal G2 Root CA
    i:/C=FR/O=Orange/OU=FR 89 380129866/CN=Orange Internal G2 Root CA

    1. Bonjour,

      Vous n’avez pas utilisé l’option -cafile qui permet de préciser le keystore qui contient la chaîne de certification.

Laisser un commentaire

Your email address will not be published.