7.5.1 HTTPS原理与证书体系
HTTPS 是在 HTTP 之上通过 TLS 提供加密、身份认证与数据完整性保护的协议栈。Nginx 常作为 TLS 终止点负责证书链下发与加密通信建立。本节聚焦原理与证书体系,并给出可执行示例、常用命令与排错思路。
HTTPS/TLS 原理草图
sequenceDiagram
participant C as Client
participant S as Nginx Server
participant CA as CA
C->>S: ClientHello(TLS版本/套件/SNI)
S->>C: ServerHello(选择套件/证书链)
C->>CA: 验证证书链与域名
CA-->>C: 证书有效/无效
C->>S: 密钥协商(ECDHE)
S->>C: Finished
C<->>S: 加密HTTP数据传输
证书体系与信任链
- 根证书 Root CA:预置在浏览器/系统信任库。
- 中间证书 Intermediate CA:由根 CA 签发,降低根证书暴露风险。
- 服务器证书 Leaf:绑定域名与公钥;应包含完整链(不含根)。
- 信任链校验:客户端从 Leaf 往上验证至受信任根。
核心概念与字段
- 公钥/私钥:私钥必须保密;公钥包含于证书。
- CSR:证书签名请求,包含主体与公钥信息。
- SAN:多域名支持字段,现代浏览器以 SAN 为准。
- 证书类型:DV/OV/EV,按业务合规与验证级别选择。
示例:本地生成测试证书(演示原理)#
仅用于学习/测试,生产请使用可信 CA(如 Let’s Encrypt)
1)生成私钥与 CSR
# 生成私钥
openssl genrsa -out /etc/nginx/ssl/demo.key 2048
# 生成 CSR(包含 SAN)
cat >/etc/nginx/ssl/openssl.cnf <<'EOF'
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = CN
ST = BJ
L = Beijing
O = DemoOrg
CN = demo.example.com
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = demo.example.com
DNS.2 = www.demo.example.com
EOF
openssl req -new -key /etc/nginx/ssl/demo.key \
-out /etc/nginx/ssl/demo.csr -config /etc/nginx/ssl/openssl.cnf
2)自签发证书(学习用)
openssl x509 -req -in /etc/nginx/ssl/demo.csr \
-signkey /etc/nginx/ssl/demo.key \
-out /etc/nginx/ssl/demo.crt \
-days 365 -extensions req_ext -extfile /etc/nginx/ssl/openssl.cnf
3)验证证书信息
# 查看证书基本信息
openssl x509 -in /etc/nginx/ssl/demo.crt -noout -text | head -n 30
# 验证 SAN 是否包含域名
openssl x509 -in /etc/nginx/ssl/demo.crt -noout -text | grep -A2 "Subject Alternative Name"
示例:TLS 连接与握手检查#
# 查看 TLS 版本与证书链
openssl s_client -connect demo.example.com:443 -servername demo.example.com -showcerts
# 仅测试 TLS 1.2 / 1.3
openssl s_client -connect demo.example.com:443 -tls1_2 -servername demo.example.com
openssl s_client -connect demo.example.com:443 -tls1_3 -servername demo.example.com
预期效果
- 输出中 Protocol 为 TLSv1.2/1.3
- Verify return code: 0 (ok) 表示证书链可信
Nginx 证书链文件示例(理解证书链)#
# 假设 CA 提供了证书链:server.crt + intermediate.crt
cat /etc/nginx/ssl/server.crt /etc/nginx/ssl/intermediate.crt \
> /etc/nginx/ssl/fullchain.crt
常见排错与定位#
1)证书不受信任
- 原因:证书链不完整或使用自签证书
- 排查:
openssl s_client -connect demo.example.com:443 -servername demo.example.com -showcerts \
| sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' > /tmp/chain.pem
# 验证链完整性(需提供受信根)
openssl verify -CAfile /etc/ssl/certs/ca-bundle.crt /tmp/chain.pem
2)域名不匹配
- 原因:证书 CN/SAN 不含访问域名
- 排查:
openssl x509 -in /etc/nginx/ssl/fullchain.crt -noout -text | grep -A2 "Subject Alternative Name"
3)协议/套件不兼容
- 原因:客户端不支持服务端 TLS 版本/套件
- 排查:
# 扫描支持的协议(nmap)
nmap --script ssl-enum-ciphers -p 443 demo.example.com
关键命令解释(理解用途)#
openssl genrsa:生成 RSA 私钥文件openssl req -new:根据私钥生成 CSRopenssl x509 -req:签发证书(此处为自签)openssl s_client:模拟客户端握手并查看证书链openssl verify:验证证书链可信性
练习#
- 生成一个包含两个域名的证书(使用 SAN),验证是否包含正确域名。
- 使用
openssl s_client连接一个公网 HTTPS 网站,记录其证书链中包含的证书数量。 - 使用
nmap --script ssl-enum-ciphers检查本机 Nginx 的 TLS 版本与加密套件。