2015-05-29 8 views
11

Ich habe ein PHP-Skript, das URLs Verfügbarkeit überprüft (im Grunde sollte das Skript für eine bestimmte URL zurück, wenn die URL im Browser geöffnet werden konnte und umgekehrt). Es gibt eine URL, über die ich gestolpert bin: https://thepiratebay.gd/. Diese URL kann im Browser korrekt geöffnet werden, aber fsockopen() schlägt einfach mit den SSL-Handshake-Fehlern fehl. Es gibt nicht viele Optionen für das Debuggen von fsockopen() in PHP, aber während mehr in sie zu graben, fand ich, dass ich auch auf https://thepiratebay.gd/ mit Konsole openssl Client eine Verbindung nicht in der Lage:"Tlsv1 Alarm interner Fehler" während Handshake

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: 

Diese Webseite scheint gut zu öffnen mit webbrowser oder curl konnte ich jedoch keine verbindung zu openssl herstellen. Offenbar verwendet der Server TLS 1.2 mit ECDHE-ECDSA-AES128-GCM-SHA256 Chiffre, aber auch wenn ich die für openssl zwingen, es immer noch nicht: 0.9.8y:

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

ich verschiedene OpenSSL-Versionen ausprobiert habe , 1.0.1g und die neuesten 0.9.8zf und 1.0.2a. Ich habe auch versucht, dies auf mindestens 5 Servern (CentOS, Debian, OSX) ohne Glück auszuführen.

Jede andere Website scheinen gut zu handhaben, hier ein Beispiel für einen erfolgreichen Handshake-Ausgang ist:

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) 

Es ist schwer zu glauben, dass all diese OpenSSL-Versionen die gleichen Fehler haben, so denke ich dass ich etwas falsch mache.

Kann jemand empfehlen, wie man sich mit dieser bestimmten Website unter Verwendung von openssl verbindet?

+0

Ah, das hat funktioniert.Danke, Jeff. –

+0

Ich bin kein Experte SSL, aber von dem, was ich sehe, hatte nicht alle meine Server COMODO ECC-Stammzertifikat installiert, die Handshake fehlgeschlagen, bis ich dieses Zertifikat manuell installiert habe? Klingt das richtig? Eigentlich war mein Quellproblem mit der Verwendung von fsockopen() in PHP mit einem anderen Server verbunden, und dieses Problem wurde gelöst, indem fsockopen() gezwungen wurde, TLSv1 zu verwenden. Die piratbay.gd war ein Nebenproblem, das ich beim Ausprobieren verschiedener Dinge entdeckt habe und war nur neugierig, warum die Verbindung fehlschlägt. –

+0

Ok, ich habe den Post bearbeitet und mein erstes Problem dort aufgenommen. hmm ... angesichts Ihrer jüngsten Erkenntnisse über die Fehlkonfiguration des Remote-Servers ... Ich frage mich, warum Chrome-Browser oder curl scheinen keine Probleme mit dieser Domain zu erfahren. Vielleicht ist dies ein häufiger Fall und einige Software haben Umgehungsmöglichkeiten dafür. –

Antwort

11

Diese beiden sind eine schlechte Kombination:

-cipher ECDHE-ECDSA-AES128-GCM-SHA256 

Und:

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

OpenSSL 0.9.8 nicht voll EG-Unterstützung hat. Und es unterstützt nicht TLS 1.1 oder 1.2. Um die AEAD Cipher Suites zu erhalten, müssen Sie TLS 1.2 verwenden. Das bedeutet, dass Sie OpenSSL 1.0.0 oder höher (IIRC) benötigen.

OpenSSL 1.0.1 und 1.0.2 haben sie, also ist es wahrscheinlich besser, diese Versionen zu verwenden.


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

Der Befehl Sie suchen, ist: openssl s_client -connect thepiratebay.gd:443 -tls1_2 -servername thepiratebay.gd -CAfile XXX. -servername ruft SNI auf.

Wenn ich die Website traf, wurde der Server von AddTrust externe CA Root zertifiziert. Wenn Sie auf die Website klicken, wurde es von DigiCert High Assurance EV Stamm CA zertifiziert. Und wenn Sie erneut auf die Website klickten, wurde sie von COMODO ECC Certification Authority zertifiziert.

Die verschiedenen CAs und Konfigurationen sprechen mit einer verteilten Site hinter einem Load Balancer, wobei sich jeder teilnehmende Webserver in einer etwas anderen Konfiguration befindet.


Zusätzlich zu mehreren Webservern und Konfigurationen sind einige der Webserver selbst falsch konfiguriert. Sie sind falsch konfiguriert, weil sie nicht die Kette senden, die zum Erstellen eines Pfads für die Validierung erforderlich ist.

Die Kette sollte (1) das Serverzertifikat enthalten; (2) Untergeordnete CAs oder Zwischenprodukte, die die Kette zur "Wurzel" bilden. Für (2) kann es ein oder mehrere Zwischenprodukte geben.

