1. HTTPS 基础概述
1.1 核心概念
- 为什么需要 HTTPS:HTTP 协议使用明文传输,容易遭受中间人攻击(Man-in-the-Middle Attack),导致信息被窃取(监听)或篡改(劫持)。HTTPS = HTTP + SSL/TLS,通过加密传输确保数据的机密性、完整性和身份认证。
- SSL/TLS:
- SSL (Secure Sockets Layer):早期安全协议,已废弃。
- TLS (Transport Layer Security):SSL 的继任者,目前主流使用 TLS 1.2 和 TLS 1.3。
- 作用层级:位于 OSI 模型中的表示层(应用层 HTTP 之下,传输层 TCP 之上)。
1.2 身份认证体系 (PKI)
- CA (Certificate Authority):数字证书认证机构,负责颁发和管理数字证书的权威机构。
- 证书链:
- 根证书:内置在操作系统或浏览器中,深受信任。
- 中间证书:由根证书签名,用于签名用户证书。
- 用户证书:部署在 Web 服务器上。
- 验证流程:浏览器接收到服务器证书后,会沿着证书链向上验证签名,直到受信任的根证书。同时还会检查证书有效期、域名匹配情况以及吊销状态(CRL/OCSP)。
1.3 HTTPS 工作流程 (握手简述)
- Client Hello:客户端发送支持的加密套件、随机数 R1。
- Server Hello:服务器确认加密套件,发送随机数 R2 和数字证书。
- 验证证书:客户端验证证书合法性,提取服务器公钥。
- 密钥交换:
- 客户端生成预主密钥 (Pre-Master Secret),用服务器公钥加密发送给服务器。
- 服务器用私钥解密获取预主密钥。
- 生成会话密钥:双方结合 R1, R2, Pre-Master Secret 生成最终的对称会话密钥。
- 加密通信:后续数据传输全部使用该对称密钥进行加密。
2. 数字证书管理
2.1 证书类型对比
| 类型 | 验证方式 | 颁发速度 | 浏览器标识 | 适用场景 |
|---|---|---|---|---|
| DV (Domain Validation) | 验证域名所有权 | 快 (几分钟) | 小锁标志 | 个人博客、中小网站 |
| OV (Organization Validation) | 验证企业身份 | 中 (3-5天) | 小锁标志 | 企业官网、电商平台 |
| EV (Extended Validation) | 严格的企业验证 | 慢 (5-7天) | 显示企业名称 (部分浏览器) | 金融机构、大型支付平台 |
2.2 证书保护范围
- 单域名:仅保护一个特定域名 (e.g.,
www.example.com)。 - 多域名 (SAN):一张证书保护多个不同的域名。
- 通配符 (Wildcard):保护主域名及其所有子域名 (e.g.,
*.example.com)。
2.3 【拓展】免费证书方案 (Let's Encrypt)
原文主要介绍了自签名证书和购买证书。在现代生产环境中,推荐使用 Let's Encrypt 获取免费的 DV 证书。
- 工具:
certbot或acme.sh。 - 特点:免费、自动化申请/续期(有效期 90 天)。
- 自动化命令示例:
# 使用 Certbot 为 Nginx 自动配置证书
certbot --nginx -d example.com -d www.example.com
3. Nginx HTTPS 实战配置
3.1 基础单机配置
生成自签名证书(仅用于测试):
# 生成私钥
openssl genrsa -out server.key 2048
# 生成证书签名请求 (CSR) 及自签名证书
openssl req -days 365 -x509 -sha256 -nodes -newkey rsa:2048 -keyout server.key -out server.crt
Nginx 配置:
server {
listen 443 ssl;
server_name www.example.com;
# 证书文件路径
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
# HTTP 强制跳转 HTTPS
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri; # 推荐使用 301 永久重定向
}
3.2 负载均衡 (LB) 场景配置
在集群架构中,通常在负载均衡层 (LB) 卸载 SSL 证书,后端服务器 (Web) 使用 HTTP 通信。
LB 节点配置 (处理 HTTPS):
upstream backend_servers {
server 172.16.1.8:80;
server 172.16.1.9:80;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
location / {
proxy_pass http://backend_servers;
# 关键:传递真实 Host 和 协议信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # 告诉后端这是 HTTPS 请求
}
}
Web 节点配置 (处理 PHP 等应用):
如果后端是 PHP (如 WordPress),需要告知应用层当前通过 HTTPS 访问,否则会出现资源加载错误(混合内容问题)或重定向循环。
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
# 显式告诉 PHP 当前是 HTTPS 环境
fastcgi_param HTTPS on;
}
4. 深度拓展:性能优化与安全加固
4.1 开启 HTTP/2
HTTP/2 相比 HTTP/1.1 有显著的性能提升(多路复用、头部压缩),且绝大多数浏览器只支持基于 HTTPS 的 HTTP/2。
server {
# 在 listen 指令后添加 http2
listen 443 ssl http2;
...
}
4.2 HSTS (HTTP Strict Transport Security)
为了防止 SSL 剥离攻击,强制浏览器在指定时间内只使用 HTTPS 访问网站。
server {
listen 443 ssl http2;
...
# 开启 HSTS,有效期 1 年,包含子域名
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
4.3 SSL 参数优化
为了提升握手速度和安全性,建议配置 Session 缓存和现代加密套件。
# 1. 优化会话缓存
ssl_session_cache shared:SSL:10m; # 10MB 缓存,可存储约 40000 个会话
ssl_session_timeout 1d; # 缓存有效期
# 2. 禁用不安全的协议 (如 SSLv3, TLS 1.0, TLS 1.1)
ssl_protocols TLSv1.2 TLSv1.3;
# 3. 推荐的加密套件 (Mozilla Intermediate configuration)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
4.4 常见问题排查
- 混合内容 (Mixed Content):
- 现象:浏览器地址栏虽然有锁,但显示黄色或灰色警告。
- 原因:HTTPS 页面中加载了 HTTP 资源(如图片、JS、CSS)。
- 解决:确保所有静态资源链接都使用
https://,或使用相对路径//example.com/image.jpg。 - 快速修复头:
add_header Content-Security-Policy "upgrade-insecure-requests";
- 重定向循环:
- 现象:浏览器提示“重定向次数过多”。
- 原因:LB 卸载 SSL 后,以 HTTP 请求后端;后端应用判断是 HTTP,又发起 301 重定向到 HTTPS,形成死循环。
- 解决:确保 Web 服务器识别
X-Forwarded-Proto头,或者在 Nginx/PHP 配置中显式设置 HTTPS 状态(如上文 3.2 所示)。
Comments NOTHING