This article explains how to configure Hairpin NAT when the server is located behind the same LAN interface.
The external IP address of the Server is from the same subnet but does not belong to FortiGate directly.
VIP:
config firewall vip
edit "VIP-test"
set extip 10.5.209.229
set mappedip "10.64.11.53"
set extintf "any"
set portforward enable
set extport 8080
set mappedport 80
next
end
In this scenario, configure two firewall policies. One is to allow access from LAN to WAN and the second policy is from LAN to LAN as below:
LAN-WAN Policy:
config firewall policy
edit 1
set name "LAN-to-WAN"
set srcintf "port5"
set dstintf "port3"
set action accept
set srcaddr "all"
set dstaddr "all"
set schedule "always"
set service "ALL"
set nat enable
next
end
LAN-LAN with Destination object as VIP:
config firewall policy
edit 2
set name "Hairpin LAN-to-LAN"
set srcintf "port5"
set dstintf "port5"
set action accept
set srcaddr "all"
set dstaddr "VIP-test"
set schedule "always"
set service "ALL"
next
end
If the second policy is not configured, the following logs will appear in the Flow debug:
id=65308 trace_id=385 func=print_pkt_detail line=5942 msg="vd-root:0 received a packet(proto=6, 10.64.8.32:60008->10.5.209.229:8080) tun_id=0.0.0.0 from port5. flag [S], seq 308377660, ack 0, win 64240"
id=65308 trace_id=385 func=init_ip_session_common line=6127 msg="allocate a new session-001a0baa"
id=65308 trace_id=385 func=iprope_dnat_check line=5480 msg="in-[port5], out-[]"
id=65308 trace_id=385 func=iprope_dnat_tree_check line=824 msg="len=1"
id=65308 trace_id=385 func=__iprope_check_one_dnat_policy line=5345 msg="checking gnum-100000 policy-1"
id=65308 trace_id=385 func=get_new_addr line=1274 msg="find DNAT: IP-10.64.11.53, port-80"
id=65308 trace_id=385 func=__iprope_check_one_dnat_policy line=5435 msg="matched policy-1, act=accept, vip=1, flag=100, sflag=2000000"
id=65308 trace_id=385 func=iprope_dnat_check line=5505 msg="result: skb_flags-02000000, vid-1, ret-matched, act-accept, flag-00000100"
id=65308 trace_id=385 func=fw_pre_route_handler line=191 msg="VIP-10.64.11.53:80, outdev-unknown"
id=65308 trace_id=385 func=__ip_session_run_tuple line=3487 msg="DNAT 10.5.209.229:8080->10.64.11.53:80"
id=65308 trace_id=385 func=__vf_ip_route_input_rcu line=1988 msg="find a route: flag=00000000 gw-0.0.0.0 via port5"
id=65308 trace_id=385 func=__iprope_fwd_check line=810 msg="in-[port5], out-[port5], skb_flags-020000c0, vid-1, app_id: 0, url_cat_id: 0"
id=65308 trace_id=385 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=63, len=1"
id=65308 trace_id=385 func=__iprope_check_one_policy line=2140 msg="checked gnum-100004 policy-0, ret-matched, act-accept"
id=65308 trace_id=385 func=__iprope_user_identity_check line=1903 msg="ret-matched"
id=65308 trace_id=385 func=__iprope_check_one_policy line=2374 msg="policy-0 is matched, act-drop"
id=65308 trace_id=385 func=__iprope_fwd_check line=847 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-0"
id=65308 trace_id=385 func=iprope_fwd_auth_check line=876 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-0"
id=65308 trace_id=385 func=fw_forward_handler line=839 msg="Denied by forward policy check (policy 0)"
For a more detailed explanation and examples of common Hairpin NAT topologies, refer to the following article:
Technical Tip: Configuring Hairpin NAT (VIP)
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.