Calcifer Calcifer 2
Linux

SSL证书链:一个被忽视的配置细节,让AWS服务集体罢工

2026/03/10 18:20 10 次阅读 王梓
打赏
✸ ✸ ✸

一个常见的错误

在 AWS API Gateway 配置自定义域名时,上传 SSL 证书后,控制台可能会弹出一个刺眼的错误:

Certificate chain is missing or incomplete.
The certificate must include the intermediate CA certificates.

很多人会疑惑:证书不是上传成功了吗?为什么还要什么"证书链"?

这篇文章,将详细解释证书链的作用和影响。

一、什么是证书链?

1.1 信任的传递

想象一下这个场景:你去银行办业务,柜员要求你出示身份证。你递过去一张卡片,柜员看了一眼说:"这张卡我无法验证真假,你需要再给我看发证机关的证明。"

SSL 证书也是同理。浏览器不认识你的证书,它需要一条信任链来验证:

🏛️ 根证书 Root CA DigiCert, Let's Encrypt... 预装在浏览器/系统中 签发 🔗 中间证书 Intermediate CA CA的"代理人" 需要配置到服务器 签发 🔐 服务器证书 Your Certificate 你的域名证书 example.com 信任链验证流程 1. 浏览器收到服务器证书 2. 查找中间证书 → 验证签名 3. 查找根证书 → 验证签名 4. 根证书在信任库中? ✓ 信任 5. 中间证书缺失? ✗ 信任链断裂 6. 根证书不在信任库? ✗ 不信任

1.2 为什么需要中间证书?

你可能会问:为什么不直接用根证书签发服务器证书?

方式安全性风险
根证书直接签发❌ 极低根证书私钥一旦泄露,所有证书都失效
中间证书签发✅ 高中间证书泄露只影响该中间证书下的证书

中间证书就像"代理人":根证书把签发权限委托给中间证书,自己则离线保存,大大降低风险。

二、证书链缺失的影响范围

2.1 AWS 服务影响全景图

AWS 服务对证书链的依赖程度 ❌ 严重影响 API Gateway 直接报错,无法配置自定义域名 CloudFront 警告提示,部分客户端无法访问 ELB/ALB 证书验证失败,HTTPS 不可用 Elastic Beanstalk 环境创建失败 ⚠️ 中等影响 EKS Ingress 需要额外配置证书链 ECS Service Discovery 服务间通信可能失败 App Runner 自定义域名配置受限 Lightsail 证书验证警告 ✓ 轻微/无影响 ACM 托管证书 ACM 自动管理证书链 S3 静态网站 需配合 CloudFront 使用 Direct Connect 使用 IAM 证书,需完整链 IoT Core 设备证书需完整链 💡 关键结论 使用 ACM (AWS Certificate Manager) 申请的证书,AWS 自动管理证书链,无需手动配置 导入外部证书到 IAM/ACM 时,必须包含完整的证书链,否则多个服务会报错 🌍 客户端影响 Chrome/Edge: 自动缓存中间证书,可能正常访问 Firefox: 不缓存中间证书,直接报错 NET::ERR_CERT_AUTHORITY_INVALID curl/openssl: 报错 unable to get local issuer certificate 移动端 App: 取决于系统证书库,Android 较严格

2.2 API Gateway 为什么最严格?

API Gateway 是 AWS 中对证书链要求最严格的服务,原因如下:

API Gateway 证书验证流程 上传证书到 IAM 包含证书链? ❌ 验证失败 无法配置域名 ✓ 验证通过 配置成功 API Gateway 边缘证书

API Gateway 在边缘位置处理 HTTPS 请求,需要向客户端出示完整的证书链。如果证书链不完整:

  • 某些客户端(如 Firefox)会直接拒绝连接
  • API 调用失败,返回 SSL 握手错误
  • 影响所有依赖 API Gateway 的服务(如 Lambda、AppSync)

三、如何正确导入证书链

3.1 证书文件的组成

一个完整的证书文件应该包含:

-----BEGIN CERTIFICATE-----
服务器证书内容
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
中间证书内容(可能有多个)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
根证书内容(可选,通常不需要)
-----END CERTIFICATE-----

3.2 获取证书链的方法

方法一:从 CA 获取

大多数 CA 会提供一个压缩包,包含:

  • your_domain.crt - 服务器证书
  • intermediate.crt - 中间证书
  • ca-bundle.crt - 完整证书链

方法二:手动拼接

# 拼接服务器证书和中间证书
cat your_domain.crt intermediate.crt > fullchain.crt

