为何OpenSSL获取的SSL证书与浏览器获取的不一致?
这种情况在HTTPS场景里挺常见的,我给你拆解几个最可能的核心原因:
1. 未指定SNI(最常见的坑)
现在很多服务器是多个域名共享同一个IP的,这时候客户端必须发送SNI(Server Name Indication)字段,告诉服务器你要访问的具体域名,服务器才会返回对应域名的证书。
老版本的OpenSSL(比如1.0.2及以前)默认不会自动发送SNI,这时候服务器会返回它的默认 fallback 证书(不是你要的api.paczkomaty.pl的证书),而Chrome/Firefox这类现代浏览器会自动发送SNI,所以拿到的是正确的目标证书。
你可以试试带SNI参数的OpenSSL命令重新获取:
openssl s_client -connect api.paczkomaty.pl:443 -servername api.paczkomaty.pl
然后从输出里提取-----BEGIN CERTIFICATE-----到-----END CERTIFICATE-----的部分,再和浏览器的证书对比,应该就能匹配上了。
2. CDN/负载均衡的节点差异
如果这个API域名用了CDN或者负载均衡服务,不同客户端可能被分配到不同节点:
- 浏览器可能被导向CDN边缘节点,拿到的是CDN提供的证书
- OpenSSL直接连接的是源站服务器,拿到的是源站自有证书
或者反过来,也可能是DNS解析差异:本地DNS给OpenSSL返回的是源站IP,给浏览器返回的是CDN节点IP。
你可以先查域名解析的IP:
nslookup api.paczkomaty.pl
再对比浏览器访问时的实际连接IP(Chrome可在开发者工具「网络」标签里查看请求的远程IP),如果IP不一样,那就是这个原因。
3. 证书链层级混淆
浏览器会自动展示完整的证书链(包括叶子证书、中间CA证书、根证书),有时候你可能在浏览器里误看了中间CA的证书,而OpenSSL提取的是叶子证书,或者反过来。
你可以用OpenSSL查看证书的详细信息,确认拿到的是哪一环:
# 假设证书已保存为cert.pem openssl x509 -in cert.pem -text -noout
对比浏览器里证书的序列号、有效期,就能判断是不是拿错了证书链里的某一层。
4. 浏览器缓存了旧证书
虽然概率不高,但如果浏览器之前访问过这个网站,可能缓存了旧版本的证书(也就是你看到的2018年那版)。你可以尝试清空浏览器的SSL缓存,或者用隐私窗口重新访问,看看证书是否和OpenSSL获取的一致。
内容的提问来源于stack exchange,提问作者dr_

