"tlsv1 предупреждает о внутренней ошибке" во время рукопожатия


У меня есть PHP-скрипт, который проверяет доступность URL-адресов (в основном, скрипт должен возвращать значение true для данного URL-адреса, когда URL-адрес можно открыть в браузере, и наоборот). Есть URL-адрес, на который я наткнулся: https://thepiratebay.gd /. Этот URL-адрес может быть правильно открыт в браузере, но fsockopen() просто не работает с ошибками подтверждения SSL. В PHP не так много вариантов отладки fsockopen(), но, углубляясь в него, я обнаружил, что также не могу подключиться к https://thepiratebay.gd / использование консольного клиента openssl:

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:

Этот веб-сайт, похоже, нормально открывается с помощью веб-браузера или curl, однако я не смог найти способ подключиться к нему через openssl. По-видимому, сервер использует TLS 1.2 с шифром ECDHE-ECDSA-AES128-GCM-SHA256, но даже когда я использую их для openssl, он все равно терпит неудачу:

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)
---

Я пробовал различные версии openssl: 0.9.8y, 1.0.1g и самые последние версии 0.9.8zf и 1.0.2a. Я также пытался запустить это по крайней мере на 5 серверам (CentOS, Debian, OSX) не повезло.

Все остальные веб-сайты, похоже, обрабатываются нормально, вот пример успешного вывода рукопожатия:

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)

Трудно поверить, что все эти версии openssl имеют одну и ту же ошибку, поэтому я думаю, что делаю что-то не так.

Может ли кто-нибудь посоветовать, как подключиться к этому конкретному веб-сайту с помощью openssl?

Author: jww, 2015-05-29

2 answers

Эти два - плохая комбинация:

-cipher ECDHE-ECDSA-AES128-GCM-SHA256

И:

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

OpenSSL 0.9.8 не имеет полной поддержки EC. И он не поддерживает TLS 1.1 или 1.2. Чтобы получить наборы шифров AEAD, вам необходимо использовать TLS 1.2. Это означает, что вам нужен OpenSSL 1.0.0 или выше (IIRC).

Они есть в OpenSSL 1.0.1 и 1.0.2, поэтому, вероятно, лучше использовать эти версии.


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

Команда, которую вы ищете, это: openssl s_client -connect thepiratebay.gd:443 -tls1_2 -servername thepiratebay.gd -CAfile XXX. -servername зачисляет SNI.

Когда я зашел на сайт, сервер был сертифицирован AddTrust Внешний корневой центр сертификации. Когда вы зашли на сайт, он был сертифицирован DigiCert High Assurance EV Root CA. И когда вы снова зашли на сайт, он был сертифицирован Центром сертификации COMODO ECC.

Различные центры сертификации и конфигурации взаимодействуют с распределенным сайтом за балансировщиком нагрузки, при этом каждый участвующий веб-сервер находится в несколько ином конфигурация.


В дополнение к нескольким веб-серверам и конфигурациям, некоторые из самих веб-серверов сконфигурированы неправильно. Они неправильно настроены, поскольку не отправляют цепочку, необходимую для построения пути для проверки.

Цепочка должна включать (1) сертификат сервера; (2) Подчиненные центры сертификации или промежуточные звенья, которые образуют цепочку до "корня". Для (2) может быть одно или несколько промежуточных звеньев.

Цепочка не должна включать корень. Вы у вас должен быть корень, и ему нужно доверять.


Этот веб-сайт, похоже, нормально открывается с помощью веб-браузера или curl, однако я не смог найти способ подключиться к нему через openssl...

Это связано с тем, что браузеры содержат список из сотен корневых ЦС и подчиненных ЦС из-за неправильной конфигурации веб-сервера:) Список включает Добавить доверенный внешний корневой центр сертификации, Корневой центр сертификации DigiCert высокой гарантии EV и Корневой сертификат COMODO ECC Авторитет.


Может ли кто-нибудь посоветовать, как подключиться к этому конкретному веб-сайту с помощью openssl?

Хорошо, для команды OpenSSL вы должны использовать -CAfile. Обычно вы просто используете что-то вроде openssl s_client -connect ... -CAfile DigiCertHighAssuranceEVRootCA.crt (для сервера, сертифицированного с помощью DigiCert High Assurance EV Root CA). Но в данном случае это не сработает.

Вам необходимо создать один файл с требуемыми корневыми и подчиненными центрами сертификации. Файл должен представлять собой объединение корневых центров сертификации и Подчиненные центры сертификации в формате PEM, необходимые для построения пути для проверки сертификата сервера. Похоже, для этого потребуется как минимум 3 или 4 сертификата.

Или вы могли бы отказаться от создания собственного файла и использовать что-то вроде cacert.pem. Но есть некоторый риск в использовании зоопарка ЦА (мой ласковый термин для них). Для некоторых рисков см. Является ли cacert.pem уникальным для моего компьютера?.

Программно вы бы использовали SSL_CTX_load_verify_locations в OpenSSL. Объединенный PEM файл передан, хотя CAfile.

Я не уверен, что вы бы использовали в PHP.


Связанные, cacert.pem имеет 155 корней и подчиненных. Большинство из них не нужны для сертификации сайта thepiratebay.gd:

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

Отсюда причина, по которой вы хотите ограничить свой CAfile только теми, которые необходимы для сертификации сайта.


(комментарий) Не уверен, что это правильный вопрос, но теперь мне интересно, есть ли способ пропустить некоторые из этих проверок программно чтобы уменьшить количество ложных негативов...

Я бы, вероятно, не отказался от проверок. Теперь, когда вы понимаете, что происходит, вам должно быть проще работать с системой, чем отказываться от нее.

Чтобы повторить, либо:

  1. Используйте только необходимые корневые и подчиненные CAs

    1. Вы создаете его, объединение сертификатов PEM
    2. Создать файл piratebay-certs.pem
    3. Добавить необходимое CAs
  2. Используйте зоопарк ЦС с предопределенным доверенным корневым и подчиненным ЦС

    1. Вы загружаете его
    2. cacert.pem

Третий вариант - заставить сайт исправить конфигурации своего веб-сервера. Но если этого до сих пор не произошло, то, вероятно, и не произойдет. (И это может быть дизайнерское решение - сайт может использовать несколько центров сертификации, чтобы гарантировать, что ни один центр сертификации не сможет управлять сайтом. Но это не решает проблему неполного цепь).


И более общее наблюдение:

У меня есть PHP-скрипт, который проверяет доступность URL-адресов (в основном, скрипт должен возвращать значение true для данного URL-адреса, когда URL-адрес можно открыть в браузере, и наоборот

Переходя от piratebay.gd, в частности, к проверке случайных URL-адресов, вам, вероятно, придется использовать cacert.pem. Это потому, что случайная выборка из 1 миллиона сайтов, скорее всего, будет использовать их все.

Если piratebay.gd все еще терпит неудачу, то выясните чего не хватает в cacert.pem, а затем:

cat cacert.pem > my-expanded-cacert.pem
cat missing-cert.pem >> my-expanded-cacert.pem
 11
Author: jww, 2017-05-23 10:30:49

У меня было такое же сообщение об ошибке по другой причине: многие серверы используют SNI, и это может привести к этой ошибке.

В моем случае (клиент c++, созданный с помощью boost_asio + openssl) Я исправил это, используя следующий код:

 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());

Смотрите также этот ответ SO .

 2
Author: Malick, 2018-02-23 01:44:45