2016-07-01 17 views
0

Ich versuche a WebSocket client (unter Android) zu verwenden, um über einen sicheren wss eine Verbindung zu einem NGINX-Proxy herzustellen.Debugging javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Vertrauensanker für Zertifizierungspfad nicht gefunden

Ich habe zwei Server, einen im Intranet und einen AWS.

Wenn auf dem lokalen Server zu verbinden versuchen, scheitert die Verbindung mit einem javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Wenn auf den Server, auf AWS Verbindungs ​​ich ein com.neovisionaries.ws.client.OpeningHandshakeException: The status code of the opening handshake response is not '101 Switching Protocols'. The status line is: HTTP/1.1 404 Not Founderhalten, die zu erwarten ist, weil die NGINX Instanz auf AWS nicht gewesen konfiguriert, um das Protokoll zu wechseln und eine Verbindung zum Upstream-Websocket-Server herzustellen. Dies wird auf dem lokalen Server entwickelt. Aber das ist ein Hinweis darauf, dass TLS/SSL an AWS arbeitet, was für mich ausreicht.

Auch eine Verbindung zu ist erfolgreich und Nachrichten werden zurückgesendet.

Jetzt ist die seltsame Sache: Die NGINX-Instanz in AWS, die in einem Docker Container ausgeführt wird, hat die gleiche Codebasis wie die auf dem lokalen Computer. Bei beiden handelt es sich um NGINXs, die in einem Andock-Container ausgeführt werden, die Volumes werden auf die gleiche Weise mit sehr ähnlichen Konfigurationsdateien gemountet. Das einzige, was sich unterscheidet, ist der Domainname und die zugehörigen SSL-Zertifikate.

Das sind DV-Zertifikate von Comodo (Positive SSL). Ich habe auch LetsEncrypt-Zertifikate mit dem gleichen Ergebnis versucht.

Ich verstehe nicht, warum die beiden Behälter so unterschiedlich verhalten, und ich kann keinen Grund, die Schuld, die Server-Hosting der Docker Service (beide Ubuntu 14.04)

So will ich sezieren das finden Zertifikate (und ihre Kette) in der Android-Client-Anwendung.

Wie kann ich den Inhalt der Zertifikatskette drucken?

Chrome Browser JavaScript wss Verbindungen zum lokalen Server funktionieren, sowohl vom Android-Gerät als auch von PCs.

~~~~ aktualisieren ~~~~ Bitte antworten Sie nicht auf die Sachen unten, wie ich es in eine separate Frage gespalten wird

Ok, ich fortgeschritten mit Hilfe von @CommonsWare . Hier sind neue Fragen, die interessant werden.

Der Server im Intranet hostet ein selbstsigniertes Zertifikat als Catchall-HTTPS-Antwort. Die Logik dahinter ist, dass wenn jemand aus dem Internet die IP-Adresse der öffentlichen IP dieses Intranets über https://<IP-INTRANET-GATEWAY> besucht, wird es dieses Dummy-Zertifikat geliefert. Der Grund dafür ist, dass das Zertifikat für das Intranet nicht zurückgegeben werden sollte (https://intranet.example.com).

Mehrere Domain-Namen mit verschiedenen Zertifikaten verweisen auf diese IP-Adresse https://intranet.example.com, https://testing.intranet.example.com, so gibt es mehrere SSL-Zertifikate diente für diese IP-

In NGINX wäre es:

server {  
    listen 443; 
    server_name _; 
    ssl on; 
    ssl_certificate  /etc/nginx/self-signed-dummy.pem; 
    ssl_certificate_key /etc/nginx/self-signed-dummy.key; 
    location/{ 
    return 404; 
    } 
} 

server {  
    listen 443; 
    server_name intranet.example.com; 
    ssl on; 
    ssl_certificate  /etc/nginx/intranet.example.com.pem; 
    ssl_certificate_key /etc/nginx/intranet.example.com.key; 
    location/{ 
    ... 
    } 
} 

