← Back to knowledge base
highRouting (BGP/OSPF/Static)

Troubleshooting FortiGate policy routing

Confirmed 8/8/2026

Problem

Traffic does not appear to follow the configured policy route, or confirmation is needed that FortiGate matched the intended policy route and firewall policy.

Symptoms

Traffic uses an unexpected path, continues to use a previous path, or is captured by another routing mechanism such as an overlapping SD-WAN rule.

Environment

FortiGate. Applies to IPv4 and IPv6 policy routing where supported. SD-WAN must also be considered when configured.

FortiOS version

7.6.3

Root Cause

Common causes include no matching active route for the policy route gateway, an existing session retaining the old path, or an overlapping SD-WAN rule selecting the same traffic. A policy route requires a corresponding active route in the routing table.

Solution

  1. Display the active policy routes and inspect their IDs, interfaces, source and destination ranges, hit counts, and last-used timestamps.
diagnose firewall proute list

Example:

Endeavour-kvm48 # diag firewall proute list

list route policy info(vf=root):
id=1(0x01) dscp_tag=0xfc 0xfc flags=0x0 tos=0x00 tos_mask=0x00 protocol=0 sport=0-0 iif=4(port2) dport=0-65535 path(1) oif=5(port3)
source wildcard(1): 192.168.184.0/255.255.255.0
destination wildcard(1): 1.1.1.1/255.255.255.255
hit_count=4 last_used=2024-08-29 16:27:32
  1. Review the policy engine data and kernel routing information.
diagnose firewall iprope list
get router info kernel
get router info routing-table all

A matching active route must exist for the policy route to operate. Example routing table:

Endeavour-kvm48 # get router info routing-table all

Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
V - BGP VPNv4
* - candidate default
Routing table for VRF=0

S*      0.0.0.0/0 [10/0] via 10.9.15.254, port1, [1/0]
S       1.1.1.1/32 [10/0] via 192.168.72.5, port3, [1/0]
C       10.0.199.0/24 is directly connected, rbarnes
C       10.9.0.0/20 is directly connected, port1
C       10.10.1.0/24 is directly connected, test123
C       10.10.1.1/32 is directly connected, test123
C       10.10.76.0/24 is directly connected, port6
C       10.103.23.0/24 is directly connected, VPN-3
C       10.103.23.1/32 is directly connected, VPN-3
C       10.253.240.0/20 is directly connected, wqt.root
C       192.168.24.0/24 is directly connected, vxlansw
C       192.168.56.0/24 is directly connected, test
C       192.168.72.0/24 is directly connected, port3
C       192.168.94.0/24 is directly connected, port4
C       192.168.184.0/24 is directly connected, port2
S       192.168.184.9/32 [10/0] is directly connected, gretoint, [1/0]
S       192.168.184.74/32 [10/0] is directly connected, gretoint, [1/0]
S       192.168.185.2/32 [10/0] is directly connected, gretoint, [1/0]
S       192.168.187.4/32 [10/0] is directly connected, gretoint, [1/0]
  1. Test the route lookup for the exact traffic tuple. Supply the destination IP, source IP, inbound interface, protocol, and destination port.
diag ip route match <dst-ip> <src-ip> <inbound-intf> <protocol> <dst-port>
  1. Configure debug-flow filters for the source and destination, enable policy-engine and function-name output, and capture 100 traces.
diagnose debug flow filter addr <source>
diagnose debug flow filter daddr <destination>
diagnose debug flow show iprope enable
diagnose debug flow show function-name enable
diagnose debug enable
diagnose debug flow trace start 100
  1. Inspect the trace for a policy-route match, the selected gateway and interface, and the accepting firewall policy. The following example shows policy route ID 1 choosing gateway 192.168.72.5 through port3, followed by firewall Policy-29 permitting the traffic:
id=65308 trace_id=1 func=init_ip_session_common line=6080 msg="allocate a new session-0ae78a65, tun_id=0.0.0.0"
id=65308 trace_id=1 func=iprope_dnat_check line=5281 msg="in-[port2], out-[]"
id=65308 trace_id=1 func=iprope_dnat_tree_check line=824 msg="len=0"
id=65308 trace_id=1 func=iprope_dnat_check line=5293 msg="result: skb_flags-02000000, vid-0, ret-no-match, act-accept, flag-00000000"
id=65308 trace_id=1 func=rpdb_srv_match_input line=1040 msg="Match policy routing id=1: to 1.1.1.1 via ifindex-5"
id=65308 trace_id=1 func=__vf_ip_route_input_rcu line=1990 msg="find a route: flag=00000000 gw-192.168.72.5 via port3"
id=65308 trace_id=1 func=iprope_fwd_check line=768 msg="in-[port2], out-[port3], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"
id=65308 trace_id=1 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=37, len=2"
id=65308 trace_id=1 func=__iprope_check_one_policy line=2033 msg="checked gnum-100004 policy-29, ret-matched, act-accept"
id=65308 trace_id=1 func=__iprope_user_identity_check line=1807 msg="ret-matched"
id=65308 trace_id=1 func=__iprope_check line=2281 msg="gnum-4e20, check-000000008ae915f5"
id=65308 trace_id=1 func=__iprope_check_one_policy line=2033 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
id=65308 trace_id=1 func=__iprope_check_one_policy line=2033 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
id=65308 trace_id=1 func=__iprope_check_one_policy line=2033 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
id=65308 trace_id=1 func=__iprope_check line=2298 msg="gnum-4e20 check result: ret-no-match, act-accept, flag-00000000, flag2-00000000"
id=65308 trace_id=1 func=__iprope_check_one_policy line=2251 msg="policy-29 is matched, act-accept"
id=65308 trace_id=1 func=iprope_fwd_check line=805 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-29"
id=65308 trace_id=1 func=iprope_fwd_auth_check line=824 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-29"
id=65308 trace_id=1 func=fw_forward_handler line=989 msg="Allowed by Policy-29:"
id=65308 trace_id=1 func=ip_session_confirm_final line=3113 msg="npu_state=0x100, hook=4"
id=65308 trace_id=2 func=print_pkt_detail line=5894 msg="vd-root:0 received a packet(proto=1, 192.168.184.105:1->1.1.1.1:2048) tun_id=0.0.0.0 from port2. type=8, code=0, id=1, seq=10."
id=65308 trace_id=2 func=resolve_ip_tuple_fast line=5982 msg="Find an existing session, id-0ae78a65, original direction"
id=65308 trace_id=2 func=npu_handle_session44 line=1327 msg="Trying to offloading session from port2 to port3, skb.npu_flag=00000400 ses.state=00000200 ses.npu_state=0x00000100"
id=65308 trace_id=2 func=fw_forward_dirty_handler line=439 msg="state=00000200, state2=00000000, npu_state=00000100"
id=65308 trace_id=3 func=print_pkt_detail line=5894 msg="vd-root:0 received a packet(proto=1, 192.168.184.105:1->1.1.1.1:2048) tun_id=0.0.0.0 from port2. type=8, code=0, id=1, seq=11."
id=65308 trace_id=3 func=resolve_ip_tuple_fast line=5982 msg="Find an existing session, id-0ae78a65, original direction"
id=65308 trace_id=3 func=npu_handle_session44 line=1327 msg="Trying to offloading session from port2 to port3, skb.npu_flag=00000400 ses.state=00000200 ses.npu_state=0x00000100"
id=65308 trace_id=3 func=fw_forward_dirty_handler line=439 msg="state=00000200, state2=00000000, npu_state=00000100"
id=65308 trace_id=4 func=print_pkt_detail line=5894 msg="vd-root:0 received a packet(proto=1, 192.168.184.105:1->1.1.1.1:2048) tun_id=0.0.0.0 from port2. type=8, code=0, id=1, seq=12."
id=65308 trace_id=4 func=resolve_ip_tuple_fast line=5982 msg="Find an existing session, id-0ae78a65, original direction"#
id=65308 trace_id=4 func=ipv4_fast_cb line=53 msg="enter fast path"
  1. Compare the policy-route ID in diagnose firewall proute list with the ID shown by debug flow. In this example, id=1 appears in both outputs, confirming that the policy route is functioning.

  2. Check the session table before treating the behavior as a policy-route configuration problem. An established session can keep traffic on the previous path.

  3. If SD-WAN is enabled, examine its rules for overlapping source, destination, service, or interface criteria. SD-WAN rules provide policy-based routing behavior and have their own precedence relative to config router policy; ensure an SD-WAN rule is not capturing the traffic.

  4. On FortiOS 7.6.3, users and groups can be configured as source filters in IPv4 and IPv6 routing policies. When this feature is used, verify that the traffic's user or group identity matches the policy route.

Verification

Confirm all of the following: the policy route has a nonzero or increasing hit_count; its last_used value updates; get router info routing-table all contains the required active route; debug flow reports Match policy routing id=1: to 1.1.1.1 via ifindex-5; route lookup selects gateway 192.168.72.5 through port3; and the expected firewall policy permits the flow, as shown by Allowed by Policy-29:. Matching id=1 in the policy-route list and debug flow verifies successful policy-route selection.

Tags

No tags yet.

Community rating

/ 5 (0)

Discussion (0)

    No comments yet.