TLS 把应用的字节流切成一条条记录,每条记录单独加密、认证。这篇抓包看这些记录:一次 write 变成多长的记录、每条固定多出多少字节、大块数据怎么切、为什么小消息写得越碎越吃亏,以及记录长度在线上为什么泄露了消息大小。
TLS 1.3(协商 TLSv1.3,TLS_AES_256_GCM_SHA384):最后 5 条应用数据记录的长度(记录体,不含 5 字节记录头)= [18, 27, 117, 1017, 10017]
每条的开销(记录体 − 明文 + 5 字节记录头):1 → 22, 10 → 22, 100 → 22, 1000 → 22, 10000 → 22
TLS 1.2(协商 TLSv1.2,ECDHE-ECDSA-AES256-GCM-SHA384):最后 5 条应用数据记录的长度(记录体,不含 5 字节记录头)= [25, 34, 124, 1024, 10024]
每条的开销(记录体 − 明文 + 5 字节记录头):1 → 29, 10 → 29, 100 → 29, 1000 → 29, 10000 → 29
TLS 1.3:记录体 = 明文 + 1 字节真实内容类型 + 16 字节认证标签 → 开销 22 字节(含 5 字节头);TLS 1.2 GCM:记录体 = 8 字节显式 nonce + 密文 + 16 字节标签 → 开销 29 字节。最外层的“记录类型”在 TLS 1.3 里一律写成 23(ApplicationData),真实类型藏在密文里
记录长度明文可见:1 → 10 → 100 → 1000 → 10000 的明文长度,在线上对应的记录长度严格单调且差值恰好等于明文差——路径上的观察者能看出每条消息有多长TLS 1.3 固定 22 字节,TLS 1.2 GCM 固定 29 字节,与明文长度无关;记录长度在线上明文可见,观察者能看出每条消息有多长(TLS 1.3 允许填充来掩盖,本篇没有测)。
一次写 100000 字节,最后出现的记录体长度:[69, 16401, 16401, 16401, 16401, 16401, 16401, 1713] 其中 6 条是满的记录(体 16401 字节 = 16384 明文 + 1 类型字节 + 16 标签 = 16401);剩下的是尾部较短的记录;总共 100188 字节密文承载 100000 字节明文 TLS 记录明文最大 2^14 = 16384 字节;100000 ÷ 16384 = 6.10 → 需要 7 条记录;额外开销 7 × 22 = 154 字节(0.15%)
明文最大 16384 字节一条;100000 字节需要 7 条记录。
40 次 × 100 字节:线上应用数据记录 40 条(最后这批),合计记录体 4680 字节,加上记录头 4880 字节;明文 4000 字节;开销 880 字节(22.0%) 1 次 × 4000 字节:线上应用数据记录 1 条(最后这批),合计记录体 4017 字节,加上记录头 4022 字节;明文 4000 字节;开销 22 字节(0.5%) 每条记录固定多 22 字节的头 + 标签,所以小消息越碎、开销占比越高;应用要合并小写入(或依赖 TCP 层之上的缓冲)
40 次小写入的开销是一次大写入的 40 倍(22.0% 对 0.5%)。