server {  
    listen 443; 
    server_name testing.intranet.example.com; 
    ssl on; 
    ssl_certificate  /etc/nginx/testing.intranet.example.com.pem; 
    ssl_certificate_key /etc/nginx/testing.intranet.example.com.key; 
    location/{ 
    ... 
    } 
} 

Dies ist ein Unterschied an den Server in AWS, auf dem kein selbstsigniertes Zertifikat vorhanden ist.

Eine Idee, warum der Client das Dummy-Zertifikat erhalten konnte?

Wie kann ich das Zertifikat auch ohne Ausnahme ausgeben, um beispielsweise das vom AWS-Server zurückgegebene Zertifikat (+ Kette) zu analysieren?

Eine einfache HttpURLConnection mit https funktioniert ohne Probleme.

+2

'getCause()' auf der 'SSLHandshakeException' gibt wahrscheinlich eine' CertPathValidatorException' zurück. Das hat eine 'getCertPath()' Methode, die einen 'CertPath' zurückgibt, der eine' getCertificates() 'Methode hat, die die Kette darstellt. – CommonsWare

+0

Ja, danke! "Internet Widgits Pty Ltd" und ich frage mich, warum das serviert wird. Du hast mir geholfen. Setzen Sie eine Antwort ein und ich werde es akzeptieren. –

Antwort

2

getCause() auf die SSLHandshakeException gibt wahrscheinlich eine CertPathValidatorException, angesichts des Textes des Fehlers. Das hat eine getCertPath() Methode, die eine CertPath zurückgibt, die eine getCertificates() Methode hat, die die Kette darstellt. Bei Bedarf können diese Zertifikate in X509Certificate Objekte umgewandelt werden, die Ihnen eine Vielzahl von Details über das Zertifikat geben.

„Internet Widgits Pty Ltd“ und ich frage mich, warum die

Ich weiß es nicht, sondern eine Internet-Suche auf dieser Zeichenfolge klingt nicht viel versprechend serviert bekommen.

+0

Ich habe die Frage aktualisiert. Mein NGINX-Server im Intranet liefert ein Dummy-Zertifikat für alle Standardtreffer, die keiner bestimmten Domäne entsprechen. Es ist dieses Zertifikat. –

+0

@DanielF: "Irgendeine Idee, warum der Client das Dummy-Zertifikat erhalten könnte?" - Wenn der Server zusätzlich zu den WebSocket-Inhalten normale Seiten bereitstellt, sehen Sie sich an, wie sich eine gewöhnliche HTTPS-Anfrage verhält (z. B. OkHttp3 oder 'HttpURLConnection'). Wenn das gelingt, müssen Sie vielleicht etwas anderes für das WebSocket-Setup tun. "Wie kann ich das Zertifikat ohne Ausnahme ausgeben" - die einzige Möglichkeit, die ich kenne, ist die Implementierung eines eigenen 'X509TrustManager', damit Sie die Zertifikatskette für die Validierung bekommen können, aber das ist ein Problem. – CommonsWare

+0

Danke. Ich habe gerade überprüft, indem ich dieses Dummy-Zertifikat durch dasjenige der fraglichen Domain ersetzt habe, und es funktioniert. Offensichtlich ist dies ein Workaround, aber es ist ein guter Ausgangspunkt. Ich teile die Frage in eine neue und teste deine Empfehlung. Ich bin nicht scharf darauf, einen benutzerdefinierten X509TrustManager zu implementieren, da die Dinge in Zukunft noch weiter gehen könnten (dh in einigen Jahren, wenn Änderungen an den Zertifikaten vorgenommen werden). Es ist auch seltsam, dass WebViews keine Probleme damit haben. Es kann ein Implementierungsproblem der WebSocket-Bibliothek sein, weshalb ich als nächstes Ihre https-Empfehlung überprüfen werde –