调试javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚

时间:2016-07-01 19:07:30

标签: java android ssl nginx websocket

我正在尝试使用a WebSocket client(在Android上)通过安全wss连接到NGINX代理。

我有两个服务器,一个在Intranet中,一个在AWS上。

尝试连接到本地服务器时,连接失败并显示javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

当连接到AWS上的服务器时,我得到一个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 Found ,这是预期的,因为AWS上的NGINX实例尚未配置为切换协议并连接到上游websocket服务器。这是在本地服务器上开发的。但这表明TLS / SSL正在AWS上工作,这对我来说已经足够了。

此外,与wss://echo.websocket.org的连接成功,消息也会回传。

现在,这是奇怪的事情:AWS上的NGINX实例(在docker容器内运行)具有与本地计算机上相同的代码库。两者都是在docker容器中运行的NGINX,卷以相同的方式安装,具有非常相似的配置文件。唯一不同的是域名和相关的SSL证书。

这些是来自Comodo(正SSL)的DV证书。我也尝试了相同结果的LetsEncrypt证书。

我不明白为什么这两个容器的行为如此不同,我找不到理由责备托管docker服务的服务器(两者都是Ubuntu 14.04)

所以我想要在Android客户端应用程序中剖析证书(及其链)。

如何打印证书链的内容?

Chrome浏览器与本地服务器的JavaScript连接可以在Android设备和PC上运行。

~~~~更新~~~~请不要回答下面的内容,因为我会把它分成一个单独的问题

好的,我在@CommonsWare 的帮助下取得了进展。以下是新问题,开始变得有趣。

Intranet中的服务器将自签名证书作为catchall https响应进行托管。其背后的逻辑是,如果来自互联网的某人通过https://<IP-INTRANET-GATEWAY&gt;访问该内部网的公共IP的IP地址,则会获得该虚拟证书。原因是它不应该返回Intranet的证书(https://intranet.example.com)。

具有不同证书的多个域名指向该IP地址https://intranet.example.comhttps://testing.intranet.example.com,因此为此IP提供了多个SSL证书

在NGINX中它将是:

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 / {
    ...
  }  
}  

这与AWS上的服务器不同,后者没有自签名证书。

知道为什么客户可以获得虚拟证书吗?

另外,如何在没有异常的情况下转储证书,例如为了分析AWS服务器返回的证书(+链)?

使用带有https的普通HttpURLConnection可以正常工作。

1 个答案:

答案 0 :(得分:2)

鉴于错误文本,getCause()上的

SSLHandshakeException可能会返回CertPathValidatorException。这有一个getCertPath()方法,它返回一个CertPath,它有一个代表链的getCertificates()方法。如果需要,这些证书应该能够转换为X509Certificate个对象,这些对象可以为您提供有关证书的各种详细信息。

  

“Internet Widgits Pty Ltd”,我想知道为什么要提供服务

我不知道,但对该字符串的互联网搜索听起来并不乐观。