📡 第五章 防火墙功能与防范威胁的对策
📄 一句话概括

会话表是状态检测防火墙的心脏——它记住「谁和谁在说话、说到哪了」。 没有这张表,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 秒实验

  1. 查一台防火墙的并发会话数与内存大小,用 150 字节乘一下对不对得上。
  2. 看它的默认 TCP 超时是多少秒。
  3. 想一想:如果超时设成 2 小时,会话表会变成几倍?

常见误区

  1. 以为会话表只记五元组。还要记序号与时间戳,否则挡不住伪造回包。
  2. 以为超时越长越好。超时与会话数成正比,长超时会吃掉表容量。
  3. 以为表满了会「整体变慢」。实际现象是「时通时不通」,很容易误判。
自测三问(点开对答案) 1. 状态检测比「只记五元组」多了哪两件事? —— 确认回包序号在窗口内、确认包的方向与状态一致。 2. 半开状态的超时为什么设得很短? —— 因为半开连接最容易被 SYN 洪水占满,短超时能让表快速回收。 3. 会话表打满时,用户看到的现象是什么? —— 时通时不通:老连接被挤掉后它的后续包被判非法丢弃,重连又恢复。

下一节:会话表要读的字段,是怎么从一堆字节里拆出来的。

相关笔记