Die Kette sollte nicht die Wurzel enthalten. Sie müssen die Wurzel haben, und es muss vertraut werden.


Diese Webseite scheinen jedoch zu öffnen feinen Web-Browser oder curl verwenden, ich einen Weg finden, um eine Verbindung zu ihm über openssl ...

Dies liegt daran, nicht in der Lage war, die Browser enthalten eine Liste von Hunderten von Root-CAs und Untergeordneten CAs aufgrund von Webserver-Fehlkonfigurationen :) Die Liste enthält AddTrust External CA-Root, DigiCert High Assurance EV Stamm CA und COMODO ECC Stammzertifizierungsstelle.


Kann jemand Rat, wie auf diese spezielle Website mit OpenSSL verbinden?

OK, für den OpenSSL-Befehl sollten Sie -CAfile verwenden. Normalerweise verwenden Sie einfach so etwas wie openssl s_client -connect ... -CAfile DigiCertHighAssuranceEVRootCA.crt (für den Server mit der Zertifizierung DigiCert High Assurance EV Stamm CA). Aber das wird in diesem Fall nicht funktionieren.

Sie müssen eine einzelne Datei mit den erforderlichen Stamm- und untergeordneten Zertifizierungsstellen erstellen. Die Datei sollte eine Verkettung der Stammzertifizierungsstellen und untergeordneten Zertifizierungsstellen im PEM-Format sein, die zum Erstellen eines Pfads zum Überprüfen des Serverzertifikats erforderlich sind. Es sieht so aus, als ob es mindestens 3 oder 4 Zertifikate benötigt.

Oder Sie könnten darauf verzichten, Ihre eigene Datei zu erstellen, und verwenden Sie etwas wie cacert.pem. Aber es gibt ein gewisses Risiko bei der Verwendung der CA Zoo (meine liebevolle Bezeichnung für sie). Für einige der Risiken, siehe Is cacert.pem unique to my computer?.

Programmatisch würden Sie SSL_CTX_load_verify_locations in OpenSSL verwenden. Die verkettete PEM-Datei wird über CAfile übergeben.

Ich bin mir nicht sicher, was Sie in PHP verwenden würden.


Verwandte, cacert.pem hat 155 Wurzeln und Untergebenen.

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

daher der Grund, warum Sie möchten, dass Ihre CAfile, um nur die notwendigen zu beschränken, die Website zu zertifizieren: Die meisten von ihnen sind nicht zu bestätigen, die Website thepiratebay.gd benötigt.


(Kommentar) nicht sicher, dies ist der richtige Thread zu fragen, aber jetzt frage ich mich, ob es eine Möglichkeit ist, einige dieser Überprüfungen auszulassen programmatisch Anzahl der falsch-negative Ergebnisse zu reduzieren ...

Ich würde wahrscheinlich nicht verzichten auf die Prüfungen. Jetzt, wo Sie verstehen, was vor sich geht, sollte es einfacher sein, mit dem System zu arbeiten, anstatt es aufzugeben.

Um es zu wiederholen, entweder:

  1. Verwenden Sie nur notwendig, Root und Untergeordnete CAs

    1. Sie es bauen, Verkettung von PEM-Zertifikate
    2. Datei erstellen piratebay-certs.pem
    3. hinzufügen notwendig CAs
  2. Verwenden Sie ein CA Zoo mit predifined vertrauenswürdigen Root und Untergeordnete CAs

    1. Sie es herunterladen
    2. cacert.pem

Die dritte Option ist die Website zu bekommen, um ihre Web-Server-Konfigurationen zu beheben . Aber wenn es bis jetzt nicht passiert ist, wird es wahrscheinlich nicht passieren. (Und es könnte eine Designentscheidung sein - die Site verwendet möglicherweise mehrere Zertifizierungsstellen, um sicherzustellen, dass keine CA die Site ausführen kann. Dies betrifft jedoch nicht die unvollständige Kette).


Und die allgemeinere Beobachtung:

ich einen PHP-Skript, die URLs Verfügbarkeit (grundsätzlich überprüft, soll das Skript für eine bestimmte URL true zurück, wenn die URL in Browser und vice geöffnet werden kann

kehrt

Abkehr von piratebay.gd insbesondere zufällige URLs überprüft, werden Sie wahrscheinlich cacert.pem verwenden. Das ist, weil eine zufällige Stichprobe von 1 Million Websites wahrscheinlich alle von ihnen verwenden.

Wenn piratebay.gd noch fehlschlägt, dann herausfinden, was aus cacert.pem fehlt, und dann:

cat cacert.pem > my-expanded-cacert.pem 
cat missing-cert.pem >> my-expanded-cacert.pem 
0

ich aus einem anderen Grunde die gleiche Fehlermeldung hatte: eine Menge von Servern verwendet SNI und dies kann produzieren dieser Fehler.

In meinem Fall (a C++ Client gemacht mit boost_asio + OpenSSL) Ich habe es fixiert den folgenden Code verwenden:

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

auch this SO answer sehen.

Verwandte Themen