This article describes how to troubleshoot Central NAT and traffic flow on FortiGate. It explains the packet processing order, routing considerations, firewall policy matching, and NAT behavior, and provides CLI and GUI troubleshooting methods.
FortiGate, FortiOS.
Central NAT on FortiGate is a powerful feature that enables flexible source and destination NAT policies. It is often used for complex deployments like VIPs, VPNs, and multi-VRF environments. However, troubleshooting Central NAT issues can be challenging due to its deep integration with routing, firewall policies, and UTM policies. In Central NAT mode, NATs and firewall policies are 2 independent modules.
This article provides a step-by-step troubleshooting guide focusing on:
Understanding Packet Flow in Central NAT
When a packet arrives at a FortiGate interface, it follows a specific sequence. This process ensures that the packet is handled correctly based on the configured rules and policies.
Example traffic flow and steps in red:
trace_id=76 func=print_pkt_detail line=6005 msg="vd-root:0 received a packet(proto=6, 192.168.1.10:49928->192.168.2.10:80) tun_id=0.0.0.0 from port2. flag [S], seq 4102116648, ack 0, win 64240"
trace_id=76 func=init_ip_session_common line=6204 msg="allocate a new session-00014233"
trace_id=76 func=iprope_dnat_check line=5481 msg="in-[port2], out-[]"
trace_id=76 func=iprope_dnat_tree_check line=824 msg="len=0"
trace_id=76 func=iprope_dnat_check line=5506 msg="result: skb_flags-02000000, vid-0, ret-no-match, act-accept, flag-00000000"
trace_id=76 func=__vf_ip_route_input_rcu line=1989 msg="find a route: flag=00000000 gw-192.168.10.2 via port3"
trace_id=76 func=__iprope_fwd_check line=810 msg="in-[port2], out-[port3], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"
trace_id=76 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=37, len=2"
trace_id=76 func=__iprope_check_one_policy line=2140 msg="checked gnum-100004 policy-1, ret-matched, act-accept"
trace_id=76 func=__iprope_user_identity_check line=1903 msg="ret-matched"
trace_id=76 func=__iprope_check line=2404 msg="gnum-4e20, check-ffffffffa002cb97"
trace_id=76 func=__iprope_check_one_policy line=2140 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
trace_id=76 func=__iprope_check_one_policy line=2140 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
trace_id=76 func=__iprope_check_one_policy line=2140 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"
trace_id=76 func=__iprope_check line=2421 msg="gnum-4e20 check result: ret-no-match, act-accept, flag-00000000, flag2-00000000"
trace_id=76 func=__iprope_check_one_policy line=2374 msg="policy-1 is matched, act-accept"
trace_id=76 func=__iprope_fwd_check line=847 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-1"
trace_id=76 func=iprope_fwd_auth_check line=876 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-1"
trace_id=76 func=iprope_reverse_dnat_check line=1353 msg="in-[port2], out-[port3], skb_flags-02000000, vid-0"
trace_id=76 func=iprope_reverse_dnat_tree_check line=916 msg="len=0"
trace_id=76 func=iprope_central_nat_check line=1376 msg="in-[port2], out-[port3], skb_flags-02000000, vid-0"
trace_id=76 func=__iprope_check_one_policy line=2140 msg="checked gnum-10000d policy-1, ret-matched, act-accept"
trace_id=76 func=get_new_addr line=1274 msg="find DNAT: IP-192.168.0.10, port-49928"
trace_id=76 func=__iprope_check_one_policy line=2374 msg="policy-1 is matched, act-accept"
trace_id=76 func=fw_forward_handler line=1002 msg="Allowed by Policy-1: SNAT"
trace_id=76 func=ip_session_confirm_final line=3179 msg="npu_state=0x100, hook=4"
trace_id=76 func=__ip_session_run_tuple line=3512 msg="SNAT 192.168.1.10->192.168.0.10:49928"
Note:
If use the DNAT mapped IP (VIP) in the Policy:
If the policy still uses the VIP, it won’t match, and traffic will hit the implicit deny (policy-0).
DNAT on Outgoing Traffic:
In some rare cases, DNAT applied on outgoing (egress) interface. The logic remains the same:
Note: Missing routes or policy for the translated IP cause policy drop issues.
Debug traffic flow and packet capture
The diagnose debug flow command is essential for tracing packet flow. Use the commands below to enable and use it for gathering traffic flow.
Reset debug filters and levels:
diagnose debug reset
diagnose debug flow filter clear
Set filter and parameters:
diagnose debug flow filter <parameter> <value>
diagnose debug flow show iprope enable
diagnose debug flow show function-name enable
diagnose debug console timestamp enable
diagnose debug flow trace start <number of packets>
View applied filters:
diagnose debug flow filter
enable/ disable debug:
diagnose debug enable
diagnose debug disable
Sometimes, it is necessary to see the packet's contents before and after the NAT process to troubleshoot. Use the diagnose sniffer packet command with a specific filter to capture packets.
diagnose sniffer packet any 'host < IP> and port <port>' 4
GUI Tools for Troubleshooting:
Under Policy & Objects -> Central NAT, find the rule, right-click, and select 'Show matching logs'.
Under Log & Report -> Forward Traffic, find the traffic and check NAT translations and policies.
Common Debug Scenarios and Error Messages:
Depending on the specific condition, such as an incorrect policy configuration or a routing issue, different error messages may be encountered. By analyzing these messages, it is possible to identify the root cause of the problem.
SNAT Issues:
No route to destination:
func=fw_forward_handler line=839 msg="Denied by forward policy check (policy 0)"
func=fw_forward_dirty_handler line=443 msg="state=00000208, state2=00000000, npu_state=40000100"
func=fw_post_route_handler line=1158 msg="Session is in BLOCK state. Drop the packet."
No matching policy:
func=fw_forward_handler line=839 msg="Denied by forward policy check (policy 0)"
Central-NAT policy problem:
func=__iprope_check_one_policy line=2374 msg="policy-0 is matched, act-accept"
func=fw_snat_check line=688 msg="NAT disabled by central SNAT policy!"
DNAT Issues:
No matching DNAT policy:
func=iprope_dnat_check line=5506 msg="result: skb_flags-02000000, vid-0, ret-no-match, act-accept, flag-00000000"
Host behind NAT unreachable:
Normal debug flow but diagnose sniffer packet shows:
551.958499 port3 in 192.168.2.10.60761 -> 192.168.5.10.80: syn 641016312
554.826495 port3 out 192.168.10.1 -> 192.168.2.10: icmp: host 192.168.5.10 unreachable
Or in some cases, shows ARP resolution failure:
17.511812 port2 out arp who-has 192.168.1.10 tell 192.168.1.1
Key Troubleshooting:
The Fortinet Security Fabric brings together the concepts of convergence and consolidation to provide comprehensive cybersecurity protection for all users, devices, and applications and across all network edges.
Copyright 2025 Fortinet, Inc. All Rights Reserved.