web-dev-qa-db-fra.com

"Erreur interne d'alerte tlsv1" pendant la prise de contact

J'ai un PHP qui vérifie la disponibilité des URL (en gros, le script devrait retourner vrai pour une URL donnée lorsque l'URL pourrait être ouverte dans le navigateur et vice versa). Il y a une URL sur laquelle je suis tombé : https://thepiratebay.Gd/ . Cette URL pourrait être correctement ouverte dans le navigateur, mais fsockopen () échoue simplement avec les erreurs de négociation SSL. Il n'y a pas beaucoup d'options pour déboguer fsockopen () en PHP , mais en creusant davantage, j'ai trouvé que je ne pouvais pas non plus me connecter à https://thepiratebay.Gd/ en utilisant le client openssl de la console:

openssl s_client -connect thepiratebay.Gd:443 
CONNECTED(00000003)
39613:error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s23_clnt.c:602:

Ce site Web semble bien s'ouvrir en utilisant un navigateur Web ou curl, cependant, je n'ai pas pu trouver un moyen de s'y connecter via openssl. Apparemment, le serveur utilise TLS 1.2 avec le chiffrement ECDHE-ECDSA-AES128-GCM-SHA256, mais même lorsque je force ceux-ci pour openssl, il échoue toujours:

openssl s_client -cipher ECDHE-ECDSA-AES128-GCM-SHA256 -connect thepiratebay.Gd:443 -tls1_2
CONNECTED(00000003)
140735195829088:error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:s3_pkt.c:1256:SSL alert number 80
140735195829088:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1432931347
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

J'ai essayé différentes versions d'OpenSL: 0.9.8y, 1.0.1g, et les plus récentes 0.9.8zf et 1.0.2a. J'ai également essayé de l'exécuter sur au moins 5 serveurs (CentOS, Debian, OSX) sans succès.

Tous les autres sites Web semblent bien gérés, voici un exemple de sortie réussie de prise de contact:

