SSL证书链详解:为什么浏览器报证书不受信任
最近帮一个朋友排查SSL问题,他的网站证书明明有效,但部分浏览器报”证书不受信任”。检查后发现是证书链不完整——服务器只部署了域名证书,没部署中间证书。这个问题非常常见,这篇就把证书链讲清楚。
什么是证书链
SSL证书不是直接由根证书签发的,而是分层签发:
根证书(Root CA)
↓ 签发
中间证书(Intermediate CA)
↓ 签发
你的域名证书(你的网站)
证书链就是从你的域名证书一直追溯到根证书的完整路径。
为什么要分层:
- •根证书是信任锚,必须绝对安全,离线保存
- •中间证书负责日常签发,可以撤销和更换
- •分层降低根证书泄露风险
浏览器如何验证证书
浏览器验证网站证书的过程:
- 服务器发送证书(应该包含域名证书+中间证书)
- 浏览器收到证书,从域名证书开始向上追溯
- 用中间证书的公钥验证域名证书签名
- 用根证书的公钥验证中间证书签名
- 根证书在浏览器内置的信任库中,验证通过
关键点:如果服务器只发域名证书,不发中间证书,浏览器无法追溯到根证书,就会报”证书不受信任”。
证书链不完整的症状
典型表现:
- •PC浏览器显示绿色小锁,但手机浏览器报警告
- •Chrome正常,但Firefox/Safari报警告
- •部分老浏览器报”证书不受信任”
- •SSL检测工具报”Certificate chain incomplete”
为什么部分浏览器正常:现代浏览器会缓存中间证书,或主动下载缺失的中间证书。但老浏览器和移动端浏览器没这能力,就会报错。
如何检测证书链是否完整
方法1:在线工具
用 SSL测试工具 检测,会直接告诉你证书链是否完整,缺失哪个中间证书。
方法2:命令行检测
openssl s_client -connect example.com:443 -servername example.com
输出会显示服务器发送的证书链:
Certificate chain
0 s:CN=example.com # 你的域名证书
i:CN=ZeroSSL ECC Domain Secure Site CA # 颁发者
1 s:CN=ZeroSSL ECC Domain Secure Site CA # 中间证书(应该有)
i:CN=USERTrust ECC Certification Authority
如果只有 0 没有 1,说明中间证书没部署。
方法3:浏览器查看
点击地址栏小锁 → 查看证书 → 看证书路径。如果路径只有1层(域名证书),说明中间证书缺失。
如何获取中间证书
从CA官网下载:
- •ZeroSSL:控制台下载证书时会有
ca_bundle.crt - •Let’s Encrypt:自动包含在fullchain.pem中
- •DigiCert:订单页面下载”CA Bundle”
用OpenSSL获取:
# 查看证书的颁发者
openssl x509 -in cert.pem -text -noout | grep -A1 "Issuer"
# 下载中间证书(需要知道中间证书URL)
openssl s_client -showcerts -connect example.com:443 </dev/null
从sslmianfei.com下载的证书:
申请证书后下载的压缩包里包含:
- •
certificate.crt:你的域名证书 - •
ca_bundle.crt:中间证书链 - •
private.key:私钥
部署时需要合并这两个证书文件。
合并证书链
正确顺序:域名证书在前,中间证书在后
# 方法1:命令行合并
cat certificate.crt ca_bundle.crt > fullchain.pem
# 方法2:手动编辑
# 用记事本打开fullchain.pem,按顺序粘贴:
# 1. 你的域名证书内容
# 2. 中间证书内容
合并后的文件内容:
-----BEGIN CERTIFICATE-----
(你的域名证书,第一个)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(中间证书,第二个)
-----END CERTIFICATE-----
重要:
- •顺序不能反,域名证书必须在最前面
- •不要包含根证书(浏览器自带)
- •两个证书之间要有换行符
不同服务器的部署方式
Nginx部署:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/fullchain.pem; # 完整证书链
ssl_certificate_key /path/to/private.key; # 私钥
}
Apache部署:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/fullchain.pem # 完整证书链
SSLCertificateKeyFile /path/to/private.key # 私钥
# SSLCertificateChainFile 已废弃,合并到CertificateFile中
</VirtualHost>
宝塔面板部署:
- 网站 → 设置 → SSL → 其他证书
- 证书框粘贴
fullchain.pem的完整内容 - 私钥框粘贴
private.key的内容 - 保存 → 开启强制HTTPS
IIS部署:
IIS需要把证书和中间证书分别导入:
- 导入中间证书到”中间证书颁发机构”
- 导入域名证书到”个人”
- 绑定网站
常见的中间证书
ZeroSSL的中间证书链:
USERTrust ECC Certification Authority(根)
↓
Sectigo ECC Domain Validation Secure Server CA 2(中间)
↓
你的域名证书
Let’s Encrypt的中间证书链:
ISRG Root X1(根)
↓
R3(中间)
↓
你的域名证书
部署时把整个中间证书链都部署上即可。
证书链完整的好处
1. 浏览器兼容性
所有浏览器都能正确验证证书,避免部分用户看到警告。
2. 移动端兼容性
Android、iOS的浏览器通常不缓存中间证书,必须服务器完整发送。
3. SEO加分
Google把HTTPS作为排名因素,证书链不完整会影响HTTPS可用性。
4. 用户信任
用户看到警告会离开,完整的证书链避免这种情况。
证书链问题的排查流程
遇到证书报警告,按这个流程排查:
- 用 SSL测试工具 检测 → 看是否报证书链不完整
- 用 证书查看工具 解析证书 → 看颁发者信息
- 检查服务器发送的证书 →
openssl s_client -showcerts -connect example.com:443 - 合并完整证书链 → 域名证书 + 中间证书
- 重新部署 → 替换fullchain.pem
- 验证 → 用工具重新检测
中间证书过期问题
罕见但严重的问题:中间证书过期。
表现:
- •证书本身没过期,但浏览器报错
- •部分浏览器正常,部分报错
- •错误信息提到”证书路径中的证书已过期”
原因:CA的中间证书也有有效期,过期后签发的域名证书不受信任。
解决办法:
- •联系CA更换新的中间证书
- •重新申请证书
- •部署新的中间证书链
中间证书交叉签名
为兼容老设备,根证书会交叉签名多份中间证书:
旧根证书 → 中间证书A(旧设备识别)
新根证书 → 中间证书B(新设备识别)
你的域名证书可能由中间证书A或B签发,部署时都要加上。ZeroSSL和Let’s Encrypt都有交叉签名的情况。
关于OCSP装订
OCSP(在线证书状态协议)用于验证证书是否被撤销。
问题:浏览器每次访问都要查询OCSP服务器,影响速度,也泄露隐私(CA知道你访问了哪个网站)。
OCSP装订:服务器代为查询OCSP状态,把结果”装订”到TLS握手响应中。
Nginx配置:
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
OCSP装订需要完整的证书链才能正常工作。
常见问题
Q:根证书需要部署吗?
A:不需要。根证书在浏览器和操作系统的信任库中,服务器只需要部署域名证书+中间证书。
Q:证书链顺序反了会怎样?
A:浏览器可能无法验证证书,报”证书不受信任”。Nginx会报警告日志。
Q:可以只部署域名证书吗?
A:不推荐。部分浏览器能自动下载中间证书,但不是所有浏览器都能。建议部署完整证书链。
Q:如何确认证书链是否正确?
A:用 SSL测试工具 检测,”证书链完整”一项应该是绿色。
Q:中间证书可以撤销吗?
A:可以。CA可以撤销中间证书,签发在该中间证书下的所有域名证书都会失效。
最后
证书链不完整是SSL部署最常见的错误之一,90%的浏览器报警告都是这个原因。
核心就三步:
- 获取中间证书(从CA下载或用OpenSSL提取)
- 合并证书链(域名证书在前,中间证书在后)
- 部署到服务器(用fullchain.pem替换原证书)
部署完成后用 SSL测试工具 检测一遍,确认证书链完整。希望这篇能帮你解决证书链问题。