# 或者按顺序拼接
cat your_domain.crt > fullchain.crt
cat intermediate1.crt >> fullchain.crt
cat intermediate2.crt >> fullchain.crt

方法三:从服务器获取

# 查看远程服务器的证书链
openssl s_client -connect example.com:443 -showcerts

# 导出证书链
openssl s_client -connect example.com:443 -showcerts /dev/null | openssl x509 -outform PEM > certchain.pem

3.3 验证证书链完整性

# 验证证书链
openssl verify -CAfile intermediate.crt your_domain.crt

# 验证完整证书链
openssl verify -CAfile ca-bundle.crt fullchain.crt

# 查看证书链信息
openssl crl2pkcs7 -nocrl -certfile fullchain.crt | openssl pkcs7 -print_certs -noout

3.4 如何检查证书链顺序?

证书链必须按照从下到上的顺序拼接,即:直接签发者 → 上级签发者 → 更上级签发者 → 根证书。顺序错误会导致验证失败。

如何确定顺序?

每个证书都有 subject(主题)和 issuer(签发者)信息。正确的顺序是:

  • 服务器证书的 issuer = 第一个中间证书的 subject
  • 第N个中间证书的 issuer = 第N+1个中间证书的 subject
  • 以此类推,直到根证书

快速检查命令:

# 查看每个证书的签发者和主题
openssl x509 -in file1.crt -noout -subject -issuer
openssl x509 -in file2.crt -noout -subject -issuer
openssl x509 -in file3.crt -noout -subject -issuer

# 输出示例:
# subject=CN = Intermediate CA 3
# issuer=CN = Intermediate CA 2    ← 说明 CA2 签发了 CA3

验证顺序是否正确:

# 验证证书链顺序
cat cert1.crt cert2.crt cert3.crt > chain.crt
openssl verify -CAfile chain.crt server.crt

# 输出 "OK" = 顺序正确
# 输出错误 = 顺序不对或缺少证书

如果顺序错了会怎样?

情况结果
AWS 导入可能成功(AWS 有时会自动调整)
客户端验证❌ 可能失败,报证书链错误
最佳实践❌ 必须按正确顺序

建议:用上面的命令检查每个文件的 subjectissuer,按签发关系排序。

3.5 导入到 AWS IAM

# 上传证书(必须包含证书链)
aws iam upload-server-certificate \
    --server-certificate-name my-cert \
    --certificate-body file://server.crt \
    --private-key file://server.key \
    --certificate-chain file://intermediate.crt

# 验证上传结果
aws iam get-server-certificate --server-certificate-name my-cert

3.6 导入到 AWS ACM

# 导入证书到 ACM
aws acm import-certificate \
    --certificate file://server.crt \
    --private-key file://server.key \
    --certificate-chain file://intermediate.crt \
    --region us-east-1

# 注意:ACM 证书只能用于特定的 AWS 服务
# API Gateway 和 CloudFront 要求证书在 us-east-1 区域

四、常见问题排查

4.1 如何判断证书链是否完整?

❌ 证书链不完整 • 只有一个 BEGIN CERTIFICATE 块 • openssl verify 返回错误 • 浏览器显示"证书不受信任" • AWS 控制台显示警告 ✓ 证书链完整 • 至少两个 BEGIN CERTIFICATE 块 • openssl verify 返回 OK • 浏览器显示绿色锁头 • AWS 控制台无警告

4.2 不同浏览器的行为差异

浏览器证书链缺失时的行为原因
Chrome/Edge可能正常访问自动缓存中间证书(AIA 扩展)
Firefox直接报错不缓存中间证书,严格验证
Safari可能正常访问依赖系统证书库
Android 浏览器可能报错取决于系统版本
iOS Safari可能正常访问依赖系统证书库
curl/openssl直接报错无缓存机制,严格验证

4.3 常见错误信息

错误信息原因解决方案
Certificate chain is missing未上传中间证书添加证书链
unable to get local issuer certificate证书链不完整检查中间证书顺序
certificate verify failed根证书不在信任库使用主流 CA 证书
SSL handshake failed证书格式错误检查 PEM 格式

五、最佳实践

5.1 推荐做法

✅ 推荐做法 1. 优先使用 ACM 申请证书 AWS 自动管理证书链和续期 2. 导入证书时包含完整链 服务器证书 + 中间证书 3. 使用自动化工具管理证书 cert-manager, Let's Encrypt ❌ 避免做法 1. 只上传服务器证书 缺少中间证书导致验证失败 2. 证书链顺序错误 服务器证书在前,中间证书在后 3. 使用自签名证书 客户端不信任,仅限测试环境

