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.
syadav
Staff
Staff
Article Id 262988
Description This article describes which service to allow in the inbound VIP firewall policy when virtual IP port forwarding is configured with a different external port than the internal port.
Scope FortiOS v5.6 and later.
Solution

This article assumes the following topology:

 

syadav_0-1688741986333.png

 

Create a VIP object as shown below:

 

config firewall vip

    edit "web"

        set extip 10.0.20.2

        set mappedip "10.1.1.2"

        set extintf "port1"

        set portforward enable

        set extport 8080

        set mappedport 80

    next

end

 

In the above configuration, 10.0.20.2 is the external WAN IP and 10.1.1.2 is the internal web server.

The incoming traffic is on port 8080, which is mapped internally to port 80.

 

For the inbound firewall policy, a common mistake is to allow the external port in the inbound firewall policy as shown below:

 

config firewall policy

    edit 2

        set name "inbound"

        set srcintf "port1"

        set dstintf "port2"

        set action accept

        set srcaddr "all"

        set dstaddr "web"

        set schedule "always"

        set service "web_8080"

    next

end
config firewall service custom

    edit "web_8080"

        set tcp-portrange 8080

    next

end

 

The flow trace logs show the traffic matches the implicit deny policy 0, not the above policy.

id=65308 trace_id=1 func=print_pkt_detail line=5842 msg="vd-root:0 received a packet(proto=6, 10.0.20.20:54644->10.0.20.2:8080) tun_id=0.0.0.0 from port1. flag [S], seq 2421238541, ack 0, win 64240"

id=65308 trace_id=1 func=init_ip_session_common line=6028 msg="allocate a new session-00000043, tun_id=0.0.0.0"

id=65308 trace_id=1 func=iprope_dnat_check line=5303 msg="in-[port1], out-[]"

id=65308 trace_id=1 func=iprope_dnat_tree_check line=824 msg="len=1"

id=65308 trace_id=1 func=__iprope_check_one_dnat_policy line=5168 msg="checking gnum-100000 policy-1"

id=65308 trace_id=1 func=get_new_addr line=1239 msg="find DNAT: IP-10.1.1.2, port-80"

id=65308 trace_id=1 func=__iprope_check_one_dnat_policy line=5258 msg="matched policy-1, act=accept, vip=1, flag=100, sflag=2000000"

id=65308 trace_id=1 func=iprope_dnat_check line=5315 msg="result: skb_flags-02000000, vid-1, ret-matched, act-accept, flag-00000100"

id=65308 trace_id=1 func=fw_pre_route_handler line=184 msg="VIP-10.1.1.2:80, outdev-port1"

id=65308 trace_id=1 func=__ip_session_run_tuple line=3435 msg="DNAT 10.0.20.2:8080->10.1.1.2:80"

id=65308 trace_id=1 func=__vf_ip_route_input_rcu line=2012 msg="find a route: flag=00000000 gw-0.0.0.0 via port2"

id=65308 trace_id=1 func=iprope_fwd_check line=794 msg="in-[port1], out-[port2], skb_flags-020000c0, vid-1, 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=28, len=2"

id=65308 trace_id=1 func=__iprope_check_one_policy line=2059 msg="checked gnum-100004 policy-2, ret-no-match, act-accept"

id=65308 trace_id=1 func=__iprope_check_one_policy line=2059 msg="checked gnum-100004 policy-0, ret-matched, act-accept"

id=65308 trace_id=1 func=__iprope_user_identity_check line=1833 msg="ret-matched"

id=65308 trace_id=1 func=__iprope_check_one_policy line=2277 msg="policy-0 is matched, act-drop"

id=65308 trace_id=1 func=iprope_fwd_check line=831 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-0"

id=65308 trace_id=1 func=iprope_fwd_auth_check line=850 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-0"

id=65308 trace_id=1 func=fw_forward_handler line=835 msg="Denied by forward policy check (policy 0)"

 

