跳到主要内容

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 的区别

特性HTTPHTTPS
端口80443
数据传输明文加密
安全性
性能略快略慢(握手开销)
证书不需要需要

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 使用混合加密方案:

  1. 使用非对称加密协商对称密钥
  2. 使用对称密钥加密实际数据

这样既解决了密钥分发问题,又保证了加密效率。

数字签名

数字签名用于验证数据的来源和完整性:

数据 --[哈希]--> 摘要 --[私钥加密]--> 签名

验证:签名 --[公钥解密]--> 摘要 --[与原数据哈希比较]

数字证书

数字证书由证书颁发机构(CA)签发,包含:

  • 证书持有者信息
  • 公钥
  • CA 签名
  • 有效期
  • 证书用途

证书链:根证书 -> 中间证书 -> 服务器证书

TLS 握手过程

TLS 1.2 握手

TLS 1.2 握手需要 2 个 RTT(往返时间):

客户端                                        服务器
| |
| ClientHello |
| (支持的加密套件、随机数) |
|------------------------------------------->|
| |
| ServerHello |
| (选定的加密套件、随机数) |
| Certificate(服务器证书) |
| ServerKeyExchange(可选) |
| ServerHelloDone |
|<-------------------------------------------|
| |
| ClientKeyExchange |
| (加密的预主密钥) |
| ChangeCipherSpec |
| Finished |
|------------------------------------------->|
| |
| ChangeCipherSpec |
| Finished |
|<-------------------------------------------|
| |
| 应用数据(加密) |
|<------------------------------------------>|

密钥生成过程

  1. 客户端生成随机预主密钥(Pre-Master Secret)
  2. 用服务器公钥加密预主密钥,发送给服务器
  3. 双方使用预主密钥和两个随机数生成主密钥(Master Secret)
  4. 从主密钥派生出会话密钥(对称加密密钥、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

多域名证书:保护多个域名。

证书链验证

浏览器验证证书的过程:

  1. 检查证书是否在有效期内
  2. 检查证书是否被吊销(CRL 或 OCSP)
  3. 检查证书是否由受信任的 CA 签发
  4. 递归验证证书链直到根证书
服务器证书
|
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 安全的基础:

  1. 加密通信:保护数据机密性和完整性
  2. TLS 握手:协商加密算法和密钥
  3. 证书体系:验证服务器身份
  4. 安全配置:使用安全的加密套件,启用 HSTS
  5. TLS 1.3:更快更安全的协议版本

理解 HTTPS 原理对于 Web 开发和运维至关重要。

练习

  1. 解释 HTTPS 的工作原理和 TLS 握手过程
  2. 说明对称加密和非对称加密的区别及应用场景
  3. 描述数字证书的验证过程
  4. 配置一个支持 HTTPS 的 Web 服务器