Skip to main content
alif
Staff
Staff
February 10, 2026

Technical Tip: Bidirectional firewall policy for GRE passthrough traffic

  • February 10, 2026
  • 0 replies
  • 370 views
Description This article describes the behavior of GRE keepalive traffic that requires a firewall policy for both incoming and outgoing traffic.
Scope FortiGate.
Solution

Consider a GRE tunnel configured between two endpoints where FortiGate is acting as a transit (passthrough) device.

 

gre.png

config firewall policy
    edit 1

        set name "GRE Tunnel - Outbound"

        set srcintf "Trust"

        set dstintf "Untrust"
        set action accept
        set srcaddr "11.11.11.11/32"
        set dstaddr "22.22.22.22/32"
        set schedule "always"
        set service "GRE"
        set logtraffic all
    next
end

 

No. Time Source Destination Protocol Length Info
1 38.490594 11.11.11.11 22.22.22.22 GRE 70 Encapsulated Possible GRE keepalive packet
2 38.509918 11.11.11.11 22.22.22.22 GRE 46 Encapsulated Possible GRE keepalive packet

 

Entry 2 indicates GRE Keepalive Packet Response.

 

The debug flow indicates that traffic matches an existing session on FortiGate.

 

id=65308 trace_id=938 func=print_pkt_detail line=6005 msg="vd-External-FW:0 received a packet(proto=47, 11.11.11.11:0->22.22.22.22:0) tun_id=0.0.0.0 from wan1. "
id=65308 trace_id=938 func=resolve_ip_tuple_fast line=6107 msg="Find an existing session, id-04f6bc52, original direction"
id=65308 trace_id=938 func=ipv4_fast_cb line=53 msg="enter fast path"

 

id=65308 trace_id=940 func=print_pkt_detail line=6005 msg="vd-root:0 received a packet(proto=47, 22.22.22.22:0->11.11.11.11:0) tun_id=0.0.0.0 from wan2"
id=65308 trace_id=940 func=resolve_ip_tuple_fast line=6107 msg="Find an existing session, id-04f6bc52, reply direction"
id=65308 trace_id=940 func=ipv4_fast_cb line=53 msg="enter fast path"

 

The GRE keepalive response arrives on destination port 64763, which does not match the existing session.

 

id=65308 trace_id=948 func=print_pkt_detail line=6005 msg="vd-root:0 received a packet(proto=47, 22.22.22.22:3->11.11.11.11:64763) tun_id=0.0.0.0 from wan2. "
id=65308 trace_id=948 func=init_ip_session_common line=6206 msg="allocate a new session-04f6c06c"
id=65308 trace_id=948 func=iprope_dnat_check line=5487 msg="in-[wan2], out-[]"
id=65308 trace_id=948 func=iprope_dnat_tree_check line=824 msg="len=0"
id=65308 trace_id=948 func=iprope_dnat_check line=5512 msg="result: skb_flags-02000000, vid-0, ret-no-match, act-accept, flag-00000000"
id=65308 trace_id=948 func=__vf_ip_route_input_rcu line=1989 msg="find a route: flag=00000000 gw-0.0.0.0 via wan1"
id=65308 trace_id=948 func=__iprope_fwd_check line=809 msg="in-[wan2], out-[wan1], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"
id=65308 trace_id=948 func=__iprope_tree_check line=535 msg="gnum-100004, use addr/intf hash, len=31"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-403, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-2, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-24, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-25, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-402, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-361, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-20, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-8, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-10, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-13, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-30, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-242, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-62, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-250, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-426, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-347, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-104, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-108, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-156, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-172, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-183, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-202, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-214, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-244, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-276, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-315, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-396, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-491, ret-no-match, act-accept"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2146 msg="checked gnum-100004 policy-23, ret-matched, act-accept"
id=65308 trace_id=948 func=__iprope_user_identity_check line=1909 msg="ret-matched"
id=65308 trace_id=948 func=__iprope_check_one_policy line=2380 msg="policy-23 is matched, act-drop"
id=65308 trace_id=948 func=__iprope_fwd_check line=846 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-23"
id=65308 trace_id=948 func=iprope_fwd_auth_check line=875 msg="after iprope_captive_check(): is_captive-0, ret-matched, act-drop, idx-23"
id=65308 trace_id=948 func=fw_forward_handler line=839 msg="Denied by forward policy check (policy 0)"

 

The above behavior is expected because GRE session control is unidirectional. GRE keys are independently assigned and asymmetrical in nature.

 

Since multiple distinct tunnels can exist between the same source and destination IP addresses, independent keys can't be inherently correlated into a single 'Original/Reply' pair.

 

Hence, a firewall rule is required to allow traffic in incoming direction as follows:

 

config firewall policy
    edit 2
        set name "GRE Tunnel - Inbound"
        set srcintf "Untrust"
        set dstintf "Trust"
        set action accept
        set srcaddr "22.22.22.22/32"
        set dstaddr "11.11.11.11/32"
        set schedule "always"
        set service "GRE"
        set logtraffic all
    next
end

 

Related articles:

Technical Tip: GRE Tunnel monitoring

Technical Tip: Monitoring GRE tunnel with keepalive