VIP 匹配顺序
VIP 匹配顺序
网络拓扑

初始状态下,FortiGate 的公网接口 port1 上配置了 1 个 VIP:从公网 IP 202.103.1.1 全映射到 Server1 10.10.1.100(VIP1)。
config firewall vip edit "VIP1" set extip 202.103.1.1 set mappedip "10.10.1.100" set extintf "port1" next end创建 1 条防火墙策略(VIP1_Policy)引用 VIP1,公网客户端通过 VIP1_Policy 策略访问 Server1。
config firewall policy edit 1 set name "VIP1_Policy" set srcintf "port1" set dstintf "port2" set action accept set srcaddr "all" set dstaddr "VIP1" set schedule "always" set service "ALL" next end
问题现象
由于业务需求,需要增加与 VIP1 相同的公网 IP 202.103.1.1 的 80 端口映射到 Server2 10.10.1.100 的 80 端口(VIP2),创建后 VIP2 位于 VIP1 后边。
config firewall vip edit "VIP1" set extip 202.103.1.1 set mappedip "10.10.1.100" set extintf "port1" next edit "VIP2" set extip 202.103.1.1 set mappedip "10.10.1.200" set extintf "port1" set portforward enable set extport 80 set mappedport 80 next end创建防火墙策略 VIP2_Policy,引用 VIP2,将 VIP2_Policy 移动到 VIP1_Policy 之前。当前的需求是,按照防火墙策略的顺序:
- 访问 VIP 202.103.1.1 的 80 端口的流量应该优先匹配 VIP2_Policy。
- 访问 VIP 202.103.1.1 的其他端口的流量应该匹配 VIP1_Policy。
config firewall policy edit 2 set name "VIP2_Policy" set srcintf "port1" set dstintf "port2" set action accept set srcaddr "all" set dstaddr "VIP2" set schedule "always" set service "ALL" next edit 1 set name "VIP1_Policy" set srcintf "port1" set dstintf "port2" set action accept set srcaddr "all" set dstaddr "VIP1" set schedule "always" set service "ALL" next end但实际情况是:公网客户端(202.103.1.200)访问 VIP(202.103.1.1)的 80 端口(或其他任意端口),流量经过 DNAT 后,目标地址仍然被转换为 VIP1 对应的 Server1 IP 10.10.1.100,会话匹配策略为 VIP1_Policy(ID 1)。这不符合预期。
session info: proto=6 proto_state=01 duration=10 expire=3589 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3 ...... orgin->sink: org pre->post, reply pre->post dev=3->4/4->3 gwy=0.0.0.0/0.0.0.0 hook=pre dir=org act=dnat 202.103.1.200:50883->202.103.1.1:80(10.10.1.100:80) <----DNAT的地址仍为VIP1映射的Server1 hook=post dir=reply act=snat 10.10.1.100:80->202.103.1.200:50883(202.103.1.1:80) ...... misc=0 policy_id=1 pol_uuid_idx=15851 auth_info=0 chk_client_info=0 vd=0 ......查看策略 VIP2_Policy(ID 2)的匹配计数,始终为 0。
FortiGate # diagnose firewall iprope show 100004 2 idx:2 pkts:0 (0 0 0 0 0 0 0 0) bytes:0 (0 0 0 0 0 0 0 0) asic_pkts:0 (0 0 0 0 0 0 0 0) asic_bytes:0 (0 0 0 0 0 0 0 0) flag:0x0查看策略 VIP1_Policy(ID 1)的匹配计数,持续增长。
FortiGate # diagnose firewall iprope show 100004 1 idx:1 pkts:282 (282 0 0 0 0 0 0 0) bytes:15921 (15921 0 0 0 0 0 0 0) asic_pkts:0 (0 0 0 0 0 0 0 0) asic_bytes:0 (0 0 0 0 0 0 0 0) flag:0x0 hit count:54 (54 0 0 0 0 0 0 0) first hit:2025-11-05 14:52:19 last hit:2025-11-05 16:27:38 established session count:0 first est:2025-11-05 15:02:00 last est:2025-11-05 15:53:55通过如下 CLI 命令查看 iprope 表特定流量的防火墙策略匹配情况,可以看到以上访问 VIP 80 端口的流量匹配的就是防火墙策略 VIP1_Policy(ID 1)。
diagnose firewall iprope lookup <src ip> <src port> <dst ip> <dst port> <protocol> <device> FortiGate # diagnose firewall iprope lookup 202.103.1.200 0 202.103.1.1 80 6 port1 <src [202.103.1.200-0] dst [202.103.1.1-80] proto 6 dev port1> matches policy id: 1
问题原因
由于 FortiGate 内核设计,VIP 转换始终优于防火墙策略进行处理:
- 首先流量到达 FortiGate 后,VIP 按照顺序从上向下依次匹配,并执行 DNAT 转换。
- 然后防火墙策略才会按照 DNAT 转换后的流量特征,顺序从上向下依次匹配。
当全映射 VIP(VIP1)排在 80 端口映射 VIP(VIP2)上方时,所有目标为该公网 IP 的流量均命中全映射 VIP(VIP1),并按照 VIP1 进行 DNAT 转换,导致转换后的流量无法匹配 VIP2_Policy。
通过观察防火墙 iprope 的 VIP 策略组(100000)也可以看到,VIP1 在 VIP2 之前:
相关信息
iprope 的相关解释请参考:策略与对象 → iprope 列表章节。
FortiGate # diagnose firewall iprope list 100000 policy index=15849 uuid_idx=15849 action=accept <----VIP1在前 flag (8000104): f_p nat pol_stats schedule() cos_fwd=0 cos_rev=0 group=00100000 av=00000000 au=00000000 split=00000000 host=0 chk_client_info=0x0 app_list=0 ips_view=0 misc=0 zone(1): 0 -> zone(1): 0 source(1): 0.0.0.0-255.255.255.255, uuid_idx=0, dest(1): 202.103.1.1-202.103.1.1, uuid_idx=15849, service(1): [0:0x0:0/(0,0)->(0,0)] flags:0 helper:auto nat(1): flag=0 base=202.103.1.1:0 10.10.1.100-10.10.1.100(0:0) policy index=15850 uuid_idx=15850 action=accept <----VIP2在后 flag (8000100): nat pol_stats schedule() cos_fwd=0 cos_rev=0 group=00100000 av=00000000 au=00000000 split=00000000 host=0 chk_client_info=0x0 app_list=0 ips_view=0 misc=0 zone(1): 0 -> zone(1): 0 source(1): 0.0.0.0-255.255.255.255, uuid_idx=0, dest(1): 202.103.1.1-202.103.1.1, uuid_idx=15850, service(1): [6:0x0:0/(0,65535)->(80,80)] flags:0 helper:auto nat(1): flag=0 base=202.103.1.1:80 10.10.1.200-10.10.1.200(80:80) ......
解决方法
调整 VIP 顺序,让映射 80 端口的 VIP(VIP2)排在全映射的 VIP (VIP1)之前,防火墙策略的顺序不需要调整。
config firewall vip move VIP2 before VIP1 end config firewall vip edit "VIP2" set extip 202.103.1.1 set mappedip "10.10.1.200" set extintf "port1" set portforward enable set extport 80 set mappedport 80 next edit "VIP1" set extip 202.103.1.1 set mappedip "10.10.1.100" set extintf "port1" next end公网客户端(202.103.1.200)再次访问 VIP(202.103.1.1)的 80 端口,流量经过 DNAT 后,目标地址被转换为 VIP2 对应的 Server2 IP 10.10.2.100,会话匹配策略为 VIP2_Policy(ID 2)。符合预期。
session info: proto=6 proto_state=01 duration=4 expire=3595 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3 ...... orgin->sink: org pre->post, reply pre->post dev=3->4/4->3 gwy=0.0.0.0/0.0.0.0 hook=pre dir=org act=dnat 202.103.1.200:58372->202.103.1.1:80(10.10.1.200:80) <----DNAT的地址变为VIP2映射的Server2 hook=post dir=reply act=snat 10.10.1.200:80->202.103.1.200:58372(202.103.1.1:80) ...... misc=0 policy_id=2 pol_uuid_idx=15852 auth_info=0 chk_client_info=0 vd=0 ......公网客户端(202.103.1.200)再次访问 VIP(202.103.1.1)的其他端口(如 443),流量经过 DNAT 后,目标地址被转换为 VIP1 对应的 Server1 IP 10.10.1.100,会话匹配策略为 VIP1_Policy(ID 1)。符合预期。
session info: proto=6 proto_state=06 duration=0 expire=4 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3 ...... orgin->sink: org pre->post, reply pre->post dev=3->4/4->3 gwy=0.0.0.0/0.0.0.0 hook=pre dir=org act=dnat 202.103.1.200:58617->202.103.1.1:443(10.10.1.100:443) <----DNAT的地址为VIP1映射的Server1 hook=post dir=reply act=snat 10.10.1.100:443->202.103.1.200:58617(202.103.1.1:443) ...... misc=0 policy_id=1 pol_uuid_idx=15851 auth_info=0 chk_client_info=0 vd=0 ......查看策略 VIP2_Policy(ID 2)已经开始有匹配计数。
FortiGate # diagnose firewall iprope show 100004 2 idx:2 pkts:46 (46 0 0 0 0 0 0 0) bytes:2029 (2029 0 0 0 0 0 0 0) asic_pkts:0 (0 0 0 0 0 0 0 0) asic_bytes:0 (0 0 0 0 0 0 0 0) flag:0x0 hit count:3 (3 0 0 0 0 0 0 0) first hit:2025-11-05 16:44:31 last hit:2025-11-05 16:50:40 established session count:1 first est:2025-11-05 16:44:31 last est:2025-11-05 16:50:40查询 iprope 表特定流量的防火墙策略匹配情况,可以看到访问 VIP 80 端口的流量匹配的是防火墙策略 VIP2_Policy(ID 2)。
diagnose firewall iprope lookup <src ip> <src port> <dst ip> <dst port> <protocol> <device> FortiGate # diagnose firewall iprope lookup 202.103.1.200 0 202.103.1.1 80 6 port1 <src [202.103.1.200-0] dst [202.103.1.1-80] proto 6 dev port1> matches policy id: 2