HTTPS 与 SSL/TLS
HTTP 明文传输,任何人都能偷看、篡改。HTTPS 把 HTTP 包装一层加密,让通信变得机密、完整、可认证。这一章把 HTTPS 拆开看清楚。
1. HTTP 的三大安全隐患
- 窃听:HTTP 明文传输,WiFi 提供方、ISP、路由器都能看到内容(密码、Token)。
- 篡改:运营商劫持 HTTP 响应塞广告、改页面(你肯定见过右下角的弹窗)。
- 伪造:黑客伪装成银行网站,你以为是真站实际是钓鱼。
HTTPS 同时解决这三件事:加密防窃听、完整性校验防篡改、证书防伪造。
2. HTTPS 不是新协议
HTTPS = HTTP over TLS。HTTP 报文不变,只是在传给 TCP 之前先经过 TLS 加密层。默认端口从 80 变成 443。
# HTTP vs HTTPS — 协议栈对比
# HTTP: 应用层 (HTTP) → 直接走 TCP,默认端口 80
# HTTPS: 应用层 (HTTP) → TLS 加密层 → TCP,默认端口 443
#
# HTTPS 不是新协议,是 "HTTP over TLS"
# 报文格式一模一样,只是字节被加密了再传
curl http://example.com/ # 走 80,明文
curl https://example.com/ # 走 443,加密3. SSL vs TLS:叫法问题
SSL(Secure Sockets Layer)是网景 1995 年发明的,TLS(Transport Layer Security)是 IETF 在 SSL 3.0 基础上做的标准化版本(1999 起)。两者其实是同一东西的不同代。SSL 2/3 已被发现严重漏洞全部废弃,现在用的全是 TLS(TLS 1.2 / 1.3)。但叫法上"SSL 证书"这个习惯说法沿用至今,技术文档里通常指 TLS 证书。
4. 对称 vs 非对称加密
理解 TLS 必须先懂两种加密:
- 对称加密:双方共享一个密钥,加密解密都用它。代表算法 AES。优点:快。缺点:怎么把密钥安全传给对方是个难题。
- 非对称加密:有一对密钥(公钥 + 私钥)。公钥加密只能私钥解(机密性),私钥加密只能公钥解(签名)。代表算法 RSA、ECC。优点:解决密钥分发。缺点:很慢,不适合大量数据。
# 为什么 TLS 同时用两种加密?
# 非对称加密 (RSA/ECC):
# - 有公钥/私钥对
# - 公钥加密,只有私钥能解 (或反之)
# - 慢,但能安全交换密钥
# 对称加密 (AES):
# - 双方共享一个密钥
# - 快,适合大量数据
# - 但如何安全传递这个密钥? → 用非对称加密传
# TLS 把两者结合:
# 1. 用非对称加密安全协商出一个对称密钥 (pre-master secret)
# 2. 之后通信用这个对称密钥 (快)
# "用非对称换密钥,用对称传数据"TLS 的核心思路就是"用非对称换密钥,用对称传数据"。
5. TLS 握手流程
HTTPS 通信前要先握手协商出对称密钥。简化流程:
# TLS 1.2 握手流程 (简化版)
# 1. ClientHello: 客户端说"我支持这些加密套件,这是我的随机数 A"
Client → Server: TLS版本, 支持的密码套件, 客户端随机数
# 2. ServerHello + 证书: 服务器选定套件,返回证书 + 随机数 B
Server → Client: 选定的套件, 服务器随机数, X.509 证书 (含公钥)
# 3. 客户端验证证书 (见下文)
# 4. 客户端生成 pre-master secret,用服务器公钥加密发过去
Client → Server: 加密后的 pre-master secret
# 5. 双方用 (A + B + pre-master) 算出对称会话密钥
# 6. 后续所有数据用这个对称密钥加解密 — 这就是 "对称加密传输"
# TLS 1.3 简化为 1 个 RTT (甚至 0-RTT),更快更安全关键点:
- 握手期间交换了三个随机数(客户端、服务器、pre-master),三者合起来生成会话密钥,保证每次连接密钥都不同。
- 整个握手对开发者透明——服务器和浏览器自动完成。你只需配置好证书。
- TLS 1.2 握手要 2 个 RTT;TLS 1.3 优化到 1 个 RTT,甚至支持 0-RTT(首次连接也要 1 RTT)。
6. 证书:证明服务器身份
光加密不够——如果黑客冒充银行给你他的公钥,你加密的内容他全能解。数字证书解决"我怎么知道这个公钥真是银行的"问题。
证书由CA(Certificate Authority,证书颁发机构)签发,是一份带签名的电子文档:
# X.509 证书长什么样
# 一份证书包含:
Certificate:
Version: 3
Serial Number: 0x...
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Let's Encrypt R3 # 谁签发的
Validity:
Not Before: Aug 5 06:00:00 2026 GMT
Not After : Nov 3 06:00:00 2026 GMT # 90 天后过期
Subject: CN=fertijourney.com # 给谁签的
Subject Public Key Info: # 持有人的公钥
Public Key Algorithm: id-ecPublicKey
...
X509v3 Subject Alternative Name:
DNS:fertijourney.com, DNS:www.fertijourney.com
Signature Algorithm: sha256WithRSAEncryption
(CA 用私钥对前面内容的签名)
# 浏览器验证: 拿 CA 的公钥验签名 → 通过则信任7. 信任链:根 CA
浏览器/操作系统内置了一份信任的根 CA 列表。你的证书只要被这条链上某个 CA 签发,浏览器就信任:
# 证书信任链
# 你的证书
# ↑ 签发者
# 中间 CA 证书 (如 Let's Encrypt R3)
# ↑ 签发者
# 根 CA 证书 (如 ISRG Root X1)
# ↑ 操作系统/浏览器内置信任
# 浏览器/操作系统自带一个根 CA 列表 (信任根)
# 你的证书只有被这条链上的某个 CA 签发,才会被信任
# 配置服务器时,通常要 "证书 + 中间证书" 一起发,否则部分客户端会不认
# 查看一个网站的证书链:
openssl s_client -connect fertijourney.com:443 -showcerts自签名证书(自己当 CA 签自己)浏览器不认,会弹"不安全"警告——适合内网开发用。
8. Let's Encrypt:免费证书
2015 年前 SSL 证书要钱,而且贵。Let's Encrypt 出现后完全免费(90 天有效期,自动续期),是个人/小项目首选:
# Let's Encrypt — 免费证书 (90 天有效期)
# 用 certbot 自动申请 + 自动续期:
sudo apt install certbot
sudo certbot certonly --nginx -d fertijourney.com -d www.fertijourney.com
# 证书放在:
# /etc/letsencrypt/live/fertijourney.com/fullchain.pem (含中间证书)
# /etc/letsencrypt/live/fertijourney.com/privkey.pem (私钥)
# Nginx 配置:
server {
listen 443 ssl http2;
server_name fertijourney.com;
ssl_certificate /etc/letsencrypt/live/fertijourney.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fertijourney.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
}
# 自动续期 (cron 里加):
sudo certbot renew --quiet9. 证书的类型
- DV(Domain Validation):只验证你拥有这个域名。最便宜(Let's Encrypt 都是 DV),签发快。
- OV(Organization Validation):还验证组织身份(公司真实存在)。证书里能看到公司名。
- EV(Extended Validation):最严格,人工审核公司材料。曾经浏览器地址栏显示绿色公司名(现在多数浏览器已取消这种视觉标记)。
- 通配符证书:
*.example.com,一个证书覆盖所有一级子域名。 - 多域名证书(SAN):一个证书列多个域名,跨域名共用。
10. TLS 1.3:更快更安全
2018 年标准化的 TLS 1.3 带来:
- 握手只要 1 RTT(甚至 0-RTT 恢复会话)。
- 删除了所有不安全的加密算法(RSA 密钥交换、SHA-1、RC4 等)。
- 前向保密(Forward Secrecy):即使私钥泄露,过去已加密的会话也无法被解密。
新项目务必启用 TLS 1.2 和 1.3,禁用 TLS 1.0/1.1 和 SSL。
11. HSTS:防首次劫持
即使用了 HTTPS,用户第一次输入 http:// 时仍会先发 HTTP(可能被劫持)。HSTS 告诉浏览器"以后永远 HTTPS":
# HSTS — 强制 HTTPS
# 服务器响应头告诉浏览器: "我以后永远用 HTTPS 访问我"
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# max-age=31536000 一年内强制 HTTPS
# includeSubDomains 所有子域名也强制
# preload 申请加入浏览器内置的 HSTS Preload 列表
# (即便用户第一次访问也是 HTTPS,防止首次劫持)
# 警告: 开启 HSTS 前要确认 HTTPS 完全可用,否则用户可能永远访问不到你
# 把 http 强制跳转 https:
# 1. 服务器 301 跳转 (处理用户输入 http:// 的情况)
# 2. HSTS (处理浏览器以后的访问)12. HTTPS 性能影响
早期 HTTPS 慢,但现代硬件上几乎可以忽略:
- TLS 握手增加 1~2 RTT(TLS 1.3 后只有 1 RTT)。
- 加解密 CPU 开销,现代 CPU 有 AES-NI 指令集,吞吐量 Gbps 级别。
- HTTP/2 / HTTP/3 强制要求 HTTPS(HTTP/2 在浏览器只通过 TLS 实现),所以上 HTTPS 是上 HTTP/2 的前提。
13. 调试 HTTPS
openssl s_client -connect host:443:看证书、握手细节。curl -v https://...:看 TLS 握手过程。- SSL Labs:在线评测证书配置安全性(A+ 是目标)。
- Charles/Fiddler:本地代理抓 HTTPS 包,需要安装并信任它的根证书。
小结
HTTPS = HTTP + TLS。用非对称加密换对称密钥,用对称密钥传数据,用 CA 证书证明身份。新项目一律 HTTPS + TLS 1.2/1.3 + HSTS + Let's Encrypt,没有任何借口不用。
← 上一篇 Cookie 与 Session
下一篇 curl 命令实战 →