透明防火墙主主部署 + ECMP 导致业务访问极慢:一次非对称路径故障分析
关键词 :透明网桥、状态检测、ECMP、LACP、非对称路由、会话同步、策略路由
适用读者 :网络运维 / 网络安全工程师
故障等级:业务可用性严重受损(可用但极慢)
目录
- 一、故障现象
- 二、拓扑与关键配置
- 三、根因分析
- [3.1 选路点辨析:LACP 不是元凶,ECMP 才是](#3.1 选路点辨析:LACP 不是元凶,ECMP 才是)
- [3.2 非对称路径 × 状态检测 = 单向丢包](#3.2 非对称路径 × 状态检测 = 单向丢包)
- [3.3 为什么是「极慢」而不是「不通」](#3.3 为什么是「极慢」而不是「不通」)
- 四、定位与验证步骤
- 五、解决方案对比与实施
- 六、附带隐患与加固建议
一、故障现象
- PC(192.168.0.0/24)访问 Server(172.16.0.0/16)速度极慢,但并非完全不可达;
- 部分连接能建立、部分连接长时间无响应,传输速率波动剧烈;
- 防火墙策略已配置为「允许任意流量经过」,排除策略拦截因素;
- 拓扑中存在两条等价路径(FW1 / FW2),链路带宽与设备 CPU、内存均无明显瓶颈。
二、拓扑与关键配置

- 防火墙**主主模式**部署,与接入交换机、堆叠核心之间均运行 LACP;
- 每台防火墙创建**一组透明网桥**,策略默认允许;
- PC 网关位于接入交换机,Server 网关位于堆叠核心;
- 接入与核心之间使用 **VLAN100 / VLAN101 两个三层互联 VLAN**,通过 **ECMP 静态路由**做负载分担。
**接入交换机主要配置:**
```bash
! 创建 ECMP 的 2 个互联 VLAN
vlan 100
description to FW1
!
vlan 101
description to FW2
!
! 创建客户端 VLAN
vlan 2
description to Client
! 创建 2 组聚合口用于和防火墙互联
interface bond0
switchport access vlan 100
bond mode dynamic
description FW1
!
interface bond1
switchport access vlan 101
bond mode dynamic
description FW2
! 将物理接口加入对应聚合组
interface twenty-fivegige0_0
switchport access vlan 100
bond group 1
speed 10G
!
interface twenty-fivegige0_1
switchport access vlan 100
bond group 1
speed 10G
!
interface twenty-fivegige0_2
switchport access vlan 101
bond group 2
speed 10G
!
interface twenty-fivegige0_3
switchport access vlan 101
bond group 2
speed 10G
! 配置互联 VLAN IP
interface vlan-if100
ip address 10.0.0.1/30
!
interface vlan-if101
ip address 10.0.0.5/30
! 配置 Client 端网关
interface vlan-if2
ip address 192.168.0.254/24
! 创建 2 条 ECMP 静态路由
ip route 172.16.0.0/16 10.0.0.2
ip route 172.16.0.0/16 10.0.0.6
Server 侧堆叠核心配置与接入层对称(VLANIF 互联地址互为对端,回程同样为两条等价静态路由)。
技术备注 :注意本拓扑中
bond0与bond1是两条彼此独立的三层路径(VLAN100 / VLAN101 分属不同二层域),并非同一聚合组内的两个成员口。这一点是后续分析的起点。
三、根因分析
3.1 选路点辨析:LACP 不是元凶,ECMP 才是
一种常见理解是「只要两端 LACP 配置妥当,流量就应来回路径一致」。该理解在本拓扑中不成立,原因有两点:
-
LACP 的作用域是聚合组内部 。LACP 的负载分担 hash 只决定「本端从聚合组的哪个成员口把报文发出去」。本例中,
bond0的两个成员口都指向 FW1,bond1的两个成员口都指向 FW2------无论 hash 如何计算,报文到达的下一跳设备是确定的,聚合内选口不改变路径。 -
真正的选路发生在三层 ECMP 。
ip route 172.16.0.0/16 10.0.0.2与ip route 172.16.0.0/16 10.0.0.6构成等价路由,交换机对每条流做逐流 hash 后选择 FW1 或 FW2。接入侧与核心侧各自独立计算,互不协商。去程(接入侧 hash):hash(192.168.0.10 → 172.16.0.100) ⇒ 下一跳 10.0.0.2 ⇒ FW1
回程(核心侧 hash):hash(172.16.0.100 → 192.168.0.10) ⇒ 下一跳 10.0.0.5 ⇒ FW2
↑ 两端独立计算,结果不保证一致
3.2 非对称路径 × 状态检测 = 单向丢包
故障链条如下:
#mermaid-svg-ihbx0qlVoxEDRDbV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ihbx0qlVoxEDRDbV .error-icon{fill:#552222;}#mermaid-svg-ihbx0qlVoxEDRDbV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ihbx0qlVoxEDRDbV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ihbx0qlVoxEDRDbV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ihbx0qlVoxEDRDbV .marker.cross{stroke:#333333;}#mermaid-svg-ihbx0qlVoxEDRDbV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ihbx0qlVoxEDRDbV p{margin:0;}#mermaid-svg-ihbx0qlVoxEDRDbV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster-label text{fill:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster-label span{color:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster-label span p{background-color:transparent;}#mermaid-svg-ihbx0qlVoxEDRDbV .label text,#mermaid-svg-ihbx0qlVoxEDRDbV span{fill:#333;color:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV .node rect,#mermaid-svg-ihbx0qlVoxEDRDbV .node circle,#mermaid-svg-ihbx0qlVoxEDRDbV .node ellipse,#mermaid-svg-ihbx0qlVoxEDRDbV .node polygon,#mermaid-svg-ihbx0qlVoxEDRDbV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ihbx0qlVoxEDRDbV .rough-node .label text,#mermaid-svg-ihbx0qlVoxEDRDbV .node .label text,#mermaid-svg-ihbx0qlVoxEDRDbV .image-shape .label,#mermaid-svg-ihbx0qlVoxEDRDbV .icon-shape .label{text-anchor:middle;}#mermaid-svg-ihbx0qlVoxEDRDbV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ihbx0qlVoxEDRDbV .rough-node .label,#mermaid-svg-ihbx0qlVoxEDRDbV .node .label,#mermaid-svg-ihbx0qlVoxEDRDbV .image-shape .label,#mermaid-svg-ihbx0qlVoxEDRDbV .icon-shape .label{text-align:center;}#mermaid-svg-ihbx0qlVoxEDRDbV .node.clickable{cursor:pointer;}#mermaid-svg-ihbx0qlVoxEDRDbV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ihbx0qlVoxEDRDbV .arrowheadPath{fill:#333333;}#mermaid-svg-ihbx0qlVoxEDRDbV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ihbx0qlVoxEDRDbV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ihbx0qlVoxEDRDbV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ihbx0qlVoxEDRDbV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ihbx0qlVoxEDRDbV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ihbx0qlVoxEDRDbV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster text{fill:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV .cluster span{color:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ihbx0qlVoxEDRDbV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ihbx0qlVoxEDRDbV rect.text{fill:none;stroke-width:0;}#mermaid-svg-ihbx0qlVoxEDRDbV .icon-shape,#mermaid-svg-ihbx0qlVoxEDRDbV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ihbx0qlVoxEDRDbV .icon-shape p,#mermaid-svg-ihbx0qlVoxEDRDbV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ihbx0qlVoxEDRDbV .icon-shape rect,#mermaid-svg-ihbx0qlVoxEDRDbV .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ihbx0qlVoxEDRDbV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ihbx0qlVoxEDRDbV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ihbx0qlVoxEDRDbV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
PC 发起 SYN
接入交换机 ECMP hash 命中 FW1
FW1 建立会话表项 透传至核心
核心转发至 Server
Server 回 SYN-ACK
核心 ECMP hash 命中 FW2
FW2 查会话表 未命中
是否 TCP 首包 SYN
状态检测丢弃
PC 重传 SYN 业务极慢
关键点在于 FW1 与 FW2 是两台独立的状态检测设备:
- 去程 SYN 经过 FW1,FW1 创建会话表项(五元组 + 状态机),由于策略全放通,报文被正常透传;
- 回程 SYN-ACK 经过 FW2,FW2 的会话表中不存在该会话;
- FW2 按首包处理流程检查:该报文不是 TCP 首包(无 SYN 标志),状态检测判定为非法报文,直接丢弃;
- PC 收不到 SYN-ACK,触发超时重传,TCP 建连时延被放大到秒级,表现为「访问极慢」。
技术备注 :透明网桥模式只改变了防火墙的二层转发行为(不改写 MAC、不查路由),并不等于关闭状态检测。只要防火墙仍工作在状态检测模式(绝大多数厂商的默认行为),非对称流量就会被单向丢弃。「透明 + 全放通」的组合容易让人误以为防火墙是「无状态的透明线缆」,这是本案例最大的认知盲区。
3.3 为什么是「极慢」而不是「不通」
这一现象本身是根因判定的重要佐证:
| 流量特征 | 表现 |
|---|---|
| hash 结果恰好对称的流(去程回程均选中同一台 FW) | 会话完整,通信正常 |
| hash 结果不对称的流 | 回程被丢弃,反复重传 |
| UDP / ICMP(部分厂商会话建立宽松) | 可能单向可达,业务表现各异 |
结果是「部分会话正常 + 部分会话重传」,叠加 TCP 拥塞退避,用户感知为时快时慢、整体极慢,而非彻底中断。若排查时发现「断掉一条链路后业务反而恢复正常」,即可高度确认本根因。
四、定位与验证步骤
Step 1 --- 收敛验证(最快确认根因)
在核心侧删除一条 ECMP 路由,仅保留一条,另一条改为高优先级浮动备份:
bash
! 接入侧与核心侧均改为单路径
ip route 172.16.0.0/16 10.0.0.2
ip route 172.16.0.0/16 10.0.0.6 preference 100 ! 备份路径,仅主路径失效时生效
若业务立即恢复正常,即可确认根因为路径不对称。
Step 2 --- 防火墙侧取证
| 检查项 | 观察点 |
|---|---|
| 会话表 | FW1 上同一五元组的会话仅存在去程方向的统计;FW2 上查无此会话 |
| 丢包计数 | 「状态检测丢弃 / 会话未命中 / 非首包丢弃」类计数持续增长 |
| 调试跟踪 | 单流跟踪回程报文,输出「无会话匹配」「反向路径检查失败」等日志 |
不同厂商命令名称存在差异,以下为常用入口(以设备实际版本为准):
bash
! 华为 USG 系列
display firewall session table
display firewall statistics system discard
! H3C SecPath 系列
display session table
display session statistics
! Fortinet FortiGate
diagnose sys session list
diagnose debug flow filter addr 192.168.0.10
diagnose debug flow trace start 100
! 山石 Hillstone
show session
show log debug
Step 3 --- 终端侧抓包
bash
! PC 侧抓包应观察到大量 SYN 重传、Dup ACK 或乱序
tcpdump -i any host 172.16.0.100 and tcp
! 典型现象:同一 SYN 以 1s / 2s / 4s 间隔重复出现,无 SYN-ACK 回应
Step 4 --- 验证 ECMP 双路径确实生效
bash
! 使用不同源端口触发不同 hash 结果,观察两条路径均被使用
traceroute -s 192.168.0.10 -p 10001 172.16.0.100
traceroute -s 192.168.0.10 -p 10002 172.16.0.100
技术备注:Step 1 的收敛验证务必在业务低峰执行,并提前确认单链路可承载峰值流量。这是唯一能在一分钟内给出确定性结论的手段,优先于任何抓包分析。
五、解决方案对比与实施
| 方案 | 做法 | 优点 | 代价 / 风险 | 适用场景 |
|---|---|---|---|---|
| A. 双机热备 + 会话同步 | FW1/FW2 建立 HA(华为 HRP 负载分担、H3C RBM、FortiGate FGCP 等),会话表互相同步,并开启非对称兼容 / 宽松状态检查 | 保留双链路带宽,对 hash 结果不敏感 | 要求同型号同版本、HA 心跳链路可靠;部分厂商透明模式对 HA 支持受限 | 追求带宽与高可用 |
| B. 确定性分流 PBR(推荐) | 取消 ECMP,按网段做策略路由:接入侧按 Client 网段分流,核心侧配置镜像的反向 PBR | 来回路径由配置确定性保证一致,双链路均承载流量 | 需维护分流表;流量均衡度取决于网段划分 | 透明防火墙双机旁挂的主流做法 |
| C. 主备路径 | 仅保留一条等价路由,另一条浮动优先级备份 | 改动最小、行为最可预测 | 平时仅用半数带宽 | 快速恢复业务 / 过渡方案 |
| D. 关闭状态检测 | 防火墙降级为非状态检测的包过滤 | 非对称流量可通 | 防护能力基本失效,IPS / AV / 应用识别全部不可用 | 不推荐 |
方案 B 配置示例(接入侧):
bash
! 按 Client 网段确定性分流,禁止依赖 hash
acl advanced 3001
rule 5 permit ip source 192.168.0.0 0.0.0.127 destination 172.16.0.0 0.0.255.255
!
acl advanced 3002
rule 5 permit ip source 192.168.0.128 0.0.0.127 destination 172.16.0.0 0.0.255.255
policy-based-route PBR-TO-FW permit node 10
if-match acl 3001
apply next-hop 10.0.0.2 ! 前半段走 FW1
!
policy-based-route PBR-TO-FW permit node 20
if-match acl 3002
apply next-hop 10.0.0.6 ! 后半段走 FW2
interface vlan-if2
ip policy-based-route PBR-TO-FW
bash
! 堆叠核心侧:配置镜像的反向 PBR,保证回程与去程严格同路径
acl advanced 3001
rule 5 permit ip source 172.16.0.0 0.0.255.255 destination 192.168.0.0 0.0.0.127
!
acl advanced 3002
rule 5 permit ip source 172.16.0.0 0.0.255.255 destination 192.168.0.128 0.0.0.127
policy-based-route PBR-TO-PC permit node 10
if-match acl 3001
apply next-hop 10.0.0.1 ! 与去程 FW1 对应
!
policy-based-route PBR-TO-PC permit node 20
if-match acl 3002
apply next-hop 10.0.0.5 ! 与去程 FW2 对应
interface vlan-if-server
ip policy-based-route PBR-TO-PC
技术备注 :方案 B 的本质是「用确定性的策略路由取代两端独立的 hash 计算」。PBR 的匹配条件必须双向对称------去程按源网段匹配,回程就必须按目的网段匹配,两端缺一不可。若只改接入侧而核心侧仍走 ECMP,问题依旧。
技术备注 :若选择方案 A(保留 ECMP),则必须同时满足「会话同步」与「宽松状态检查 / 非对称兼容」两个条件。仅配置 HA 会话同步而状态检查仍为严格模式时,回程报文虽能命中同步过来的会话,仍可能因序列号 / 状态机校验失败被丢弃。FortiGate 对应asymroute与tcp-session-without-syn一类开关,其余厂商请以各自文档为准。
六、附带隐患与加固建议
隐患 1:静态路由缺乏故障探测
互联 VLANIF 接口 up 仅代表物理链路连通。若防火墙软件层假死(接口仍 up,但网桥停止转发),ECMP 不会撤销该路径,形成黑洞路由。
bash
! 建议:静态路由绑定 BFD / NQA 探测,失败即撤销
ip route 172.16.0.0/16 10.0.0.2 track bfd-session 1
ip route 172.16.0.0/16 10.0.0.6 track bfd-session 2
! 或在互联段运行动态路由协议(OSPF),由协议感知邻接失效
隐患 2:安全能力实际已打折
即使通过关闭状态检测等手段让非对称流量「通了」,防火墙也只能看到单向流量,IPS、AV、应用识别、内容过滤均无法正常工作,透明串接的安全价值大幅下降。这也是最终建议迁移到方案 A 或 B 的根本原因。
隐患 3:hash 极化(Hash Polarization)
接入与核心两级逐流 hash 级联时,若使用相同算法与相同输入,可能出现两级 hash 结果高度相关,导致流量集中到单条链路。建议在多层 ECMP 组网中引入不同的 hash 种子 / 算法参数,或改用方案 B 的确定性分流。
总结
本次故障的直接原因是两台独立状态检测防火墙被部署为两条等价三层路径,而 ECMP 的逐流 hash 在两端独立计算,无法保证去程与回程选中同一台设备;回程报文在无会话、非首包的情况下被状态检测丢弃,导致 TCP 反复重传、业务极慢。
需要纠正一个常见误解:本案例中 LACP 不承担路径选择职责,真正的选路点是 ECMP;「LACP 无法制约对端」虽是正确原理,但用在本次定位上会掩盖真正的故障层级。
工程上的可靠解法只有两条:路径对称(PBR 确定性分流 / 主备路径) 或 会话共享(HA 会话同步 + 宽松状态检查,不推荐)。依赖「两端 hash 恰好对称」来保业务,属于不可控的运气,不应作为交付方案。