FortiGate 策略变更致分支机构 VPN 隧道全断的复盘

问题背景

公司采用 Hub-Spoke 组网架构,总部部署一台 FortiGate 200F 作为 VPN 中心节点,5 个分支机构各部署一台 FortiGate 60F,通过 IPSec Site-to-Site VPN 隧道互联。分支访问总部内网的流量以及分支间互访流量都经过总部中转。隧道使用 IKEv2 + 预共享密钥认证,运行稳定超过 2 年。

故障现象

12 月 6 日上午 9:00,网络安全工程师按计划实施了一次防火墙策略优化——在总部的 FortiGate 200F 上新增了一条允许内网网段出站访问互联网的策略。变更完成后约 5 分钟,运维监控告警:所有 5 个分支机构的 IPSec 隧道全部 Down

1
2
3
4
5
6
FG200F # get vpn ipsec tunnel summary
Branch-SH-DC  : down
Branch-BJ-DC  : down  
Branch-GZ-DC  : down
Branch-CD-DC  : down
Branch-SZ-DC  : down

总部内网终端无法 ping 通任何分支机构的服务器,分支机构的同事也无法访问总部的 ERP 和 OA 系统。全部分支-总部通信中断。

排查过程

第一步:确认是策略变更导致

回滚了最近一次的防火墙策略变更:删除新增的出站互联网访问策略。5 分钟后隧道自动全部恢复。确认是新增策略导致了隧道中断。

第二步:分析新增策略为什么影响 VPN

新增的策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
config firewall policy
    edit 0
        set name "Allow Internal to Internet"
        set srcintf "internal"
        set dstintf "wan1"
        set srcaddr "all"           # <--- 问题所在
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set nat enable              # <--- 问题所在
    next
end

策略匹配 srcaddr "all" + dstaddr "all",且开启了 nat enable(源 NAT)。

在 FortiGate 中,防火墙策略是按顺序匹配的(从上到下)。当这条"允许内网到互联网"的策略被放在策略列表顶部(edit 0)后,所有从内网出发的流量——包括发往分支机构网段的 VPN 流量——在到达 VPN 策略之前就被这条"Internet 出站"策略匹配了。

更致命的是 nat enable:VPN 流量被这条策略匹配后,在路由前被做了源 NAT,源 IP 变成了 wan1 的公网 IP,于是后续的 VPN 策略无法根据原始源 IP 匹配到对应的隧道规则。

第三步:验证流量路径

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
FG200F # diagnose sniffer packet any "host 10.2.1.1 and host 10.3.1.1" 4
interfaces=[any]
filters=[host 10.2.1.1 and host 10.3.1.1]
10. packets captured

pkt 1: 10.2.1.1 -> 10.3.1.1: icmp: echo request  
  # 进入 internal 口,源 10.2.1.1(总部内网)
  # 匹配策略 0 → NAT → 源 IP 变为 100.1.1.1(wan1公网IP)
  # 后续没有策略匹配 100.1.1.1 → 10.3.1.1
  # 数据包被丢弃

VPN 流量被"劫持"到了错误的安全策略中,并被 NAT 破坏了原始的源 IP。

第四步:完整策略列表分析

1
2
3
4
5
FG200F # show firewall policy
# 策略 0(新增): internal → wan1, src: all, dst: all, NAT enabled
# 策略 1: internal → wan1, src: Branch-SH, dst: Branch-SH-Subnet, NO NAT
# 策略 2: internal → wan1, src: Branch-BJ, dst: Branch-BJ-Subnet, NO NAT
# ...

VPN 策略(1-5)虽然存在,但由于策略 0 的 srcaddr "all" 完全覆盖了所有流量,VPN 策略永远不会被命中。FortiGate 的策略匹配是首次匹配即停止

解决方案

修正策略顺序和匹配条件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 必须先配置 VPN 策略(编辑为更高的序号,确保先匹配)
config firewall policy
    edit 6
        set name "Allow Internal to Internet"
        set srcintf "internal"
        set dstintf "wan1"
        set srcaddr "Internal-LAN"       # 明确指定内网地址对象
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set nat enable
    next
end

# 确保 VPN 策略在新互联网策略之前(策略 1-5)

或者更优的方案:在互联网策略中使用 negate 排除 VPN 目标:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
config firewall policy
    edit 0
        set name "Allow Internal to Internet"
        set srcintf "internal"
        set dstintf "wan1"
        set srcaddr "all"
        set dstaddr "all"
        set dstaddr-negate enable           # 否定all
        # 再加明确的排除分支地址对象
        ...
    next
end

根因分析

直接原因:新增的互联网出站策略使用了 srcaddr "all" + dstaddr "all" 的宽泛匹配条件,加上被放置在策略列表最顶部,且开启了 NAT,导致 VPN 流量在匹配到正确的 VPN 策略之前就被截获并做了错误的 NAT 处理。

深层原因:

  • 缺少"变更影响分析"流程——没人审查新增策略对现有 VPN 策略的影响
  • 策略列表缺乏优先级规划——VPN 策略在下方、通用出站策略在上方是反模式
  • 未使用 srcaddr-negate 或明确的地址对象来缩小匹配范围

预防措施

  1. 策略编排规范:VPN 策略必须在任何宽泛匹配的出站策略之前,且 VPN 策略必须包含精确的源/目标地址对象
  2. 策略变更前的影响分析:新增策略后通过 diagnose firewall proute list 检查路由-策略匹配路径
  3. 变更窗口和回滚计划:涉及防火墙策略的变更必须有明确的回滚步骤(像这次直接删除策略 0 就恢复了)
  4. 地址对象标准化:所有策略必须使用有意义的地址对象名称(Branch-SH-Subnet),禁止裸写 IP 范围
  5. 策略注释强制填写:每条策略必须写清楚"为什么需要这条策略",方便变更时审查
  6. 策略变更审批双签:涉及网络的防火墙策略变更需要第二人复核,重点检查是否会"劫持"其他流量

总结

防火墙策略管理最危险的错误不是"写了一条多余的策略",而是阻塞或破坏了一条关键的策略。在 FortiGate 的策略模型中,“all-to-all with NAT on top"是一条必须极其谨慎使用的规则——它的匹配范围只有"所有流量"和"不匹配"两种可能,而"所有流量"意味着 VPN、管理流量、监控流量等一切都会被它捕获。在防火墙上,精确永远比宽泛更安全,顺序永远比便利更重要。

使用 Hugo 构建
主题 StackJimmy 设计