在不把自己锁在门外的前提下测试防火墙变更
在规则生效前先给恢复路径排好序,然后用新策略必须评估的新连接去验证,而不是用侥幸存活的会话。
规则被写入,你手上那个终端仍在应答,而下一次登录却被拒绝。这个落差正是通过你正在改变的连接来测试防火墙变更的全部难点。连接跟踪只做一次判断,之后就不再观察,所以已建立的流是唯一看不见新策略的探针。下面会比较三条归路,然后确定改动和检查规则的顺序。
为什么侥幸存活的会话是最弱的证据
有状态防火墙只评估流的第一个数据包,并在表项存活期间沿用那次裁决。后加的规则只对之后才开始的流生效,所以正在输入的窗口依然可用,而其他人全被拒绝。你从中得到的只是几分钟前策略的描述。即便在这条流上抓包,看到的也只是机器早已做出的决定。
把仍然可用的会话当作逃生通道,而不是测量手段。值得做的检查都必须从新策略会评估的源地址发起一条新流,而且第一个检查应当是失败代价最大的那个。当这条会话是你唯一的入口时,这次变更还没有准备好。
三条归路,按各自依赖什么排序
按对被测设备的依赖程度给选项排序,因为规则出错时你抓的就是这个次序。从不穿过防火墙的控制台是独立的,演练过的回滚几乎独立,而已经打开的会话并不独立。
| Way back in | What it survives | Where it fails |
|---|---|---|
| out-of-band or hypervisor console | a policy that blocks new logins | needs separate access you have already tried |
| rollback rehearsed on that platform | a rule that breaks remote access | fails when nobody ever ran it |
| the session that is already open | the change itself | cannot show whether new flows work |
变更之前,先通过控制台登录并证明它可用,因为从未使用过的带外路径只是图纸,不是退路。回滚只有在同一平台、同一规则集上、按经批准的程序演练之后才配得上它的位置,而不是在在线机器上即兴操作。把步骤写下来,让别人念回来。如果这套流程需要靠你的记忆才能完成,它就不是计划。
一次只改一处,然后由一条必须被评估的连接来验证
保存正在运行的规则集和拥有它的文件,然后只做一处小改动。每次测试只改一处,结果才能归因;同时改两处,你只会得到一台还能用的机器,却不知道是哪处起了作用。平台能在不加载配置的情况下解析时,就先做这一步,让拼写错误在没有任何风险时暴露。
nft list ruleset > /root/ruleset.before
nft -c -f /etc/nftables.conf
然后在控制台仍然连着的时候,从改动后的规则会匹配的源地址发起一个新会话。成功就再重复一次,因为第一次尝试可能命中表里已有的表项。如果失败,你仍有一条进去的路和一个可以撤销的决定,这已是可用的最便宜的坏结果。
计数器、状态表和文件回答的是不同问题
这三种观察单独看都很有说服力,却可能让你误判另外两种。计数器显示你刚创建的流是否命中了改过的规则。状态表显示机器认为哪些流已经建立,正因如此,坏掉的规则看起来仍可能健康。保存的文件显示设备在下一次重载后会怎么做,而那可能并不是当前运行的规则集现在的行为。
ss -tn state established
把计数器当作增量来读而不是总量,因为唯一有意义的数字是你的测试流推动的那一个。计数器从不增加的规则就是没有匹配,无论纸面上看着多正确。也要确认拒绝那一侧:从未拒绝过任何东西的策略,从未证明它拦得住你真正想拦的东西。部署实际承载的每个协议族都要各走一条接口,因为 v4 规则对 v6 的流什么也没说。
从保存的规则集恢复,然后让文件与之一致
变更失败时,加载保存的规则集,而不是不断添加放行规则直到登录恢复。每多加一条放行,症状就安静一分,却留下一个比事故本身和记忆活得更久的洞。恢复、重连,然后把这次失败的对比和尝试记录放在一起。
变更成功后,让磁盘上的文件描述正在运行的规则集,并确认重载能够复现它。运行中的规则集若已偏离它自己的配置文件,就是为下一次重启埋下的陷阱。