某些HTTP客户端接受此证书,而其他HTTP客户端则不接受 . 什么可以有所作为?
Java拒绝它 .
((javax.net.ssl.HttpsURLConnection)new java.net.URL("https://www.lucidpress.com")
.openConnection())
.getInputStream()
javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:找不到与www.lucidpress.com匹配的主题备用DNS名称 . at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1715)at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:257) )sun.security.ssl.Handshaker.fatalSE(Handshaker.java:251)sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1168)at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java: 153)at sun.security.ssl.Handshaker.processLoop(Handshaker.java:609)at sun.security.ssl.Handshaker.process_record(Handshaker.java:545)at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java) :963)sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1208)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1235)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl . java:1219)at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:440)at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDele gateHttpsURLConnection.java:185)at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
Python请求拒绝它 .
import requests
requests.get('https://www.lucidpress.com')
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 55, in get
return request('get', url, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 456, in request
resp = self.send(prep, **send_kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 559, in send
r = adapter.send(request, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 382, in send
raise SSLError(e, request=request) requests.exceptions.SSLError: hostname 'www.lucidpress.com' doesn't match either of '*.lucidchart.com', 'lucidchart.com'
cURL接受了 .
$ curl -v https://www.lucidpress.com
关于connect()到www.lucidpress.com端口443(#0)尝试54.236.129.63 ...已连接成功设置证书验证位置:CAfile:无CApath:/ etc / ssl / certs SSLv3,TLS握手,客户端问候(1):SSLv3,TLS握手,服务器问候(2):SSLv3,TLS握手,CERT(11):SSLv3,TLS握手,服务器密钥交换(12):SSLv3,TLS握手,服务器完成(14):SSLv3, TLS握手,客户端密钥交换(16):SSLv3,TLS更改密码,客户端问候(1):SSLv3,TLS握手,完成(20):SSLv3,TLS更改密码,客户端问候(1):SSLv3,TLS握手,已完成(20):使用DHE-RSA-AES256-SHA服务器证书进行SSL连接:主题:OU =域控制验证; CN = * .lucidpress.com开始日期:2014-05-12 16:20:34 GMT到期日期:2015-07-09 22:19:45 GMT subjectAltName:www.lucidpress.com匹配发行人:C = US; ST =亚利桑那; L =斯科茨; O = GoDaddy.com,Inc . ; OU = HTTP://certs.godaddy.com/repository/; CN = Go Daddy安全证书颁发机构 - G2 SSL证书验证确定 .
wget拒绝它 .
wget https://www.lucidpress.com
--2014-08-09 19:55:41-- https://www.lucidpress.com/解析www.lucidpress.com(www.lucidpress.com)...... 107.23.98.6,54.236.129.63,54.88 .154.168连接到www.lucidpress.com(www.lucidpress.com)| 107.23.98.6 |:443 ...已连接 . 错误:没有证书主题替代名称与请求的主机名称“www.lucidpress.com”匹配 . 要不安全地连接到www.lucidpress.com,请使用“--no-check-certificate” .
Chrome,FF和IE接受它 .
为什么行为不同?
1 回答
简短的回答:负载 balancer ,虚拟主机和SNI .
答案很长......首先,这是对证书的分析 . 我们需要做到这一点,以确保没有明显的错误 .
从下面的转储中,公共名称中有一个通配符DNS名称 . IETF和CA /浏览器论坛都不推荐在CN中放置DNS名称 . “友好名称”应放在CN中,因为它会显示给用户 . 虽然它已被弃用,但并未被禁止 .
相反,DNS名称应该包含主题备用名称 . 应该有两个 . 第一个是
lucidpress.com
,第二个是*.lucidpress.com
. 您只需lucidpress.com
因为通配符需要匹配标签 .作为参考,IETF在RFC 6125第3.1节服务器标识中弃用CN中的DNS名称;第6.4.4节检查通用名称 .
CA /浏览器论坛在Baseline Requirements(BR)第9.2.2节“主题公共名称”字段中弃用CN中的DNS名称 . 此外,根据CA / B,主题替代名称是必需的 . 请参见第9.2.1节“主题备用名称扩展” .
相关:RFC 6125,第6.4.3节,也不允许
*.lucidpress.com
与lucidpress.com
匹配 . CA / B BR在第11.1.3节中介绍了通配符,但没有讨论匹配规则 .有了上面的背景信息和下面的证书,这里是正在发生的事情 .
您在默认证书中有2个名称 . 它默认由Apache服务,因为它的first virtual host in the configuration file .
lucidchart.com
*.lucidchart.com
Lucid Press'证书中有2个名字 .
lucidpress.com
*.lucidpress.com
我认为不同的是服务器名称指示(SNI) . 它是TLS扩展,因此您需要TLS 1.0或更高版本 . 那些没有问题的人可以获得Lucid Press认证并使用TLS 1.0或以上与SNI;那些有问题的人获得默认证书并使用SSLv3或没有SNI . Windows XP将使用TLS 1.0但不使用SNI,因此由于部署基础,它经常在现场使用 .
浏览器接受它,因为它们使用TLS 1.0或更高版本并发送SNI扩展 . 因为SNI允许您的Apache服务器在握手期间选择适当的证书,所以没有名称匹配问题 .
Java拒绝它,因为它使用SSLv3,即使你说
SSLContext.getInstance("TLS");
. 你必须跳过一些箍,以确保你真正获得TLS 1.0及以上 . 有关Stack Overflow的一些问题 . 例如,参见Which Cipher Suites to enable for SSL Socket? .Python
拒绝它,因为我猜你正在使用2.x,或者你正在允许SSLv3 . 你需要3.0或更高才能获得SNI . 请参阅Python FAQ上的Python 3 Support? .wget
在version 1.14中添加了对SNI的支持 . 我怀疑wget
没有启用它或使用SSLv3 .cURL
可能确保使用SNI(如果可用) . 丹尼尔是非常彻底的,他试图确保无故障体验和开箱即用的安全姿势 .在OpenSSL转储中,感兴趣的选项是
-tls1 -servername
. 您可以通过省略-servername
来获得没有SNI的TLS . 所以你需要tls1
和-servername <host>
.如果有兴趣,这是来自
sslscan
: