HTTPS 与 TLS 实战指南:深入理解其工作原理
您已经在浏览器中见过那个小锁图标,也知道 HTTPS 很重要。但您真的理解当浏览器连接到 HTTPS 网站时发生了什么吗?许多开发者把 TLS 当作一个黑盒——配置一次就忘了。这能行得通,直到出现问题、性能下降或安全审计发现错误配置。
本指南以实用方式解释 HTTPS 和 TLS。您将了解握手过程、证书如何建立信任,以及在服务器上正确实施 TLS 的步骤。没有过多的术语——只提供您调试问题和做出明智决策所需的概念。
HTTPS 究竟是什么
HTTPS 是运行在 TLS(传输层安全协议)之上的 HTTP。它提供三项保证:
- 加密:客户端和服务器之间交换的数据对窃听者不可读。
- 身份验证:客户端验证它正在与合法的服务器通信,而不是冒充者。
- 完整性:数据在传输过程中无法被修改而不被发现。
TLS 是实现这一点的协议。SSL 是其前身——您仍然会在营销材料中看到“SSL 证书”,但现代系统使用 TLS(目前 TLS 1.3 是最新版本)。
TLS 握手:分步解析
在任何 HTTP 数据流动之前,客户端和服务器执行握手以协商加密参数并验证身份。以下是 TLS 1.3(现代标准)的简化流程:
- 客户端问候:浏览器发送支持的密码套件列表、TLS 版本和一个随机值(客户端随机数)。
- 服务器问候:服务器选择一个密码套件,发送自己的随机值(服务器随机数),并提供其证书链。
- 密钥交换:使用临时 Diffie-Hellman(或类似算法),双方在不直接传输的情况下推导出共享密钥。这提供了前向保密性——以后即使服务器私钥被泄露,也不会解密过去的会话。
- 证书验证:客户端根据受信任的根 CA 检查证书,验证域名,并检查有效期和吊销状态。
- 完成:双方发送 MAC(消息认证码)以确认握手未被篡改。加密的 HTTP 流量开始传输。
TLS 1.3 将握手减少到一次往返(1-RTT),并支持 0-RTT 恢复以改善回访用户的延迟。TLS 1.2 需要两次往返。
证书:信任锚点
TLS 证书将公钥绑定到域名,并由证书颁发机构(CA)签名。当您的浏览器连接到 example.com 时,它会检查证书:
- 是否由信任存储中的 CA 签名(或链接到其中一个)。
- 是否与域名匹配(通过主题备用名称)。
- 是否在有效期内。
- 是否未被吊销(通过 OCSP 或 CRL,尽管执行情况各异)。
您可以从 Let's Encrypt 免费获得证书,它通过 ACME 协议颁发 90 天有效期的证书。Certbot 等自动化工具处理续期。对于内部服务,您可以运行自己的 CA,但客户端必须显式信任它。
在服务器上配置 TLS
正确的配置平衡安全性、兼容性和性能。以下是一份检查清单:
- 仅使用 TLS 1.2 和 1.3。禁用 TLS 1.0 和 1.1——它们已被弃用且存在漏洞。
- 选择强密码套件。优先使用 AES-GCM 或 ChaCha20-Poly1305 等 AEAD 密码。避免 CBC 模式和 RC4。
- 启用前向保密性。使用 ECDHE 密钥交换。
- 启用 OCSP 装订。服务器包含缓存的 OCSP 响应,减少客户端延迟和隐私泄露。
- 设置 HSTS 头部。强制浏览器在未来访问中使用 HTTPS。
- 将 HTTP 重定向到 HTTPS。确保不提供明文流量。
对于 Nginx,一个最小安全配置如下所示:
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-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://localhost:3000;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
使用 SSL Labs 的 SSL 测试或 testssl.sh 等工具测试您的配置。目标是获得 A 级评分,但如果您必须支持旧客户端,不要以牺牲兼容性为代价追求满分。
常见陷阱及如何避免
- 证书过期:自动化续期并监控到期时间。一张过期的证书就可能让您的网站下线。
- 混合内容:在 HTTPS 页面上加载 HTTP 资源会触发警告并破坏功能。使用相对 URL 或全站 HTTPS。
- 弱协议:TLS 1.0/1.1 已弃用。更新您的配置。
- 缺少中间证书:服务器必须发送完整链(根证书除外)。缺少中间证书会导致某些客户端出现信任错误。
- 不正确的重定向:在提供任何内容之前将 HTTP 重定向到 HTTPS,并使用 301 进行永久重定向。
常见问题
HTTPS 和 TLS 有什么区别?
HTTPS 是运行在 TLS 上的 HTTP。TLS 是提供加密、身份验证和完整性的密码学协议。没有 TLS 就没有 HTTPS。
www 和非 www 需要单独的证书吗?
您可以在单张证书的主题备用名称(SAN)字段中包含两者。大多数 CA 默认或通过简单配置颁发覆盖两者的证书。
我应该多久轮换一次 TLS 证书?
遵循 CA 的有效期——Let's Encrypt 为 90 天。使用 cron 作业或 systemd 定时器自动化续期。如果私钥被泄露,立即轮换。
准备好检查您的 Web 流量了吗?使用 Nginx 日志分析器 解析访问日志,验证 HTTPS 请求、状态码和潜在问题。