HTTPS 原理与报文 — 加密链路、证书校验与安全首部

HTTPS 完整访问时序、URL 加密可见性、证书链校验七步、HSTS/CT/OCSP 机制 / 应用层 / TCP 443 / RFC 9110

先建立直觉

先把"协议细节"全放下,用一句话建立画面:

HTTPS 就是把原本要寄出去的明信片(HTTP 报文),先塞进一个只有对方能打开的保险柜(TLS 加密),再交给邮局(TCP/IP)寄走。 保险柜本身走的是标准 TLS,里面装的还是标准 HTTP——一个字节的 HTTP 语义都没变。你发出去的仍然是 GET /index.html HTTP/1.1,只是这串字节在进 TCP 之前先被锁了起来。

所以"学 HTTPS"的实质不是学一套新报文,而是学 TLS 在 Web 场景下的落地细节:证书怎么签、浏览器怎么校验、SNI 是什么、怎么从 HTTP 平滑迁过来。后面所有小节,都是在拆解这只"保险柜"和"电子执照"。

它解决什么问题

没有 HTTPS 时,明文 HTTP 在互联网上等于"裸奔"。HTTPS 要补齐的就是三件事——机密性、完整性、身份认证——外加一道"防降级"的保险:

  • 防窃听:TLS 对整个 HTTP 报文(含首部与 Cookie)做 AEAD 加密,同网段抓包也读不到内容。
  • 防篡改:AEAD 认证标签 + Finished 校验,任何比特被改都会导致解密失败。
  • 防冒充:服务器必须出示由受信任 CA 为该域名签发的证书,并用私钥签名证明"我就是域名持有者",否则浏览器拒绝。
  • 防降级:HSTS(RFC 6797)强制浏览器只用 HTTPS,堵死 SSLStrip 把 https 改回 http 的攻击。

此外,HTTPS 已是大量浏览器高级能力(HTTP/2、Service Worker、定位、摄像头等)的准入门槛——不是"更安全"而已,而是"能不能用"的问题。

工作流程(简化版)

把一次 HTTPS 访问拆成"三段接力",就很好记:

  1. 传输通道建立:DNS 解析 → TCP 三次握手到 443 端口。
  2. 安全通道建立(TLS 握手):协商版本与算法 → 服务器出示证书 → 客户端校验证书并验签 → 双方通过 ECDHE 派生对称密钥 → 双向 Finished 校验。此阶段结束后,双方持有一对只有彼此知道的对称密钥
  3. 业务数据传输:把原本要写进 TCP 的 HTTP 报文字节,先交给 TLS 记录层做 AEAD 加密,再交给 TCP。服务器反向解密后交给 Web 服务处理。

关键认知:HTTPS 没有定义任何新的报文格式。抓包看到的 443 端口流量,剥掉 TLS 记录层后就是一模一样的 HTTP 报文。所谓"HTTPS 报文结构",实际上就是 TLS 记录头(5B) + 加密后的 HTTP 报文

报文/头部长什么样

这一节只看"线上到底长什么样"。先记住一个总纲:HTTPS 没有自己的头部,它只是在标准 HTTP 外面套了一层 TLS 记录头,再包进标准 IP/TCP

分层封装示意

看这张图前先记住:下面每一层里,“暴露"和"加密"是交替出现的——外层信封谁都能看,最里面那层才看不见。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
+----------------------------------------------------------+
| 以太网帧头 |
+----------------------------------------------------------+
| IP 头(源 IP、目的 IP —— 暴露) |
+----------------------------------------------------------+
| TCP 头(目的端口 443 —— 暴露) |
+----------------------------------------------------------+
| TLS 记录头 5 字节 |
| ContentType(1) = 0x17 application_data |
| LegacyVersion(2) = 0x0303 |
| Length(2) |
+----------------------------------------------------------+
| AEAD 加密载荷 —— 以下内容全部不可见 |
| GET /account?id=1024 HTTP/1.1 |
| Host: bank.example.com |
| Cookie: sid=abc123 |
| Authorization: Bearer eyJ... |
+----------------------------------------------------------+

URL 各部分的加密可见性(高频考点)

这张表是面试和排错的高频题,先记住一句话:域名/IP/端口在握手前就暴露了,路径、查询串、首部、正文才被加密,片段根本不上网。

https://api.example.com:443/v1/users?token=secret#frag 为例:

