会话表是状态检测防火墙的心脏——它记住「谁和谁在说话、说到哪了」。 没有这张表,NAT、VPN、DoS 防御、内容扫描一个都做不成。
05.06 讲的是「它能挡什么」,从这一节开始逐个拆功能。 第一个必须是会话管理,因为后面所有功能都建在它上面。
一、一条会话记什么
最核心的是五元组:源地址、目的地址、源端口、目的端口、协议。 五项合起来唯一确定一条连接,这也是「一个会话」的身份。
字段 字节 作用
源/目的 IP 8 确定两端 源/目的端口 4 确定进程 协议号 1 TCP 6/UDP 17 状态与标志 1 新建/已建/关闭 双向序号 8 判是否在窗口内 时间戳 16 老化用
注意「双向序号」这一行:它才是状态检测真正的技术含量。 光记五元组只能做到「允许回包」,记住序号才能判「这个回包是不是真的属于这次通信」。
所以「状态检测」比「记五元组」多了两件事:确认回包的序号在窗口内、确认包的方向与状态一致。 这两条才是它能挡住「伪造回包」的原因。
二、三个状态与两个超时
TCP 有明确的状态机(SYN、ESTABLISHED、FIN 等),防火墙不需要全记,只记三类就够: 新建(只看到 SYN)、已建立、关闭中。
超时是这张表能活下去的关键:没有超时,表迟早会被填满;超时太短,长连接会被误杀。
状态 典型超时 为什么
新建(半开) 5~30 秒 防 SYN 洪水占表 已建立 5~60 分钟 照顾长连接 关闭中 几秒 等最后几个包
这张表解释了 D141 的那条公式:并发数 = 新建速率 × 超时时间。 所以「把超时调大」这个看似无害的动作,会让会话表按比例膨胀。 很多「设备撑不住了」的故障,起因就是有人为了迁就一个业务把超时改成了两小时。
三、表满了会怎样
这是最容易误判的一幕:用户报「网时通时不通」,而不是「网断了」。
原因是这样:表满时,新连接要建会话,设备只能「挤掉」最老的那条。 而那条老连接的下一个包到达时,它的会话已经不存在了,于是被判成「非法包」直接丢弃。 表现出来就是「刚才还在用的连接突然断了,重连又好了」。
三种缓解手段,代价各不相同: 加大内存(贵)、缩短超时(可能误杀长连接)、限速与限连接数(牺牲一部分用户)。
最有效的还是从源头看:先查清「是谁在制造大量短连接」, 因为正常业务极少把会话表打满,打满通常意味着有扫描、有环路、或者有程序在疯狂重连。
四、动手 Demo:一条会话在内存里占多少字节
这段把会话表的字段逐个列出来,算出裸字段总长, 再按「索引与对齐放大 4 倍」估算 100 万条会话要多少内存。
raw = 8 + 4 + 1 + 1 + 8 + 16
P(u" 裸字段合计 %d 字节。" % raw)
P(u" %d × 4 = %d 字节/条。" % (raw, raw * 4))
P(u" %d × 1,000,000 = %s 字节。" % (raw * 4, format(raw * 4 * 1000000, u",")))
实跑输出:
--------------------------------------------------------------------
一条会话在内存里占多少字节
--------------------------------------------------------------------
**状态检测防火墙的全部本事,都压在「会话表」这一张表上。**
字段 字节 说明
----------------------------------------------
源/目的 IP 8 IPv4 各 4 字节
源/目的端口 4 各 2 字节
协议号 1 TCP 6/UDP 17
状态与标志 1 新建/已建/关闭
双向序号 8 各 4 字节
时间戳 16 建立与最近活动
裸字段合计 38 字节。
加上哈希桶、链表指针、锁与对齐,实际放大 4 倍:
38 × 4 = 152 字节/条。
**按 100 万条会话算**:
152 × 1,000,000 = 152,000,000 字节 = 145 MB。
**所以「支持 100 万会话」这句话背后是 150 MB 以上的内存**,**而不是一个凭空的数字。**
38 字节这个数字不用记,要记的是「放大 4 倍」这个系数: 哈希桶、链表指针、锁、内存对齐,这些不存业务数据但必须存在。 所以规格书上的「100 万会话」实际要 150 MB 以上的内存。
顺带算一下「会话表与内存的比例」:每 10 万会话约 15 MB, 那么一台标称 1000 万会话的设备,光会话表就要 1.5 GB。 拿这个数去对规格书里的内存大小,就能判断标称值有没有水分。
最后提醒一句:会话表的「条数」和「新建速率」是两个独立指标, 前者受内存限、后者受 CPU 与哈希算法限。 买设备时只看前者,遇到「大量短连接」的业务照样会卡。
30 秒实验
- 查一台防火墙的并发会话数与内存大小,用 150 字节乘一下对不对得上。
- 看它的默认 TCP 超时是多少秒。
- 想一想:如果超时设成 2 小时,会话表会变成几倍?
常见误区
- 以为会话表只记五元组。还要记序号与时间戳,否则挡不住伪造回包。
- 以为超时越长越好。超时与会话数成正比,长超时会吃掉表容量。
- 以为表满了会「整体变慢」。实际现象是「时通时不通」,很容易误判。
自测三问(点开对答案)
1. 状态检测比「只记五元组」多了哪两件事? —— 确认回包序号在窗口内、确认包的方向与状态一致。 2. 半开状态的超时为什么设得很短? —— 因为半开连接最容易被 SYN 洪水占满,短超时能让表快速回收。 3. 会话表打满时,用户看到的现象是什么? —— 时通时不通:老连接被挤掉后它的后续包被判非法丢弃,重连又恢复。下一节:会话表要读的字段,是怎么从一堆字节里拆出来的。
- ☐ (本节完,下一节 05.07.02 分组结构解析)