模块一 · 应用层
HTTPS 与 TLS
HTTP 的内容是明文的 —— 能观察或控制传输路径的人可能读取明文;仅同一Wi-Fi并不自动具备捕获所有流量的能力。HTTPS 在 HTTP 和 TCP 之间插了一层 TLS 来解决这件事。本章讲清 TLS 到底提供了什么保证,以及为什么它能防住中间人。
本章要解决的问题:HTTP 的内容是明文的 —— 能观察或控制传输路径的人可能读取明文;仅同一Wi-Fi并不自动具备捕获所有流量的能力。HTTPS 在 HTTP 和 TCP 之间插了一层 TLS 来解决这件事。本章讲清 TLS 到底提供了什么保证,以及为什么它能防住中间人。
本章的证据来源:历史实测记录(用 Node 的 TLS 模块对多个真实网站做 ALPN 与协议版本协商、curl -v 的握手输出)。协议定义出自 RFC 8446(TLS 1.3)与 RFC 5246(TLS 1.2)。
先从一个例子理解概念
把消息藏起来还不够:如果对面冒充了银行,你可能只是和冒充者加密通信。HTTPS既需要保护内容,也需要按规则核对目标身份。
加密、检错与身份:TLS的任务
HTTPS是带安全保护的HTTP通信,涉及TLS(传输层安全协议)。机密性让旁观者难以读内容,完整性帮助发现篡改,认证按信任规则核对对端身份。
谁的公钥:证书、CA与信任链
证书把身份信息和公钥等绑定在一起;CA(证书颁发机构)签发证书。信任链把服务器证书连接到客户端认可的信任起点,还要核对主机名与有效期等条件。
用密钥保护内容:对称与非对称机制
对称加密用共享的秘密密钥处理数据;非对称机制使用成对的公钥与私钥。TLS把密钥协商、签名认证和数据保护组合起来,它们不是同一个动作。
互相协商:握手、RTT与ALPN
握手是建立安全通信所需的消息交换;RTT是一来一回的时间。ALPN是握手中选择双方支持的应用协议的机制,例如选择HTTP/2。
没等服务器回答就发:0-RTT
0-RTT早期数据允许满足条件的客户端提前发送;不意味着整个安全确认已完成,也有被跨连接重复使用的重放风险。不能把“会话恢复”直接等同自动0-RTT。
下面再用这些概念看原理、命令和结果。规范与官方资料列在本章末尾,类比只帮助理解,不代替协议规则。
明文 HTTP 的三个问题
假设你在咖啡店连 Wi-Fi,用 HTTP 登录一个网站,密码以明文形式发出去:
| 问题 | 后果 |
|---|---|
| 没有加密 | 能够捕获或控制传输路径的人可能读取明文内容 |
| 没有完整性校验 | 中间设备可以偷偷改内容 —— 比如把转账的收款账号换掉,你毫无察觉 |
| 没有身份验证 | 你连的那个"银行网站"可能根本是假的(DNS 被污染、或者你连的是攻击者的热点) |
HTTPS = HTTP + TLS,就是在 HTTP 之下、TCP 之上插一层 TLS,解决这三个问题。
TLS 提供的三件事
| 保证 | 机制 | 解决上面哪个问题 |
|---|---|---|
| 机密性 | 加密,别人看不懂 | 第一个 |
| 完整性 | 校验,改过就能发现 | 第二个 |
| 身份认证 | 证书,确认对方是谁 | 第三个 |
注意第三点是 HTTPS 和"只是加密"的关键区别。 只加密不验证身份是不够的 —— 攻击者可以跟你建立一条加密连接,只要你不检查"对面到底是谁"。
对称加密与非对称加密
TLS中的几个任务需要分开:
| 任务 | 常见机制 | 作用 |
|---|---|---|
| 密钥协商 | 临时(EC)DHE或PSK相关模式 | 为会话导出共享秘密与流量密钥 |
| 身份认证 | 证书链与CertificateVerify签名,或PSK | 证明对端控制相应密钥并符合信任策略 |
| 保护应用数据 | 对称认证加密,如AES-GCM | 提供机密性与完整性 |
因此不能说“非对称机制只负责把同一把对称密钥给对方”。密钥交换、数字签名和公钥加密不是同一个操作;不同方向通常使用不同流量密钥。RFC 8446 §2、§4.4、§7
证书与 CA:为什么需要第三方
非对称加密有个前提:你得确信手里的公钥真的是对方的。
如果攻击者把自己的公钥塞给你,说"这是银行的",那整个加密体系就白搭了 —— 你能跟攻击者加密通信,但内容他都看得到。
所以需要第三方背书:CA(Certificate Authority,证书颁发机构)。
① 网站把公钥和自己的域名交给 CA,证明"这个域名确实是我的"
② CA 验证通过后,用【CA 自己的私钥】给这份信息签名
→ 这个签名结果就是【证书】
③ 浏览器访问网站时,网站把证书发过来
④ 浏览器用【CA 的公钥】验证签名 —— 签名有效,说明这份证书确实是 CA 签发的浏览器怎么知道 CA 的公钥? 因为操作系统和浏览器出厂时就内置了一批根证书(Root CA)。这些是信任的起点。
证书链:实际部署中,服务器证书往往不是根 CA 直接签的,而是中间 CA 签的:
根 CA(内置在浏览器里)
└ 中间 CA(由根 CA 签名)
└ 服务器证书(由中间 CA 签名)客户端还需校验证书链、有效期、用途、目标主机名及其他适用策略,并验证对端拥有对应私钥;单纯链条签名有效不等于能信任任何域名。证书也不是对网站业务诚信的保证。
TLS 1.2 与 1.3:握手要几个来回
| 场景 | 常见等待 | 条件 |
|---|---|---|
| TLS1.2完整握手 | 通常约2RTT | 不计TCP建连,恢复与False Start等情况不同 |
| TLS1.3普通握手 | 通常约1RTT | HelloRetryRequest等会增加交互 |
| TLS1.3会话恢复 | 可仍为1RTT | 恢复不意味着自动使用早期数据 |
| TLS1.3早期数据 | 客户端可在等响应前发送 | 需先前会话及双方许可,服务端可拒绝 |
0-RTT不是免费且等价安全的普通握手。 早期数据存在跨连接重放风险,也不具备完整前向保密;应用必须限制可接受的操作。TLS1.3移除了静态RSA密钥交换,但PSK-only和早期数据的安全性质仍需分别说明。RFC 8446 §2.3、§8
实测:真实服务器的协议协商结果
用 Node 的 TLS 模块连几个真实网站,看它们各自协商出什么:
tls.connect({ host, port: 443, servername: host, ALPNProtocols: ['h2','http/1.1'] })历史实测记录结果:
| 网站 | ALPN 协商出的应用协议 | TLS 版本 |
|---|---|---|
github.com | h2(HTTP/2) | TLSv1.3 |
www.cloudflare.com | h2(HTTP/2) | TLSv1.3 |
www.baidu.com | http/1.1 | TLSv1.2 |
这张表说明了两件事:
① 同一个客户端访问不同的网站,协商结果可以完全不同。 这依赖"协商"机制 —— 不是客户端单方面决定用哪个版本,而是双方谈出来的。
② 老协议的淘汰是渐进的。 baidu.com 协商到 HTTP/1.1 + TLS 1.2,说明它(或这条路径上的某个环节)还没启用新版本。这在实际网络里很常见 —— 协议的存在和支持是两回事。
ALPN:在握手里顺便协商应用协议
注意上一节那个参数:ALPNProtocols: ['h2','http/1.1']。这就是 ALPN(Application-Layer Protocol Negotiation,应用层协议协商)。
没有 ALPN 会怎样?
① 先完成 TLS 握手(一个往返)
② 然后再问:"你支持 HTTP/2 吗?"(又一个往返)
③ 协商完才开始传数据有 ALPN 之后:客户端在 TLS 握手的第一个包(ClientHello)里就把"我支持 h2 和 http/1.1"一起说了,服务器在响应里直接选定一个。在现有TLS握手内完成应用协议选择,不另加协商轮次;具体节省量取决于比较的替代流程。
ALPN声明所支持的协议还不够,服务端和客户端必须真正实现HTTP/2。
实测:curl 用的 TLS 实现
curl --version实测输出:
curl 8.21.0 (Windows) libcurl/8.21.0 Schannel zlib/1.3.2 WinIDN WinLDAPSchannel 是 Windows 原生的 TLS 实现(不是 curl 自带的 OpenSSL)。
在 curl -v 的输出里也能看到它:
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1这解释了一个细节:ALPN: curl offers http/1.1 —— 它只提供了 http/1.1,没提供 h2。为什么?因为这个 curl 编译时没有带 HTTP/2 支持(下一章会验证)。所以"能不能用 HTTP/2"取决于客户端实现,不只看服务器。
中间人为什么能解密
上一章留了个问题:公司代理怎么看到 HTTPS 内容?
答案:它安装了自己的根证书。
① 公司通过组策略把【公司自己的根证书】装进所有员工电脑的信任列表
② 代理拦截你的 HTTPS 连接,假装是你要访问的网站,用【临时生成的证书】跟你握手
(这个临时证书由公司的根 CA 签发,所以你的电脑认为是可信的)
③ 代理同时作为客户端,去和真实网站建立另一条 HTTPS 连接
④ 客户端到代理、代理到真实服务器各有TLS连接;代理在两条连接之间解密/检查,再重新加密这在技术上是标准的中间人攻击,只是根证书被合法安装了,所以浏览器不报警。
怎么发现自己在被解密? 看证书的签发者 —— 如果签发者是公司名字而不是公信 CA(比如 Let's Encrypt、DigiCert),说明就是公司代理签的。企业环境里这属于正常配置,个人设备上的未知受信根证书或异常签发链需要进一步核实,陌生CA名称本身不证明攻击。
常见误解
误解一:"HTTPS 就是加密的 HTTP"
加密只是三分之一。TLS 还提供完整性和身份认证,其中身份认证是防中间人的关键。只加密不验证身份的话,你可能是跟攻击者加密通信。
误解二:"非对称加密用来加密所有数据"
不是,它太慢了。 非对称机制还用于签名认证,密钥协商不等于把一把密钥直接发送给对端,真正的数据传输用对称加密。这是 TLS 最核心的设计取舍。
误解三:"HTTPS 让代理和运营商什么都看不到"
可见信息取决于部署:未保护的SNI或明文CONNECT可能暴露目标主机名,IP和流量特征仍可能被观察;ECH、加密DNS和加密代理链路会改变部分可见性,不能凭这些概念保证匿名。终止并受客户端信任的检查代理可读取明文,而纯转发代理通常不能读取HTTP内容。
误解四:"看到证书签发者不认识就是被攻击了"
在企业网络里,这可能是公司正常的 HTTPS 检查。判断标准是:这台电脑是不是公司管理的、根证书是不是通过组策略装的。但在个人设备上出现未知的签发者,就应该警惕。
本章小结
| 结论 | 性质 |
|---|---|
| TLS保护机密性与完整性,并依据认证模式验证对端 | RFC 8446 |
| 密钥交换、数字签名、对称认证加密是不同任务 | 协议机制 |
| 验证证书还需主机名、有效期、用途与信任策略 | 认证条件 |
| TLS1.3常见1RTT,恢复不必然0RTT | 有条件时延 |
| 0RTT早期数据有重放和前向保密限制 | 安全边界 |
| ALPN协商应用协议,双方仍需实际支持该协议 | RFC 7301 |
| 代理可见信息取决于CONNECT、SNI/ECH及是否终止TLS | 部署边界 |
自测题
7 题 · 先自己答,再展开对照
TLS 提供的三个保证分别解决什么问题?为什么"只加密"不够?
机密性(加密,防窃听)、完整性(校验,防篡改)、身份认证(证书,防冒充)。
"只加密"不够的原因:如果对方是攻击者,你跟他加密通信毫无意义 —— 他能解密、能读到全部内容。必须先确认"对方真的是我要找的那台服务器",加密才有意义。这就是身份认证不可少的原因,也是 HTTPS 和"自己写个加密协议"的关键区别。为什么不用非对称加密直接加密所有数据?
大量数据通常用高效对称认证加密;临时密钥交换用于导出会话密钥,非对称签名用于认证。不能说非对称机制只做密钥传递。浏览器凭什么信任一个从没见过网站的证书?
验证受信证书链、目标主机名、有效期、用途等,并通过握手签名确认对端控制私钥。只验CA签名不足以确认目标主机。TLS 1.2 和 1.3 的握手分别需要几个往返?这在跨国访问时意味着多大的差别?
普通完整握手常见TLS1.2约2RTT、TLS1.3约1RTT,不计TCP。TLS1.3恢复仍可1RTT,允许早期数据才可0RTT发送,且有重放等限制;重试等会增加轮次。ALPN 解决了什么问题?
在TLS握手中选择双方支持的应用协议,不增加单独协商轮次;实现仍需支持HTTP/2等协议,不能只加一个字段。你通过公司代理访问 HTTPS 网站,代理能看到什么、看不到什么?
能看到:你连的是哪个主机和端口(通过明文的 SNI 字段或代理的CONNECT请求 —— 历史实测记录确实能看到CONNECT www.cloudflare.com:443)。
看不到(在不解密的情况下):传输的具体内容,因为隧道里是密文。
但如果代理安装了公司根证书做中间人解密,它就能看到全部内容 —— 这是企业环境里真实存在的合法做法。你在个人笔记本上发现某个网站的证书签发者是一个陌生的公司名字。这可能是什么情况?
陌生商业CA可能合法,也可能是本地检查代理;应查看完整证书链、主机名和信任来源,结合管理员配置核对,不能仅凭名字宣布被攻击。
参考资料与适用范围
修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。