HTTPS 详解:TLS 如何保护 HTTP 通信?

HTTP 解决的是:

客户端和服务器如何表达请求与响应。

但如果直接使用 HTTP:

Client ─────── HTTP ───────> Server

网络上的中间节点理论上可以看到通信内容,甚至可能篡改数据。

例如登录请求:

POST /login HTTP/1.1
Content-Type: application/json

{
    "username": "tom",
    "password": "123456"
}

如果通信没有加密,用户名、密码以及响应内容都可能暴露。

因此 Web 中通常使用:

HTTPS = HTTP + TLS

TLS 位于 HTTP 与底层传输之间,为上层应用提供安全通信能力。

TLS 的目标主要包括:

机密性
完整性
身份认证

TLS 1.3 规范明确将建立安全信道、认证通信对端以及保护应用数据作为核心目标。需要注意的是,TLS 1.3 的 RFC 8446 已被 RFC 9846 更新,因此实际学习和实现时应同时关注最新规范。


1. 为什么需要 HTTPS?

先看一个最简单的 HTTP 请求:

Client
  │
  │  HTTP
  │  username=tom
  │  password=123456
  ▼
Server

假设客户端与服务器之间经过:

客户端
  ↓
Wi-Fi
  ↓
路由器
  ↓
运营商网络
  ↓
CDN / 代理
  ↓
服务器

HTTP 本身并不提供端到端加密。

因此攻击者如果能够处于合适的网络位置,就可能进行:

窃听
篡改
伪造

例如:

正常:

Client ───────────────> Server
       "price=100"


攻击者:

Client ───> Attacker ───> Server
              │
              └─ 修改为 price=1

HTTPS 的目的就是让中间节点无法随意读取或修改受保护的 HTTP 数据。


2. HTTPS 到底保护什么?

理解 HTTPS 最重要的是三个概念。

2.1 机密性

别人即使截获网络数据,也不能直接看到 HTTP 内容。

例如:

HTTP:

password=123456

经过 TLS 保护后,网络上传输的是加密后的数据。

因此:

攻击者看到的是密文

而不是:

password=123456

2.2 完整性

HTTPS 不只是“加密”。

还需要保证:

数据在传输过程中没有被偷偷修改。

例如:

原始:

amount=100

攻击者修改:

amount=10000

TLS 会通过密码学机制检测通信数据是否被篡改。

如果校验失败,连接不会继续正常交付给应用层。


2.3 身份认证

这是 HTTPS 非常重要、也最容易被忽略的一点。

假设你访问:

https://example.com

你不仅希望:

别人看不到我的数据。

还希望:

我连接的确实是 example.com,而不是一个冒充它的服务器。

这就是服务器身份认证。

TLS 使用 X.509 证书体系来帮助客户端验证服务器身份。

当前服务身份验证相关规范是 RFC 9525,它已经取代 RFC 6125。该规范强调客户端需要将连接目标的参考身份与服务器证书中的身份进行匹配,并且域名应通过 subjectAltName 中的 dNSName 等机制进行验证。


3. SSL 和 TLS 是什么关系?

很多资料会把:

SSL
HTTPS
TLS

混在一起。

实际上:

SSL
 ↓
TLS

TLS 是 SSL 的后继协议。

早期存在:

SSL 2.0
SSL 3.0

之后进入:

TLS 1.0
TLS 1.1
TLS 1.2
TLS 1.3

现在新系统通常应该优先使用 TLS 1.3,并根据实际兼容性考虑 TLS 1.2。

所以:

HTTPS
  ↓
TLS
  ↓
TCP

而不是:

HTTPS = SSL

今天浏览器地址栏中看到的 HTTPS,本质上是 HTTP 通过 TLS 进行保护。


4. 为什么 TLS 同时使用对称加密和非对称加密?

这是理解 HTTPS 的关键。

很多初学者会问:

为什么不直接使用 RSA 加密所有 HTTP 数据?

因为这样效率很差。

实际通信通常采用:

非对称密码学
    ↓
协商 / 建立密钥
    ↓
对称加密
    ↓
大量数据传输

对称加密

特点:

加密密钥 = 解密密钥

例如:

Client                  Server
   │                       │
   │── 同一个密钥 ─────────│
   │                       │
   │══ 加密数据 ══════════>│
   │<═ 加密数据 ═══════════│

优点是:

性能非常高。

所以真正大量传输的 HTTP 数据,一般使用对称加密。


非对称密码学

非对称密码学使用:

公钥
私钥

两个不同的密钥。

公钥可以公开:

Public Key

私钥必须保密:

Private Key

它可以用于:

身份认证
数字签名
密钥交换相关机制

但现代 TLS 1.3 的密钥建立并不是简单的:

