# 安装中间证书：修复 SSL 证书链不完整

> 找到正确的中间证书，按正确顺序合成完整证书链，安装到 Nginx、Apache、IIS、HAProxy、Tomcat、Node.js，并验证；附阿里云/腾讯云证书包说明。

Source: https://ssl.sh/zh/guides/install-intermediate-certificate/
Last updated: 2026-11-10

安装中间证书，就是让服务器在站点证书后面按顺序发送签发它的中间证书。证书链完整后，curl、Java、手机 App、微信小程序这类不会自动补全中间证书的客户端也能正常连接。方法适用于任意 CA，以及 Nginx、Apache 2.4.8+、HAProxy、Tomcat、Node.js 和 IIS。

## 前提条件

需要站点证书、私钥和服务器的 Shell 权限。

- 已安装的站点证书（`example.com.crt` 或 `cert.pem`）和私钥。
- 一台能上网的机器上装有 OpenSSL 1.1.1 或 3.x。
- IIS 需要管理员 PowerShell。

## 第一步：查看服务器当前发送的证书

用 openssl 列出服务器实际发送的证书，输出里只有深度 0 一条就是缺中间证书：

```bash
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null | grep -E '^ *[0-9] s:|^ *i:'
```

[SSL 证书检查](https://ssl.sh/zh/tools/ssl-checker/) 遇到这种情况会提示“证书链不完整”。

## 第二步：拿到正确的中间证书

优先用 CA 或 ACME 客户端给的证书包：Certbot 的 `fullchain.pem` 和 `chain.pem`、acme.sh 的 `fullchain.cer`、商业 CA 的 CA bundle，或云厂商下载包里的证书链文件。只有站点证书时，读出 CA Issuers 地址下载签发者证书：

```bash
openssl x509 -in example.com.crt -noout -ext authorityInfoAccess
curl -fsSL -o intermediate.der "http://ca-issuers.example.net/intermediate.crt"
openssl x509 -inform DER -in intermediate.der -out intermediate.pem 2>/dev/null || cp intermediate.der intermediate.pem
```

把 URL 换成第一条命令输出的地址。把证书粘贴到 [证书链生成器](https://ssl.sh/zh/tools/chain-builder/) 也能自动完成这一步。

## 第三步：按正确顺序合成完整证书链

站点证书在前，后面依次是中间证书，每张都由下一张签发：

```bash
cat example.com.crt intermediate.pem > fullchain.pem
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout
```

输出里每张证书的 issuer 必须等于下一张的 subject。再用系统信任存储验证：

```bash
openssl verify -untrusted intermediate.pem example.com.crt
```

## 第四步：配置服务器

多数服务器直接读取完整证书链文件，Tomcat 和 IIS 例外。

**Nginx**：`ssl_certificate` 指向完整证书链。

```nginx
ssl_certificate     /etc/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/example.com/example.com.key;
```

**Apache 2.4.8+**：`SSLCertificateFile` 使用完整证书链，`SSLCertificateChainFile` 已经过时。

```apache
SSLCertificateFile    /etc/ssl/example.com/fullchain.pem
SSLCertificateKeyFile /etc/ssl/example.com/example.com.key
```

**HAProxy**：一个 PEM 同时包含完整证书链和私钥，`cat fullchain.pem example.com.key > /etc/haproxy/certs/example.com.pem`。

**Tomcat**：`certificateChainFile` 只放中间证书（`intermediate.pem`），不放站点证书。

**Node.js**：`cert: fs.readFileSync('fullchain.pem')`。

**IIS**：把中间证书导入本机的中级证书颁发机构存储，IIS 会自动发送：

```powershell
Import-Certificate -FilePath C:\certs\intermediate.cer -CertStoreLocation Cert:\LocalMachine\CA
```

改完后重载服务（`sudo nginx -t && sudo systemctl reload nginx`、`sudo systemctl reload apache2` 等）。宝塔面板里把完整证书链整段粘贴到“证书（PEM 格式）”框即可。

## 验证

配置正确时，服务器同时发送站点证书和中间证书，检查结果不再提示“证书链不完整”。重载后用 [SSL 证书检查](https://ssl.sh/zh/tools/ssl-checker/) 从外部确认，或在终端运行：

```bash
curl ssl.sh/example.com
```

本地的 curl 使用自己的信任存储、不会自动补全中间证书，是很严格的测试：

```bash
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com
```

## 自动续期

CA 会轮换中间证书，Let's Encrypt 这些年也多次更换证书层级，手工拼好的证书链会随之过时。ACME 客户端每次续期都会给出当前的证书链：服务器直接引用 Certbot 的 `fullchain.pem`、acme.sh 的 `--fullchain-file` 或 lego 打包好的 `.crt`，不要引用单独保存的中间证书。商业证书和云厂商证书每次重新签发后都要重新下载整个证书包。证书最长 200 天（2029 年 3 月 15 日起 47 天），能用 ACME 就自动化，并把域名加到 [ssl.sh 监控](https://ssl.sh/zh/monitor/)（开发中），证书链不完整时会提醒。

## 常见问题排查

- **curl: (60) SSL certificate problem: unable to get local issuer certificate**：中间证书仍然缺失，见 [curl 60 错误](https://ssl.sh/zh/errors/curl-60-ssl-certificate-problem/)。
- **Java 报 PKIX path building failed**：见 [PKIX path building failed](https://ssl.sh/zh/errors/java-pkix-path-building-failed/)。
- **Node.js 报 UNABLE_TO_VERIFY_LEAF_SIGNATURE**：见 [UNABLE_TO_VERIFY_LEAF_SIGNATURE](https://ssl.sh/zh/errors/node-unable-to-verify-leaf-signature/)。
- **Firefox 报 SEC_ERROR_UNKNOWN_ISSUER**：见 [SEC_ERROR_UNKNOWN_ISSUER](https://ssl.sh/zh/errors/sec-error-unknown-issuer/)。
- **Nginx 报 key values mismatch 无法启动**：中间证书放在了站点证书前面，见 [nginx key values mismatch](https://ssl.sh/zh/errors/nginx-key-values-mismatch/)。
