HTTPS 与 TLS 工作原理:握手与证书详解
HTTPS 为何重要(以及为何常被误解)
你可能在浏览器中见过那个小锁图标,并想当然地认为该网站是“安全的”。但这到底意味着什么?HTTPS 不仅仅关乎加密;它还涉及身份认证、完整性和信任。许多开发者将 TLS 视为黑盒——配置一次后就抛诸脑后。这会导致配置错误、证书过期以及脆弱的密码套件。
在本文中,我们将拆解 HTTPS 和 TLS 的实际工作原理,从握手到证书验证,并展示如何正确设置。没有废话,只有你今天就能应用的实用知识。
TLS 握手:在第一个字节之前发生了什么
当客户端(浏览器)通过 HTTPS 连接到服务器时,它们会执行 TLS 握手。这建立了一个安全通道。以下是简化版本(TLS 1.3):
- Client Hello:客户端发送支持的密码套件、一个随机值和一个密钥共享(用于密钥交换)。
- Server Hello:服务器选择一个密码套件,发送自己的随机值和密钥共享,并出示其证书链。
- 身份验证:客户端根据受信任的 CA 验证服务器证书,并检查主机名。
- 密钥派生:双方使用 ECDHE(椭圆曲线 Diffie-Hellman 临时密钥交换)计算共享密钥。
- Finished:双方发送加密的“Finished”消息以确认握手完成。
此后,应用数据使用对称密钥加密。TLS 1.3 将往返次数减少到一次,从而改善延迟。
密钥交换:ECDHE 与 RSA
较旧的 TLS 版本使用 RSA 密钥交换,缺乏前向保密性。如果服务器的私钥被泄露,过去的流量可以被解密。现代设置使用 ECDHE,它提供前向保密性——每个会话都有唯一的密钥。
# 示例:检查支持的密钥交换算法
openssl s_client -connect example.com:443 -cipher 'ECDHE'
证书:信任锚点
证书将公钥绑定到身份(域名)。它由客户端信任的证书颁发机构(CA)签名。浏览器附带一个受信任根 CA 的存储库。
当你访问一个网站时,服务器会发送一条链:叶子证书(用于你的域名)→ 中间 CA → 根 CA。客户端验证每个签名,直到受信任的根。
证书类型
- 域名验证(DV):仅证明对域名的控制权。快速且免费(例如 Let's Encrypt)。
- 组织验证(OV):包含经过验证的组织详细信息。
- 扩展验证(EV):更严格的审查;浏览器不再显示绿色地址栏,但一些企业仍在使用。
证书验证步骤
浏览器检查:
- 签名链指向受信任的根。
- 证书在有效期内。
- 主机名匹配(主题备用名称)。
- 证书未被吊销(通过 OCSP 或 CRL)。
如果任何检查失败,你会收到警告。在生产环境中永远不要绕过这些警告。
在服务器上配置 HTTPS
让我们看一个典型的 Nginx 配置,使用现代 TLS 设置启用 HTTPS。
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# HSTS(谨慎使用)
add_header Strict-Transport-Security "max-age=63072000" always;
}
说明:
- 仅使用 TLS 1.2 和 1.3;禁用旧版本。
- 优先使用 ECDHE 密码套件以实现前向保密性。
- 启用 HTTP/2 以提升性能。
- HSTS 强制浏览器使用 HTTPS;仅在测试后启用。
使用 Let's Encrypt 获取证书
Let's Encrypt 提供免费的 DV 证书。使用 Certbot 自动化签发和续期:
sudo certbot --nginx -d example.com -d www.example.com
Certbot 会修改你的 Nginx 配置并设置 cron 任务进行续期。始终使用 --dry-run 测试续期。
常见陷阱及如何避免
- 证书过期:设置监控和自动续期。
- 证书链不完整:包含中间证书(fullchain.pem)。
- 弱密码:禁用 RC4、DES 和出口密码。
- 混合内容:确保所有资源(图片、脚本)通过 HTTPS 加载。
- 无 HSTS:没有 HSTS,用户可能被降级到 HTTP。
测试你的 HTTPS 配置
使用 SSL Labs 等在线工具或命令行工具来验证你的设置。
# 检查证书详情
openssl s_client -connect example.com:443 -servername example.com | openssl x509 -noout -text
# 测试 TLS 1.3 支持
openssl s_client -connect example.com:443 -tls1_3
查找:
- 有效的证书链。
- 没有弱协议(SSLv3、TLS 1.0、TLS 1.1)。
- 启用了前向保密性。
- 存在 HSTS 头。
常见问题解答
TLS 和 SSL 有什么区别?
SSL 是 TLS 的前身。TLS 1.0 本质上是 SSL 3.1。如今,“SSL”常被口语化使用,但你应该始终使用 TLS 1.2 或 1.3。
我需要付费证书才能使用 HTTPS 吗?
不需要。来自 Let's Encrypt 的免费 DV 证书被所有主流浏览器信任,并提供与付费证书相同的加密强度。付费证书提供保证和支持,但加密是相同的。
HTTPS 如何影响性能?
TLS 由于握手会增加延迟,但 TLS 1.3 将其减少到一次往返。通过会话恢复和 HTTP/2,开销很小。在现代 CPU 上,加密/解密成本很低。
准备好检查你服务器的 TLS 配置了吗?使用我们的 Nginx 日志分析器 来发现异常流量模式,并确保你的 HTTPS 设置按预期工作。