客户端生成 AES 密钥
 ↓
RSA 公钥加密
 ↓
服务器 RSA 私钥解密

这种描述属于很多旧教材对 TLS 的简化模型。

TLS 1.3 的核心密钥交换通常使用 (EC)DHE,双方通过 Diffie-Hellman 类机制建立共享秘密,再从中派生出实际通信所使用的密钥。RFC 8446 明确规定了 (EC)DHE 等密钥交换模式。


5. 数字证书到底是什么?

浏览器访问:

https://example.com

服务器会向客户端提供证书。

证书可以粗略理解为:

一份由受信任机构签发的、将服务器身份与公钥绑定起来的数字证明。

里面包含的信息可能包括:

域名
公钥
证书有效期
签发者
签名算法
CA 的数字签名
扩展信息

可以简化成:

example.com
      │
      ▼
   Public Key
      │
      ▼
   Certificate
      │
      ▼
      CA

这里有一个非常重要的概念:

证书不是用来“加密所有 HTTP 数据”的。

证书主要帮助客户端:

确认服务器身份
获得服务器公钥
验证证书链

真正的大量应用数据传输,还是使用握手之后建立的对称密钥。


6. CA 为什么值得信任?

问题来了:

如果服务器自己生成一张证书怎么办?

例如攻击者生成:

example.com
Public Key = attacker key

然后告诉浏览器:

这是 example.com 的证书。

浏览器不能简单相信。

因此引入了:

CA(Certificate Authority)

也就是证书颁发机构。

简单理解:

Root CA
   │
   ▼
Intermediate CA
   │
   ▼
Server Certificate
   │
   ▼
example.com

浏览器和操作系统中通常预置了一组受信任的根证书。

因此客户端可以验证:

服务器证书
     ↓
中间 CA
     ↓
受信任 Root CA

如果整个信任链有效,客户端才继续。


7. 浏览器为什么能确认“这是 example.com”?

这涉及证书中的服务器身份。

假设访问:

https://example.com

客户端首先知道:

reference identity = example.com

服务器发送证书。

证书中存在类似:

Subject Alternative Name

DNS: example.com
DNS: www.example.com

客户端进行匹配。

简化理解:

浏览器要访问:

example.com

服务器证书声明:

example.com

        ↓

匹配
        ↓

身份验证通过

如果服务器拿的是:

evil.example.net

而客户端访问的是:

example.com

就不应该通过服务器身份验证。

现代规范不应该再依赖证书 Common Name 来完成域名身份匹配,而应使用 subjectAltName 等标准身份字段。RFC 9525 对此进行了明确规定。


8. TLS 1.3 握手到底发生了什么?

这是 HTTPS 最核心的一部分。

假设:

Client
   │
   │
   ▼
Server

使用 TLS 1.3。

简化之后,可以理解为:

ClientHello
     │
     ▼
ServerHello
     │
     ▼
Server Certificate
     │
     ▼
CertificateVerify
     │
     ▼
Finished
     │
     ▼
Encrypted Application Data

实际协议消息和密钥派生过程更加复杂,但理解这条主线已经足够建立正确模型。


8.1 ClientHello

客户端首先发送:

ClientHello

其中会携带大量协商信息,例如:

支持的 TLS 版本
支持的密码套件
随机数
密钥交换参数
扩展
SNI
ALPN

其中两个 Web 开发中经常见到的概念是:

SNI
ALPN

SNI

SNI(Server Name Indication)用于告诉 TLS 服务端:

客户端想访问哪个主机名。

例如:

example.com

这非常重要,因为一个服务器 IP 上可能部署:

example.com
api.example.com
cdn.example.com

服务器需要根据客户端请求的主机名选择合适的证书。


ALPN

ALPN 用于协商应用层协议。

例如:

HTTP/1.1
HTTP/2

客户端和服务器可以通过 ALPN 协商最终使用哪个应用协议。

例如:

Client:
支持 h2、http/1.1

Server:
选择 h2

最终:

TLS
 ↓
HTTP/2

9. ServerHello 和密钥协商

服务器收到 ClientHello 后,会返回:

ServerHello

服务器选择:

TLS 版本
密码套件
密钥交换参数

然后双方通过密钥交换机制建立共享秘密。

可以简单理解为:

Client
   │
   │ Client Key Share
   ▼
Server
   │
   │ Server Key Share
   ▼
双方计算共享秘密

关键点是:

网络中并不需要直接传输最终用于加密 HTTP 的对称密钥。

双方可以根据密钥交换过程独立计算出相同的共享秘密。

然后通过 TLS 的密钥派生机制生成:

Client Traffic Key
Server Traffic Key

之后的应用数据使用这些密钥进行保护。


10. 证书在 TLS 握手中发挥什么作用?