部分是否加密说明
目的 IP端口 443❌ 明文在 IP/TCP 头中,路由必需
域名(DNS 查询)❌ 明文(除非用 DoH/DoT)解析阶段先于 TLS 发生
域名(TLS SNI)❌ 明文服务器要靠它选证书,只能在加密前发送;ECH 用于解决
服务器证书TLS 1.2 明文 / TLS 1.3 加密1.3 把 Certificate 放在 EncryptedExtensions 之后
路径 /v1/users✅ 加密属 HTTP 请求行
查询串 ?token=secret✅ 加密但会被浏览器历史、服务器 access 日志、Referer 记录,仍不应放敏感信息
请求/响应首部(含 Cookie、Authorization)✅ 加密
请求/响应正文✅ 加密
片段 #frag不发送仅浏览器本地使用,从不上网
包长与时序❌ 暴露流量分析可据此推断访问内容,需靠填充(TFC/padding)缓解

X.509 服务器证书关键字段(RFC 5280)

这张表是"证书里到底有什么"的速查。先记住:真正用来校验域名的是 SAN,不是 CN;能补链的是中间证书,根证书客户端本地就有。

字段含义与排错要点
Version现代证书均为 v3(值为 2)
Serial Number序列号,吊销查询与 CT 日志的索引
Signature Algorithm签名算法,如 sha256WithRSAEncryptionecdsa-with-SHA256。SHA-1 签名已被全面拒绝
Issuer签发者 DN,必须等于上级证书的 Subject,链式校验靠它串联
Validity (notBefore/notAfter)有效期。Let’s Encrypt 为 90 天;公共 CA 最长有效期已收紧至 398 天
Subject主体 DN。其中的 CN 字段早已不用于域名校验
Subject Public Key Info公钥算法与公钥(RSA 2048+ 或 ECDSA P-256)
Subject Alternative Name (SAN)域名校验的唯一依据,可含多个 DNS: 项与 IP: 项,支持 *.example.com 通配
Basic ConstraintsCA:TRUE 表示是 CA 证书,叶子证书必须为 CA:FALSE
Key UsagedigitalSignature, keyEncipherment
Extended Key Usage服务器证书必须含 serverAuth (1.3.6.1.5.5.7.3.1)
Authority Information Access (AIA)含 OCSP responder 地址与中间证书下载地址(部分客户端据此自动补链)
CRL Distribution Points吊销列表地址
SCT List证书透明日志的签名时间戳,Chrome 强制要求公网证书具备

HTTPS 相关的安全首部

这张表是 HTTPS 站点"除了加密,还该发哪些响应头”。先记住:HSTS 管强制、CSP 管混合内容、Alt-Svc 管升级 HTTP/3、HPKP 已废弃别用。

首部示例作用
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preloadHSTS:告诉浏览器今后只能用 HTTPS 访问本域,且证书错误不可点击忽略
Content-Security-Policyupgrade-insecure-requests自动把页面内的 http 子资源升级为 https,治理混合内容
Expect-CTmax-age=86400, enforce要求证书透明(已被 Chrome 内置强制取代,逐步淘汰)
X-Content-Type-Optionsnosniff禁止 MIME 嗅探
Alt-Svch3=":443"; ma=86400通告本服务支持 HTTP/3,引导客户端升级
Public-Key-PinsHPKP,因易造成站点自锁已被废弃,不要再用

交互时序

一句话看懂这张图:一次完整的 HTTPS 访问 = 先本地查 HSTS(决定是否强制 https)→ DNS 解析 → TCP 三次握手 → TLS 1.3 一次往返握手(含证书校验七步)→ 之后才在加密通道里跑 HTTP。关连接时先发 TLS close_notify 再发 TCP FIN

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
sequenceDiagram
    participant U as 用户/浏览器
    participant D as DNS 服务器
    participant S as Web 服务器 (443)
    participant O as OCSP / CT 日志

    Note over U: 用户输入 example.com
    U->>U: 查 HSTS 预加载列表<br/>命中则直接改写为 https://
    U->>D: 查询 A / AAAA / HTTPS 记录
    D-->>U: 93.184.216.34 (+ alpn="h3,h2")

    Note over U,S: ── 第 1 段:TCP 三次握手 ──
    U->>S: SYN
    S->>U: SYN+ACK
    U->>S: ACK

    Note over U,S: ── 第 2 段:TLS 1.3 握手(1-RTT)──
    U->>S: ClientHello<br/>SNI=example.com, ALPN=[h2,http/1.1]<br/>key_share, supported_versions=1.3
    S->>U: ServerHello (key_share, 选定套件)
    S->>U: {EncryptedExtensions} ALPN=h2
    S->>U: {Certificate} 叶子证书 + 中间 CA (+ SCT)
    S->>U: {CertificateVerify} 私钥签名
    S->>U: {Finished}
    Note right of U: ① 构建并验证证书链到根 CA<br/>② 校验有效期<br/>③ 域名匹配 SAN<br/>④ EKU 含 serverAuth<br/>⑤ 校验 SCT(证书透明)<br/>⑥ 检查吊销状态<br/>⑦ 验签 CertificateVerify
    opt 无 OCSP Stapling 时
        U->>O: OCSP 查询证书是否被吊销
        O-->>U: good / revoked
    end
    U->>S: {Finished}
    Note over U,S: ✅ 安全通道建立,密钥仅双方持有

    Note over U,S: ── 第 3 段:加密的 HTTP 交互 ──
    U->>S: [加密] GET / HTTP/2<br/>Host: example.com<br/>Cookie: sid=abc
    S->>U: [加密] 200 OK<br/>Strict-Transport-Security: max-age=31536000<br/>Content-Type: text/html<br/>[HTML 正文]
    S->>U: {NewSessionTicket} 供下次会话恢复

    Note over U,S: 关闭时先发 TLS close_notify,再 TCP FIN
    U->>S: [加密] close_notify
    U->>S: FIN