DNAT occurs before the firewall policy lookup, which leads to the traffic not matching the firewall policy.

As shown in the above debug logs, the DNAT converts the public IP and port to the internal IP and port.

This shows that the internal port (service), which is HTTP (port 80) in this case, needs to be allowed rather than the external port.

 

The following is the modified firewall policy with HTTP as the allowed service:

 

config firewall policy

    edit 2

        set name "inbound"

        set uuid 7e44221a-1506-51ee-ca6b-9064ea17fad2

        set srcintf "port1"

        set dstintf "port2"

        set action accept

        set srcaddr "all"

        set dstaddr "web"

        set schedule "always"

        set service "HTTP"

    next

end

 

id=65308 trace_id=16 func=print_pkt_detail line=5842 msg="vd-root:0 received a packet(proto=6, 10.0.20.20:54710->10.0.20.2:8080) tun_id=0.0.0.0 from port1. flag [S], seq 145684743, ack 0, win 64240"

id=65308 trace_id=16 func=init_ip_session_common line=6028 msg="allocate a new session-00000053, tun_id=0.0.0.0"

id=65308 trace_id=16 func=iprope_dnat_check line=5303 msg="in-[port1], out-[]"

id=65308 trace_id=16 func=iprope_dnat_tree_check line=824 msg="len=1"

id=65308 trace_id=16 func=__iprope_check_one_dnat_policy line=5168 msg="checking gnum-100000 policy-1"

id=65308 trace_id=16 func=get_new_addr line=1239 msg="find DNAT: IP-10.1.1.2, port-80"

id=65308 trace_id=16 func=__iprope_check_one_dnat_policy line=5258 msg="matched policy-1, act=accept, vip=1, flag=100, sflag=2000000"

id=65308 trace_id=16 func=iprope_dnat_check line=5315 msg="result: skb_flags-02000000, vid-1, ret-matched, act-accept, flag-00000100"

id=65308 trace_id=16 func=fw_pre_route_handler line=184 msg="VIP-10.1.1.2:80, outdev-port1"

id=65308 trace_id=16 func=__ip_session_run_tuple line=3435 msg="DNAT 10.0.20.2:8080->10.1.1.2:80"

id=65308 trace_id=16 func=__vf_ip_route_input_rcu line=2012 msg="find a route: flag=00000000 gw-0.0.0.0 via port2"

id=65308 trace_id=16 func=iprope_fwd_check line=794 msg="in-[port1], out-[port2], skb_flags-020000c0, vid-1, app_id: 0, url_cat_id: 0"

id=65308 trace_id=16 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=28, len=2"

id=65308 trace_id=16 func=__iprope_check_one_policy line=2059 msg="checked gnum-100004 policy-2, ret-matched, act-accept"

id=65308 trace_id=16 func=__iprope_user_identity_check line=1833 msg="ret-matched"

id=65308 trace_id=16 func=__iprope_check line=2307 msg="gnum-4e20, check-00000000b2769f66"

id=65308 trace_id=16 func=__iprope_check_one_policy line=2059 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"

id=65308 trace_id=16 func=__iprope_check_one_policy line=2059 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"

id=65308 trace_id=16 func=__iprope_check_one_policy line=2059 msg="checked gnum-4e20 policy-6, ret-no-match, act-accept"

id=65308 trace_id=16 func=__iprope_check line=2324 msg="gnum-4e20 check result: ret-no-match, act-accept, flag-00000000, flag2-00000000"

id=65308 trace_id=16 func=__iprope_check_one_policy line=2277 msg="policy-2 is matched, act-accept"

id=65308 trace_id=16 func=iprope_fwd_check line=831 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-2"

id=65308 trace_id=16 func=iprope_fwd_auth_check line=850 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-accept, idx-2"

id=65308 trace_id=16 func=fw_forward_handler line=1000 msg="Allowed by Policy-2:"

id=65308 trace_id=16 func=ip_session_confirm_final line=3087 msg="npu_state=0x100, hook=4"