密钥交换解决的是:

双方如何建立共享密钥?

证书解决的是:

我怎么知道对方确实是我要连接的服务器?

服务器会发送:

Certificate

客户端检查:

证书是否过期?
        ↓
证书链是否可信?
        ↓
域名是否匹配?
        ↓
证书用途是否正确?
        ↓
签名是否有效?
        ↓
服务器是否拥有对应私钥?

最后一个问题尤其重要。

服务器不能只是拿到:

example.com 的证书

还必须能够证明:

我确实拥有与该证书对应的私钥。

TLS 1.3 中通过 CertificateVerify 等机制完成这一过程。

因此:

证书
+
私钥

共同构成服务器身份认证的重要基础。


11. TLS 握手完成后,HTTP 才真正开始

TLS 握手完成之后:

Client
  │
  │ 加密后的 HTTP Request
  ▼
Server
  │
  │ 加密后的 HTTP Response
  ▼
Client

例如应用层实际上想发送:

GET /api/users HTTP/1.1
Host: example.com
Accept: application/json

但网络中间节点看到的不会是这些 HTTP 明文内容,而是经过 TLS Record Protocol 保护后的数据。

可以理解成:

HTTP
 ↓
TLS Record
 ↓
TCP
 ↓
IP

服务器收到数据后:

IP
 ↓
TCP
 ↓
TLS
 ↓
HTTP
 ↓
Application

这就是 HTTPS 的核心工作方式。


12. 为什么不能只使用 HTTPS 加密,而不验证证书?

假设 TLS 只做:

加密

但不验证服务器身份。

攻击者可以:

Client
   │
   │ HTTPS
   ▼
Attacker
   │
   │ HTTPS
   ▼
Real Server

客户端确实建立了一个加密连接。

但这个加密连接是:

Client ↔ Attacker

而不是:

Client ↔ Real Server

攻击者甚至可以继续与真正服务器建立另一个 HTTPS 连接。

这就是经典的:

中间人攻击(MITM)。

所以 HTTPS 的安全性不能简单理解成:

HTTPS = 加密

更准确的是:

HTTPS
  =
TLS
  +
服务器身份认证
  +
加密
  +
完整性保护

13. HTTPS 为什么仍然可以看到 IP、域名等信息?

一个常见误区是:

HTTPS 开启之后,网络运营商什么都看不到了。

不是这样。

TLS 主要保护的是:

HTTP 应用数据

例如:

URL Path
请求 Header
Cookie
Request Body
Response Body

传统 HTTPS 场景下,网络层仍然可以观察到:

源 IP
目标 IP
端口
数据包大小
时间
流量方向

而且传统 TLS 中,服务器名称还可能通过明文 SNI 暴露。

现代 TLS 生态中已经有 ECH(Encrypted ClientHello)等机制,用于进一步保护 ClientHello 中的敏感信息,但这是更进一步的话题。

所以:

HTTPS ≠ 所有网络元数据全部隐藏

这一点在网络安全和隐私分析中非常重要。


14. HTTPS 对后端开发有什么影响?

对于 PHP、Java、Go、Node.js 等后端开发者来说,HTTPS 经常表现为:

Browser
   ↓
HTTPS
   ↓
Nginx
   ↓
HTTP
   ↓
Application

也就是说,TLS 经常在:

Nginx
Load Balancer
API Gateway
CDN

这一层终止。

例如:

                    TLS
Client ─────────────────────> Nginx
                               │
                               │ HTTP
                               ▼
                            PHP-FPM

这种方式称为:

TLS Termination

应用本身可能并没有直接处理 TLS。


反向代理环境下需要注意什么?

如果:

Client
  │ HTTPS
  ▼
Nginx
  │ HTTP
  ▼
Application

应用看到的连接可能是 HTTP。

因此应用需要正确处理:

X-Forwarded-Proto
Forwarded
X-Forwarded-For

以及框架自身的 Trusted Proxy 配置。

否则可能出现:

明明用户访问 HTTPS
应用却认为是 HTTP

进而影响:

Secure Cookie
HTTPS Redirect
生成 URL
OAuth Callback
签名 URL

等功能。


15. 为什么 HTTPS 访问第一次通常更慢?

建立 HTTPS 连接通常需要:

DNS
 ↓
TCP
 ↓
TLS
 ↓
HTTP

相比直接发送 HTTP,请求链路增加了 TLS 握手和密码学计算。

但现代 TLS 已经针对这个问题进行了大量优化。

例如:

TLS 1.3

减少了握手往返次数。

另外还存在:

Session Resumption
PSK
0-RTT

等机制。

TLS 1.3 规范明确包含 PSK 会话恢复和 0-RTT 数据机制。

不过:

0-RTT 并不是“免费加速”。

