FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
hamidr
Staff
Staff
Article Id 405637
Description

 

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.

 

Scope

 

FortiGate, FortiOS.

 

Solution

 

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:

  • Packet flow and processing order
  • Routing considerations
  • Firewall policy and NAT interactions
  • Debugging commands and log analysis

 

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.

  • Ingress Interface: Packet enters ingress interface and virtual domain (VDOM).
  • Session Lookup: FortiGate checks for an existing session. If found, the packet is processed and forwarded based on the session's established rules, bypassing some subsequent checks.
  • DNAT Check: Applies if there is a matching Central NAT DNAT or VIP policy; the destination IP rewritten
  • Routing Lookup: Based on the post-DNAT destination IP, FortiGate determines the outgoing interface and VRF.
  • Firewall Policy Lookup: Matches source and (post/Pre-NAT) destination IP, ports, zones, and interfaces.
  • SNAT Check: If enabled, the source IP is translated after policy match.
  • Packet Forwarding: The packet is sent via the determined egress interface.

 

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:

  • SNAT: Use the pre-NAT source IP in the policy. SNAT applies after policy check.
  • DNAT: Use the post-NAT destination IP in the policy. DNAT applies before policy check
 

If use the DNAT mapped IP (VIP) in the Policy:

  • DNAT translates the destination IP before policy check.
  • Policy lookup tries to match the post-DNAT (real) IP.

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:

  • The destination IP is rewritten before routing and policy lookup.
  • The firewall policy must use the translated destination (Post-NAT) IP for matching.

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'.

 

centralnat.jpg

 

Under Log & Report -> Forward Traffic, find the traffic and check NAT translations and policies.

 

log.jpg

 

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:

  • New session:

 

func=fw_forward_handler line=839 msg="Denied by forward policy check (policy 0)"

 

  • Existing session after route change:

 

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:

  • Always check if policy uses the correct IP (post-NAT for DNAT, pre-NAT for SNAT).
  • Routing issues cause packets to be dropped before NAT is applied.
  • VRF configuration must match interface assignments for routes to work.
  • policy-0 drops indicate policy mismatch or routing failure.
  • Use both CLI debug and GUI logs for comprehensive visibility
Contributors