5.2 证书链检查脚本

#!/bin/bash
# 检查证书链完整性

CERT_FILE=$1

if [ -z "$CERT_FILE" ]; then
    echo "用法: $0 <证书文件>"
    exit 1
fi

echo "=== 证书链检查 ==="

# 统计证书数量
CERT_COUNT=$(grep -c "BEGIN CERTIFICATE" "$CERT_FILE")
echo "证书数量: $CERT_COUNT"

if [ "$CERT_COUNT" -lt 2 ]; then
    echo "⚠️ 警告: 证书链可能不完整(建议至少2个证书)"
else
    echo "✓ 证书链包含 $CERT_COUNT 个证书"
fi

# 提取并验证每个证书
echo ""
echo "=== 证书详情 ==="
openssl crl2pkcs7 -nocrl -certfile "$CERT_FILE" 2>/dev/null | \
    openssl pkcs7 -print_certs -noout 2>/dev/null | \
    grep -E "subject=|issuer="

# 验证证书链
echo ""
echo "=== 验证结果 ==="
if openssl verify -CAfile "$CERT_FILE" "$CERT_FILE" 2>/dev/null; then
    echo "✓ 证书链验证通过"
else
    echo "❌ 证书链验证失败"
fi

六、为什么 CloudFront 和 API Gateway 要求 us-east-1 区域的证书?

很多开发者会有这个疑问:"我的服务部署在 ap-northeast-1(东京)或 cn-north-1(北京),为什么证书非要放在 us-east-1?"

6.1 用一个比喻来理解

想象一下,你开了一家连锁餐厅:

  • 你的主厨房在东京(你的服务所在区域)
  • 外卖配送点遍布全球(CloudFront 边缘节点)
  • 营业执照(SSL 证书)需要挂在每个配送点

问题是:营业执照应该放在哪里?

  • 如果放在东京主厨房,全球 200+ 个配送点每次都要跨洋查询,太慢了
  • 如果放在一个统一的管理中心,所有配送点都能快速获取

AWS 选择了后者:us-east-1(弗吉尼亚)就是 AWS 的"全球管理中心"

6.2 技术层面的解释

CloudFront 的全球架构 us-east-1(弗吉尼亚) AWS 全球服务控制平面 边缘节点(东京) 边缘节点(新加坡) 边缘节点(法兰克福) 边缘节点(悉尼) 边缘节点(圣保罗) 所有边缘节点都从 us-east-1 获取证书配置 这样保证了全球一致的配置和快速分发

CloudFront 是全球服务,它的 200+ 个边缘节点分布在世界各地。这些节点需要:

  • 统一从某个地方获取证书配置
  • 快速响应全球用户的 HTTPS 请求

AWS 选择 us-east-1 作为全球服务的"控制平面"所在地,所有 CloudFront 的配置(包括证书)都存储在这里,然后分发到全球边缘节点。

6.3 不同服务的证书区域要求

服务证书区域要求原因
CloudFront必须 us-east-1全球服务,控制平面在 us-east-1
API Gateway(边缘优化)必须 us-east-1底层使用 CloudFront 分发
API Gateway(区域)与 API 同区域不经过 CloudFront,直接在区域内部处理
ALB/ELB与负载均衡器同区域区域服务,不涉及全球分发
App Runnerus-east-1使用 CloudFront 作为入口

6.4 中国区 AWS 和 Global AWS 的区别

AWS Global(国际区) • CloudFront 证书:us-east-1 • API Gateway 边缘优化:us-east-1 • ACM 可申请免费证书 • 证书自动续期 • 通配符证书支持 示例:你的服务在 ap-northeast-1 证书需要在 us-east-1 申请 CloudFront 自动从 us-east-1 分发 AWS China(中国区) • CloudFront 证书:cn-north-1 • API Gateway 边缘优化:cn-north-1 • ACM 不支持申请公网证书 • 需要导入外部证书到 ACM • 或使用 IAM 证书 示例:你的服务在 cn-northwest-1 证书需要在 cn-north-1 导入 中国区 CloudFront 从 cn-north-1 分发

6.5 实际案例:我在东京部署服务,证书放哪里?

场景:你的应用部署在 ap-northeast-1(东京),想用 CloudFront 加速。

重要说明:你不需要在 AWS 控制台手动选择证书区域。AWS 会自动检查证书所在区域,如果证书不在正确的区域,会直接报错。