关键机制/变体

下面几条是 HTTPS 真正"区别于裸 HTTP"的工程机制。每条先点明它解决什么:

1. 混合加密的分工 —— 解决"如何又安全又快"

阶段使用的密码学目的性能特点
身份认证RSA / ECDSA / Ed25519 签名证明服务器持有证书对应私钥慢,每次握手 1 次
密钥协商ECDHE(X25519 / P-256)在公开信道上算出共享秘密中等,每次握手 1 次
数据加密AES-128/256-GCM、ChaCha20-Poly1305(AEAD加密全部 HTTP 报文并保证完整性快(有 AES-NI 硬件加速),处理 GB 级数据

一句话:用慢算法安全地建立一把快算法的钥匙。

2. 证书信任链与校验 —— 解决"怎么确认对面是真服务器"

1
2
3
根 CA 证书(自签名,预置在操作系统/浏览器信任库)
   └── 中间 CA 证书(由根签发,CA:TRUE,服务器必须下发)
          └── 叶子证书(由中间 CA 签发,CA:FALSE,含域名 SAN)

浏览器校验的七步(对应上图时序中的 ①–⑦):链完整 → 签名有效 → 在有效期内 → 域名命中 SAN → EKU 含 serverAuth → SCT 满足 CT 策略 → 未被吊销,最后再用证书公钥验签 CertificateVerify 确认对端确实持有私钥。

工程铁律:服务器必须发送 fullchain(叶子 + 中间 CA)。根证书无需发送(客户端本地已有),只发叶子会导致部分客户端报 unable to get local issuer certificate

3. HSTS 与 HTTPS 迁移 —— 解决"如何彻底封死降级"

Strict-Transport-Security 生效后,浏览器在 max-age 期内:

  • 自动把该域名的所有 http:// 请求在本地重写https://(不发出明文请求,彻底封死 SSLStrip);
  • 证书错误时不再提供"继续访问"按钮

preload 指令可申请加入浏览器内置的 HSTS 预加载列表,实现首次访问就强制 HTTPS。但需注意:加入预加载列表后移除极其困难(需等浏览器版本迭代),上线前必须确认全站及所有子域都能提供 HTTPS。

标准迁移步骤:

  1. 申请证书(ACME / Let’s Encrypt),配置 443 监听与 fullchain
  2. 全站可用性验证后,把 80 端口配置为 301 重定向到 https
  3. 排查并修复混合内容(Mixed Content)——HTTPS 页面里引用的 http:// 脚本、样式会被浏览器直接阻断,图片会被标记为不安全。可先用 Content-Security-Policy: upgrade-insecure-requests 兜底。
  4. 更新硬编码的绝对 URL、Cookie 加 Secure 属性、SameSite 复核。
  5. max-age(如 300)灰度 HSTS,观察无异常后逐步升到一年,最后考虑 preload
  6. 配置证书到期监控与自动续期,避免"证书过期导致全站不可用"这一最常见事故。

4. OCSP Stapling 与证书吊销 —— 解决"吊销查询泄露隐私又拖慢"

传统 OCSP 由客户端向 CA 查询证书吊销状态,带来三个问题:额外一次网络往返、CA 宕机时浏览器只能"软失败"放行、CA 得知了用户访问了哪个站点(隐私泄露)。

OCSP Stapling(TLS status_request 扩展)让服务器定期向 CA 查询并缓存一份带 CA 签名的 OCSP 响应,握手时直接"钉"在 Certificate 消息后面发给客户端。客户端无需外联即可确认状态。生产环境应始终开启。

5. 证书透明(Certificate Transparency)—— 解决"误签证书没人发现"

CA 签发的每张公网证书都必须提交到多个公开、只可追加的 CT 日志,并把日志返回的 SCT(Signed Certificate Timestamp) 嵌入证书(或通过 TLS 扩展/OCSP 传递)。Chrome 等浏览器会拒绝不满足 CT 策略的证书。这使得任何"误签/恶意签发"都会在公开日志中留痕,域名所有者可通过 crt.sh 等工具监控自己域名下出现的所有证书。

6. 性能开销与优化 —— 解决"加密会不会拖慢网站"

HTTPS 的额外成本主要是握手的 1–2 个 RTT 与非对称运算的 CPU 开销。缓解手段:

  • TLS 1.3:1-RTT 握手,会话恢复 0-RTT。
  • 会话恢复:Session Ticket / PSK,避免重复完整握手。
  • OCSP Stapling:省掉客户端的额外查询。
  • ECDSA 证书:比同等强度 RSA 密钥更短、签名更快(可与 RSA 双证书并存以兼容老客户端)。
  • HTTP/2 / HTTP/3:多路复用抵消并常常反超明文 HTTP/1.1 的整体性能。
  • 会话复用与长连接:避免每个请求都重新握手。

常见误区

  1. 以为"上了 HTTPS,访问目标就隐藏了":SNI 与 DNS 查询仍然是明文,中间人照样知道你访问了哪个域名(TLS 1.2 下连证书都明文)。真正要隐藏访问目标,得靠 DoH/DoT 或 ECH,HTTPS 本身做不到。
  2. 以为"证书里的 CN(Common Name)就是用来校验域名的":现代校验唯一依据是 SAN 扩展,CN 早已不用于域名匹配。证书里 Subject 的 CN 写什么无所谓,关键看 SAN 列了哪些 DNS 名。
  3. 以为"装了叶子证书就能用":只发叶子证书时,浏览器可能靠 AIA 自动补链"看起来正常",但 curl、Java、移动端 SDK 会直接报 ERR_CERT_AUTHORITY_INVALID。服务器必须下发 fullchain(叶子 + 中间 CA)。
  4. 以为"HSTS preload 想退就退":一旦提交进浏览器预加载列表,移除要等浏览器版本迭代,极难撤回。上线前必须确认全站及所有子域都能稳定提供 HTTPS,否则可能长期不可访问。

速记口诀

  1. HTTPS = HTTP 套 TLS,语义一字不改,443 上跑的是标准 TLS 记录。
  2. 加密看路径正文,明文露 IP、SNI 和端口;域名校验认 SAN,不认 CN。
  3. 证书要发 fullchain,HSTS 防降级,OCSP 钉状态,CT 留痕防误签。

知识框架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
mindmap
  root((HTTPS))
    本质定义
      HTTP over TLS
      语义与HTTP完全一致
      TCP443  UDP443(HTTP3)
      RFC9110 定义https方案
    安全目标
      机密性 防窃听
      完整性 防篡改
      身份认证 防冒充
      前向保密
      防降级 HSTS
    混合加密
      非对称 ECDHE密钥协商
      非对称 RSA/ECDSA签名
      对称 AES-GCM ChaCha20
    证书体系
      X509v3 RFC5280
      信任链 根中间叶子
      SAN 域名校验唯一依据
      EKU serverAuth
      fullchain 必须下发中间证书
      通配符与多域名证书
    校验流程
      链构建与签名验证
      有效期
      域名匹配
      吊销 CRL OCSP Stapling
      证书透明 SCT
      CertificateVerify验签
    加密可见性
      加密 路径 查询 首部 Cookie 正文
      明文 IP 端口 SNI 包长时序
      DNS DoH/DoT保护
      ECH 加密ClientHello
    安全首部
      HSTS  preload
      CSP upgrade-insecure-requests
      Alt-Svc 通告h3
      废弃 HPKP
    迁移实践
      ACME自动签发 Let's Encrypt
      80端口301跳转
      混合内容治理
      Cookie加Secure
      证书到期监控
    性能优化
      TLS1.3 1RTT与0RTT
      会话恢复 Ticket PSK
      OCSP Stapling
      ECDSA证书
      HTTP2 HTTP3