HTTPS 与 TLS/SSL
HTTPS(HTTP Secure)是 HTTP 的安全版本,通过 TLS/SSL 协议加密通信内容,保护数据在传输过程中的机密性和完整性。在现代 Web 中,HTTPS 已成为标配。
HTTPS 概述
HTTPS = HTTP + TLS/SSL,在 HTTP 和 TCP 之间加入安全层:
应用层 HTTP HTTP
| |
安全层 - TLS/SSL
| |
传输层 TCP TCP
| |
网络层 IP IP
HTTPS 的作用
数据加密:防止数据在传输过程中被窃听。即使被截获,也无法解密内容。
数据完整性:防止数据在传输过程中被篡改。通过消息认证码(MAC)验证数据完整性。
身份认证:验证服务器身份,防止钓鱼网站。通过数字证书确认服务器身份。
HTTPS 与 HTTP 的区别
| 特性 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 数据传输 | 明文 | 加密 |
| 安全性 | 低 | 高 |
| 性能 | 略快 | 略慢(握手开销) |
| 证书 | 不需要 | 需要 |
TLS/SSL 协议
TLS 与 SSL 的关系
SSL(Secure Sockets Layer)由 Netscape 开发,TLS(Transport Layer Security)是 IETF 基于 SSL 标准化的协议。
发展历程:
- SSL 1.0:未发布,存在安全问题
- SSL 2.0(1995):已弃用
- SSL 3.0(1996):已弃用
- TLS 1.0(1999):已弃用(2020 年)
- TLS 1.1(2006):已弃用(2020 年)
- TLS 1.2(2008):目前广泛使用
- TLS 1.3(2018):最新版本,更安全更快
现代浏览器只支持 TLS 1.2 和 TLS 1.3。
TLS 协议栈
TLS 协议由两层组成:
+-------------------+
| 应用层协议 |
+-------------------+
| TLS 握手协议 |
| TLS 密钥变更协议 |
| TLS 警告协议 |
+-------------------+
| TLS 记录协议 |
+-------------------+
| TCP |
+-------------------+
TLS 记录协议:负责数据的分段、压缩、加密和传输。
TLS 握手协议:协商加密算法和密钥。
密钥变更协议:通知对方切换到新密钥。
警告协议:传递错误和警告信息。
加密技术基础
HTTPS 依赖多种加密技术保护通信安全。
对称加密
对称加密使用同一个密钥进行加密和解密:
明文 --[密钥加密]--> 密文 --[密钥解密]--> 明文
常见算法:AES、ChaCha20、3DES
优点:速度快,适合大量数据加密。
缺点:密钥分发困难,需要安全地共享密钥。
非对称加密
非对称加密使用一对密钥:公钥和私钥。公钥加密的数据只能用私钥解密,私钥签名的数据可以用公钥验证。
明文 --[公钥加密]--> 密文 --[私钥解密]--> 明文
常见算法:RSA、ECC(椭圆曲线)
优点:解决了密钥分发问题,公钥可以公开。
缺点:速度慢,不适合大量数据加密。
混合加密
HTTPS 使用混合加密方案:
- 使用非对称加密协商对称密钥
- 使用对称密钥加密实际数据
这样既解决了密钥分发问题,又保证了加密效率。
数字签名
数字签名用于验证数据的来源和完整性:
数据 --[哈希]--> 摘要 --[私钥加密]--> 签名
验证:签名 --[公钥解密]--> 摘要 --[与原数据哈希比较]
数字证书
数字证书由证书颁发机构(CA)签发,包含:
- 证书持有者信息
- 公钥
- CA 签名
- 有效期
- 证书用途
证书链:根证书 -> 中间证书 -> 服务器证书
TLS 握手过程
TLS 1.2 握手
TLS 1.2 握手需要 2 个 RTT(往返时间):
客户端 服务器
| |
| ClientHello |
| (支持的加密套件、随机数) |
|------------------------------------------->|
| |
| ServerHello |
| (选定的加密套件、随机数) |
| Certificate(服务器证书) |
| ServerKeyExchange(可选) |
| ServerHelloDone |
|<-------------------------------------------|
| |
| ClientKeyExchange |
| (加密的预主密钥) |
| ChangeCipherSpec |
| Finished |
|------------------------------------------->|
| |
| ChangeCipherSpec |
| Finished |
|<-------------------------------------------|
| |
| 应用数据(加密) |
|<------------------------------------------>|
密钥生成过程:
- 客户端生成随机预主密钥(Pre-Master Secret)
- 用服务器公钥加密预主密钥,发送给服务器
- 双方使用预主密钥和两个随机数生成主密钥(Master Secret)
- 从主密钥派生出会话密钥(对称加密密钥、MAC 密钥等)
TLS 1.3 握手
TLS 1.3 简化了握手过程,只需 1 个 RTT:
客户端 服务器
| |
| ClientHello |
| (支持的加密套件、密钥共享) |
| (密钥推导材料) |
|------------------------------------------->|
| |
| ServerHello |
| (选定的加密套件、密钥共享) |
| EncryptedExtensions |
| Certificate |
| CertificateVerify |
| Finished |
|<-------------------------------------------|
| |
| Finished |
|------------------------------------------->|
| |
| 应用数据(加密) |
|<------------------------------------------>|
TLS 1.3 改进:
- 握手更快(1-RTT)
- 移除了不安全的加密算法
- 前向保密成为强制要求
- 支持 0-RTT 恢复
0-RTT 恢复
TLS 1.3 支持 0-RTT 恢复,客户端可以立即发送应用数据:
客户端 服务器
| |
| ClientHello + 0-RTT 数据 |
|------------------------------------------->|
| |
| ServerHello + 应用数据 |
|<-------------------------------------------|
注意:0-RTT 数据可能被重放攻击,不适用于非幂等请求。
证书体系
证书类型
DV(Domain Validation)证书:只验证域名所有权,适合个人网站。
OV(Organization Validation)证书:验证组织身份,显示公司名称。
EV(Extended Validation)证书:最严格的验证,浏览器地址栏显示公司名称(旧版浏览器)。
通配符证书:保护主域名和所有子域名,如 *.example.com。
多域名证书:保护多个域名。
证书链验证
浏览器验证证书的过程:
- 检查证书是否在有效期内
- 检查证书是否被吊销(CRL 或 OCSP)
- 检查证书是否由受信任的 CA 签发
- 递归验证证书链直到根证书
服务器证书
|
v
中间证书
|
v
根证书(预装在操作系统/浏览器中)
Let's Encrypt
Let's Encrypt 是免费的自动化证书颁发机构:
# 使用 certbot 获取证书
sudo apt install certbot
sudo certbot certonly --standalone -d example.com
# 自动续期
sudo certbot renew
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;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000" always;
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
Apache 配置
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>
Node.js 配置
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello HTTPS');
}).listen(443);
HTTPS 安全配置
安全的加密套件
推荐使用支持前向保密(Forward Secrecy)的加密套件:
TLS_AES_128_GCM_SHA256 (TLS 1.3)
TLS_AES_256_GCM_SHA384 (TLS 1.3)
TLS_CHACHA20_POLY1305_SHA256 (TLS 1.3)
ECDHE-RSA-AES128-GCM-SHA256 (TLS 1.2)
ECDHE-RSA-AES256-GCM-SHA384 (TLS 1.2)
前向保密:即使服务器私钥泄露,历史通信也无法解密。因为每次会话使用临时密钥。
HSTS
HTTP Strict Transport Security 强制使用 HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age:有效期(秒)includeSubDomains:包含子域名preload:加入浏览器预加载列表
证书透明度(CT)
证书透明度要求 CA 公开所有签发的证书,便于监控和审计。
# Nginx 配置 CT
ssl_ct on;
ssl_ct_scts_file /path/to/scts;
OCSP Stapling
OCSP Stapling 让服务器缓存证书状态,减少客户端查询:
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
HTTPS 调试
查看证书信息
# 使用 openssl
openssl s_client -connect example.com:443 -showcerts
# 查看证书详情
openssl x509 -in certificate.pem -text -noout
测试 HTTPS 配置
# 使用 testssl.sh
git clone https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh example.com
# 使用 SSL Labs
# 访问 https://www.ssllabs.com/ssltest/
抓包分析
# 使用 tcpdump
tcpdump -i eth0 port 443 -w https.pcap
# 使用 Wireshark 解密(需要私钥)
# Wireshark -> Preferences -> Protocols -> TLS -> RSA keys list
常见问题
证书错误
证书过期:续期证书。
域名不匹配:证书域名必须与访问域名匹配。
不受信任的 CA:使用受信任的 CA 签发的证书。
证书链不完整:配置完整的证书链。
混合内容
HTTPS 页面加载 HTTP 资源会被浏览器阻止:
Mixed Content: The page at 'https://example.com' was loaded over HTTPS,
but requested an insecure script 'http://example.com/script.js'.
解决方案:所有资源都使用 HTTPS。
性能问题
握手开销:使用 TLS 1.3 减少 RTT,启用会话复用。
加密开销:使用 AES-NI 硬件加速,选择高效的加密算法。
证书大小:使用 ECDSA 证书(比 RSA 小)。
小结
HTTPS 是 Web 安全的基础:
- 加密通信:保护数据机密性和完整性
- TLS 握手:协商加密算法和密钥
- 证书体系:验证服务器身份
- 安全配置:使用安全的加密套件,启用 HSTS
- TLS 1.3:更快更安全的协议版本
理解 HTTPS 原理对于 Web 开发和运维至关重要。
练习
- 解释 HTTPS 的工作原理和 TLS 握手过程
- 说明对称加密和非对称加密的区别及应用场景
- 描述数字证书的验证过程
- 配置一个支持 HTTPS 的 Web 服务器