因为 0-RTT 存在重放攻击相关风险,因此不应该把任意具有副作用的 HTTP 请求都直接放进 0-RTT 数据中。

例如:

GET

这类幂等请求通常更适合考虑。

而:

POST /pay
POST /order
POST /transfer

这类具有业务副作用的请求需要非常谨慎。


16. HTTPS、HTTP/2、HTTP/3 的关系

这几个概念经常被错误地绑定在一起。

正确理解应该是:

HTTPS
  ↓
HTTP + TLS

而 HTTP 版本是另外一个维度:

HTTP/1.1
HTTP/2
HTTP/3

可以粗略表示:

HTTP/1.1
    │
    └── TLS
          │
          └── TCP

HTTP/2
    │
    └── TLS
          │
          └── TCP

HTTP/3
    │
    └── QUIC
          │
          └── UDP

所以:

HTTP/2 ≠ HTTPS
HTTP/3 ≠ HTTPS

只是现代浏览器部署中,HTTP/2 通常通过 TLS 使用,而 HTTP/3 的安全机制与 QUIC/TLS 结合。


17. 从浏览器输入 URL 到 HTTPS 请求完成

用户访问:

https://api.example.com/users/1001

完整链路可以抽象成:

① DNS
api.example.com
       ↓
IP 地址

② TCP
客户端
   ↓
TCP 三次握手
   ↓
TCP Connection

③ TLS
ClientHello
   ↓
ServerHello
   ↓
Certificate
   ↓
身份验证
   ↓
密钥协商
   ↓
Finished

④ HTTP
GET /users/1001
       ↓
Application

⑤ Response
HTTP/2 200
       ↓
JSON

⑥ TLS
加密

⑦ TCP
传输

⑧ Client
解密
       ↓
HTTP Response

如果把各层放在一起:

┌──────────────────────────┐
│        HTTP / HTTP2      │
├──────────────────────────┤
│           TLS            │
├──────────────────────────┤
│           TCP            │
├──────────────────────────┤
│            IP            │
└──────────────────────────┘

这就是 HTTPS 的完整基本模型。


18. 常见误区

误区一:HTTPS 就是 HTTP 加密

不够准确。

HTTPS 的安全目标至少包括:

机密性
完整性
服务器身份认证

误区二:证书就是用来加密数据的

证书主要用于:

身份绑定
公钥分发
建立信任

真正的大量 HTTP 数据使用握手建立的对称密钥进行保护。


误区三:HTTPS 使用 RSA 加密所有数据

这是很多旧教材留下来的错误印象。

现代 TLS 1.3 的密钥交换主要使用 (EC)DHE 等机制,并通过密钥派生产生流量密钥。

RSA/ECDSA/EdDSA 等也可能参与身份认证和签名,但不能简单说成:

RSA 加密整个 HTTPS

误区四:CA 会看到用户所有 HTTPS 数据

通常不会。

CA 的核心职责是:

签发和信任证书

而不是:

代理所有 HTTPS 流量

正常 HTTPS 通信的数据是在客户端和服务器之间通过 TLS 建立的安全信道保护的。


误区五:有 HTTPS 就绝对安全

也不正确。

HTTPS 主要解决:

传输层面的机密性、完整性和服务器身份认证

但它不能保证:

服务器代码没有漏洞
数据库没有泄露
账号密码没有被盗
业务逻辑没有漏洞
XSS 不存在
SQL 注入不存在
CSRF 不存在

所以:

HTTPS 是 Web 安全的基础

而不是全部。


19. 总结

HTTPS 可以理解为:

HTTP
 +
TLS

TLS 为 HTTP 提供安全通信能力,核心解决:

1. 机密性
2. 完整性
3. 身份认证

其中:

证书
   ↓
证明服务器身份

非对称密码学 / 密钥交换
   ↓
建立共享秘密

对称加密
   ↓
保护大量应用数据

TLS Record
   ↓
保护 HTTP 数据

TLS 1.3 的基本过程可以记成:

Client
  │
  │ ClientHello
  ▼
Server
  │
  │ ServerHello
  │ Certificate
  │ CertificateVerify
  │ Finished
  ▼
Client
  │
  │ Finished
  ▼
Encrypted HTTP

而从整个网络体系来看:

HTTP
 ↓
TLS
 ↓
TCP
 ↓
IP

到了 HTTP/3:

HTTP/3
 ↓
QUIC
 ↓
UDP
 ↓
IP

理解 HTTPS 之后,网络系列最后一个非常自然的问题就是:

如果 HTTP 是请求/响应模式,而 WebSocket 可以让客户端和服务器长期保持双向通信,它到底是怎么做到的?

《WebSocket 详解:实时双向通信是如何实现的?》

参考资料