openssl s_client -connect stackoverflow.com:443  -tls1
CONNECTED(00000003)
depth=1 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=NY/L=New York/O=Stack Exchange, Inc./CN=*.stackexchange.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGajCCBVKgAwIBAgIQCn1PE//Ffo4Be8tPBlsAZDANBgkqhkiG9w0BAQsFADBw
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
dXJhbmNlIFNlcnZlciBDQTAeFw0xMzEwMjIxMjAwMDFaFw0xNjA3MDYxMjAwMDBa
MGoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJOWTERMA8GA1UEBxMITmV3IFlvcmsx
<---skipped few lines--->
qOHCjaUIx7vKszN4cqbvyry/NdxYkPCC7S8Eks8NjSyppzRL79tU0Yr1MUhVEd6h
GjB2qDwvAGqyWmLz1Q/l82lZbXyBF26DVTJ3RFRUzzieyzKucaVgohI7HC2yyJ9Y
AsE7wvVK4odQI3fRjOsLRaXjFtpiaor0rERUxM4mg7jj05leRBkSazNjv2xvCL5/
Qqm5PN666tREQwvgvXZgg+ZlKWkFyOq6X3THstM6CC8DTGED0cb94WPQA4YTp9OQ
rS3+OedQN+Nlu80Sk8Y=
-----END CERTIFICATE-----
subject=/C=US/ST=NY/L=New York/O=Stack Exchange, Inc./CN=*.stackexchange.com
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
---
No client certificate CA names sent
---
SSL handshake has read 3956 bytes and written 426 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES128-SHA
    Session-ID: 2E38670F2CABEF3D65FAC67DB6D2E00DBACA4519E50B463D57FCFF8410640BF5
    Session-ID-ctx: 
    Master-Key: 4C63E5502FF7DD36853048E775435A76CB1FDEB37104D6714B1C37D89482D8111B93574D2B3D7F38A1EEFF85D69F9F54
    Key-Arg   : None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 39 a8 c2 5f c5 15 04 b3-20 34 af fe 20 8e 4d 6c   9.._.... 4.. .Ml
    0010 - 6e 63 f1 e3 45 fd 2a 2c-d9 3c 0d ac 11 ab c0 c9   nc..E.*,.<......
    0020 - ce 51 19 89 13 49 53 a0-af 87 89 b0 5d e2 c5 92   .Q...IS.....]...
    0030 - af e5 84 28 03 4e 1e 98-4c a7 03 d5 5f fc 15 69   ...(.N..L..._..i
    0040 - 7c 83 d2 98 7d 42 50 31-30 00 d7 a8 3c 85 88 a7   |...}BP10...<...
    0050 - cd c0 bb 45 c8 12 b1 c8-4b 76 3c 41 5e 47 04 b5   ...E....Kv<A^G..
    0060 - 60 67 22 76 60 bb 44 f3-4b 3d 3d 99 af 0e dd 0d   `g"v`.D.K==.....
    0070 - 13 95 db 94 90 c2 0f 47-26 04 65 6b 71 b2 f8 1c   .......G&.ekq...
    0080 - 31 95 82 8b 00 38 59 08-1e 84 80 dc da 04 5c f0   1....8Y.......\.
    0090 - ae cc 2b ac 55 0f 39 59-0b 39 7d c7 16 b9 60 ef   ..+.U.9Y.9}...`.

    Start Time: 1432930782
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)

Il est difficile de croire que toutes ces versions d'OpenSL ont le même bug, donc je pense que je fais quelque chose de mal.

Quelqu'un peut-il me conseiller sur la façon de se connecter à ce site Web particulier en utilisant openssl?

14
Alex Rudakov

Ces deux sont une mauvaise combinaison:

-cipher ECDHE-ECDSA-AES128-GCM-SHA256

Et:

error:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s23_clnt.c

OpenSSL 0.9.8 ne prend pas complètement en charge EC. Et il ne prend pas en charge TLS 1.1 ou 1.2. Pour obtenir les suites de chiffrement AEAD, vous devez utiliser TLS 1.2. Cela signifie que vous avez besoin d'OpenSSL 1.0.0 ou supérieur (IIRC).

OpenSSL 1.0.1 et 1.0.2 en ont, il est donc probablement préférable d'utiliser ces versions.


 openssl s_client -connect thepiratebay.Gd:443 ...

La commande que vous recherchez est: openssl s_client -connect thepiratebay.Gd:443 -tls1_2 -servername thepiratebay.Gd -CAfile XXX. -servername enrôle SNI.

Lorsque j'ai accédé au site, le serveur a été certifié par Racine de l'AC externe AddTrust . Lorsque vous accédez au site, il est certifié par DigiCert High Assurance EV Root CA . Et lorsque vous accédez à nouveau au site, il est certifié par l'autorité de certification COMODO ECC .

Les différentes autorités de certification et configurations parlent à un site distribué derrière un équilibreur de charge, avec chaque serveur Web participant dans une configuration légèrement différente.


Outre plusieurs serveurs Web et configurations, certains des serveurs Web eux-mêmes sont mal configurés. Ils sont mal configurés car ils n'envoient pas la chaîne requise pour créer un chemin de validation.

La chaîne doit inclure (1) le certificat de serveur; (2) Autorités de certification ou intermédiaires subordonnés qui forment la chaîne jusqu'à la "racine". Pour (2), il peut y avoir un ou plusieurs intermédiaires.

La chaîne ne doit pas inclure la racine. Vous devez avoir la racine et elle doit être fiable.


Ce site Web semble bien s'ouvrir en utilisant un navigateur Web ou curl, cependant, je n'ai pas pu trouver un moyen de me connecter via openssl ...

Cela est dû au fait que les navigateurs contiennent une liste de centaines d'autorités de certification racine et de autorités de certification subordonnées en raison de mauvaises configurations du serveur Web :) La liste comprend Racine de l'AC externe AddTrust , Autorité de certification racine DigiCert High Assurance EV , et Autorité de certification racine COMODO ECC .


Quelqu'un peut-il me conseiller sur la façon de se connecter à ce site Web particulier en utilisant openssl?

OK, pour la commande OpenSSL, vous devez utiliser -CAfile. Habituellement, vous utilisez simplement quelque chose comme openssl s_client -connect ... -CAfile DigiCertHighAssuranceEVRootCA.crt (pour le serveur certifié avec DigiCert High Assurance EV Root CA ). Mais cela ne fonctionnera pas dans ce cas.

Vous devez créer un fichier unique avec les autorités de certification racine et subordonnées requises. Le fichier doit être une concaténation des autorités de certification racine et des autorités de certification subordonnées au format PEM requises pour créer un chemin d'accès pour valider le certificat de serveur. Il semble qu'il aura besoin d'au moins 3 ou 4 certificats.

Vous pouvez également renoncer à créer votre propre fichier et utiliser quelque chose comme cacert.pem . Mais il y a un certain risque à utiliser le CA Zoo (mon terme affectueux pour eux). Pour certains des risques, voir cacert.pem est-il unique à mon ordinateur? .

Par programme, vous utiliseriez SSL_CTX_load_verify_locations dans OpenSSL. Le fichier PEM concaténé est transmis via CAfile.

Je ne sais pas ce que vous utiliseriez en PHP.


En relation, cacert.pem a 155 racines et subordonnés. La plupart d'entre eux ne sont pas nécessaires pour certifier le site thepiratebay.Gd:

$ cat cacert.pem | grep BEGIN | wc -l
     155

D'où la raison pour laquelle vous souhaitez restreindre votre CAfile uniquement à ceux nécessaires pour certifier le site.


(commentaire) Je ne sais pas si c'est le bon fil à poser, mais maintenant je me demande s'il existe un moyen d'ignorer certaines de ces vérifications par programme pour réduire le nombre de faux négatifs ...

Je ne voudrais probablement pas renoncer aux contrôles. Maintenant que vous comprenez ce qui se passe, il devrait être plus facile de travailler avec le système plutôt que de l'abandonner.

Pour réitérer, soit:

  1. Utilisez uniquement les autorités de certification racine et subordonnées nécessaires

    1. Vous le construisez, concaténation de certificats PEM
    2. Créer un fichier piratebay-certs.pem
    3. Ajouter les autorités de certification nécessaires
  2. Utiliser un zoo de CA avec des CA racine et subordonnées de confiance prédéterminées

    1. Vous le téléchargez
    2. cacert.pem

La troisième option consiste à demander au site de corriger ses configurations de serveur Web. Mais si cela ne s'est pas encore produit, cela n'arrivera probablement pas. (Et cela pourrait être une décision de conception - le site peut utiliser plusieurs autorités de certification pour s'assurer qu'aucune autorité de certification ne peut faire le site. Mais cela ne règle pas la chaîne incomplète).


Et l'observation plus générale:

J'ai un script PHP qui vérifie la disponibilité des URL (fondamentalement, le script doit retourner vrai pour une URL donnée lorsque l'URL peut être ouverte dans le navigateur et vice versa)

S'éloigner de piratebay.Gd en particulier pour vérifier des URL aléatoires, vous devrez probablement utiliser cacert.pem. En effet, un échantillon aléatoire de 1 million de sites les utilisera probablement tous.

Si piratebay.Gd échoue toujours, puis découvrez ce qui manque dans cacert.pem, puis:

cat cacert.pem > my-expanded-cacert.pem
cat missing-cert.pem >> my-expanded-cacert.pem
12
jww

J'ai eu le même message d'erreur pour une raison différente: beaucoup de serveurs utilisent SNI et cela peut produire cette erreur.

Dans mon cas (un client c ++ créé avec boost_asio + openssl), je l'ai corrigé en utilisant le code suivant:

 char port[] =  "https";
 string Host =  "www.server.com"
 boost::asio::ip::tcp::resolver::query query(Host, port);
 ...
 boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12);
 ...
 ...
 //the following line fix the issue
 SSL_set_tlsext_Host_name(socket_.native_handle(), Host_.c_str());

voir aussi this SO answer .

3
Malick