# 步骤1:在 us-east-1 申请/导入证书
aws acm request-certificate \
    --domain-name example.com \
    --validation-method DNS \
    --region us-east-1

# 步骤2:在东京区域部署你的应用
# (Lambda、EC2、S3 等)

# 步骤3:创建 CloudFront 分发
# CloudFront 会自动从 us-east-1 获取证书
# 并分发到全球边缘节点

6.6 常见错误:证书区域不匹配

当你在 CloudFront 或 API Gateway 配置自定义域名时,如果证书不在正确的区域,AWS 会显示类似以下错误:

Error: Certificate must be in us-east-1 region for CloudFront distribution.

或者中文:
错误:证书必须位于 us-east-1 区域才能用于 CloudFront 分发。

为什么你看不到选择区域的选项?

因为证书区域是自动检测的,不是手动选择的:

  • 当你在 CloudFront 控制台配置自定义域名时,下拉列表只显示正确区域的证书
  • 如果证书不在 us-east-1,它根本不会出现在列表中
  • 你需要先切换到 us-east-1 区域的 ACM 控制台,在那里申请或导入证书

操作步骤:

  1. 切换 AWS 控制台区域到 us-east-1 (N. Virginia)
  2. 进入 ACM (Certificate Manager) 控制台
  3. 申请或导入证书
  4. 回到 CloudFront 或 API Gateway 配置自定义域名
  5. 此时下拉列表中会显示你的证书

官方文档说明:

"You must request an ACM certificate in the US East (N. Virginia) Region."
"You must import the certificate in the US East (N. Virginia) Region."

来源:AWS CloudFront 官方文档

为什么这样设计?

  • 证书只需要存储一份(在 us-east-1)
  • 全球 200+ 边缘节点自动同步
  • 更新证书时,只需在 us-east-1 操作一次

6.7 常见误区

误区正确理解
"我的服务在东京,证书也要在东京"CloudFront 是全球服务,证书需要在其控制平面所在区域(us-east-1)
"证书在 us-east-1 会影响性能"不会,证书配置只影响初始化,实际 HTTPS 握手在最近的边缘节点进行
"中国区也用 us-east-1"❌ 中国区独立运营,使用 cn-north-1 作为控制平面

6.8 快速参考

你的情况证书区域
Global AWS + CloudFrontus-east-1
Global AWS + API Gateway(边缘优化)us-east-1
Global AWS + API Gateway(区域)与 API 同区域
Global AWS + ALB与 ALB 同区域
中国区 AWS + CloudFrontcn-north-1
中国区 AWS + API Gatewaycn-north-1

七、总结

证书链就像身份证的防伪标识,缺少它,再真实的证书也无法被信任。在 AWS 环境中配置 SSL 证书,需要记住以下几点:

7.1 证书链完整性

要点说明
证书组成服务器证书 + 中间证书(按正确顺序拼接)
顺序规则直接签发者在前,上级签发者在后
验证命令openssl verify -CAfile chain.crt server.crt
常见错误只上传服务器证书,缺少中间证书

7.2 证书区域选择

服务类型证书区域原因
CloudFront / API Gateway(边缘优化)us-east-1(Global)或 cn-north-1(中国)全球服务的控制平面所在区域
ALB / NLB与负载均衡器同区域区域服务,无需跨区域
区域型 API Gateway与 API 同区域不经过 CloudFront

7.3 最佳实践

  • 优先使用 ACM 申请证书:AWS 自动管理证书链和续期
  • 导入外部证书时:确保包含完整证书链,顺序正确
  • 检查证书链:使用 openssl s_client 或 SSL Labs 测试
  • 注意区域要求:CloudFront 和边缘优化型 API Gateway 有特定区域要求

记住两个公式:

  • 完整证书 = 服务器证书 + 中间证书(按顺序)
  • 全球服务证书区域 = us-east-1(Global)或 cn-north-1(中国)

缺少中间证书,就是给 AWS 服务埋下一颗定时炸弹;选错证书区域,CloudFront 和 API Gateway 就会报错。掌握这两点,SSL 证书配置就不再是难题。

✸ ✸ ✸

📜 版权声明

本文作者:王梓 | 原文链接:https://www.bthlt.com/note/369662064-LinuxSSL证书链:一个被忽视的配置细节,让AWS服务集体罢工

出处:葫芦的运维日志 | 转载请注明出处并保留原文链接

📜 留言板

留言提交后需管理员审核通过才会显示