Skip to main content

Inpection of asymmetric sessions on FortiGate

There is one feature available on FortiGate, and I think you should know it, as it modifies a bit what we know about stateful firewalls. In past every packet was treated individually and you had to create policies in both directions. With stateful firewalls we can track connections, and by checking couple of attributes, we can treat them as part of the same session. For example when you initiate connection from a host1 to host2, the returning connection from host2 to host1 will be treated as part of the same connection (session). They have to have the same source/destination and destination/source IPs, port numbers and interfaces.There is an exception from this rule and FortiGate in some specific cases can accept connections on port which was not used in the initial connection. Let me explain how it works on the below example:

    



The host1 has a default gateway on R1 (10.0.1.2), but you may notice that it is not the optimal path to host2 subnet. When we analyze the packet flow from host2 the path is different:

a) host1 -> R1 -> FG2 -> host2

b) host2 -> FG2 -> host1

So the path is asymmetric. How FortiGate deals with such problems?

Let's start from the case where host2 initiates the SSH connection to the host1. From the FortiGate the optimal path is port3->port1 as 10.0.1.0/24 subnet is directly connected. But what with a reply packet from the host1 which will be sent to R1? FortiGate can deal with such scenario and as long as firewall policy accepts it, both connections will be treated as one session:



  
 
FG2 # id=20085 trace_id=437 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.3.100:42862->10.0.1.100:22) from port3. flag [S], seq 2695315579, ack 0, win 29200"
id=20085 trace_id=437 func=init_ip_session_common line=5493 msg="allocate a new session-0001e45d"
...
id=20085 trace_id=437 func=vf_ip_route_input_common line=2590 msg="find a route: flag=04000000 gw-10.0.1.100 via port1"
id=20085 trace_id=437 func=iprope_fwd_check line=710 msg="in-[port3], out-[port1], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"
...
id=20085 trace_id=437 func=fw_forward_handler line=749 msg="Allowed by Policy-1:"
id=20085 trace_id=438 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.1.100:22->10.0.3.100:42862) from port2. flag [S.], seq 85123908, ack 2695315580, win 28960"
id=20085 trace_id=438 func=resolve_ip_tuple_fast line=5408 msg="Find an existing session, id-0001e45d, reply direction"
id=20085 trace_id=438 func=vf_ip_route_input_common line=2590 msg="find a route: flag=00000000 gw-10.0.3.100 via port3"
id=20085 trace_id=439 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.3.100:42862->10.0.1.100:22) from port3. flag [.], seq 2695315580, ack 85123909, win 229"
id=20085 trace_id=439 func=resolve_ip_tuple_fast line=5408 msg="Find an existing session, id-0001e45d, original direction"
id=20085 trace_id=439 func=vf_ip_route_input_common line=2590 msg="find a route: flag=04000000 gw-10.0.1.100 via port1"
id=20085 trace_id=439 func=iprope_fwd_check line=710 msg="in-[port3], out-[port1], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"


As you can see connections from port3->port1 and port2->port3 are part of the same session.

Now let's analyze the case where host1 initiates the SSH connection to host2:





id=20085 trace_id=669 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.1.100:42692->10.0.3.100:22) from port2. flag [S], seq 276815006, ack 0, win 29200"
id=20085 trace_id=669 func=init_ip_session_common line=5493 msg="allocate a new session-00066c8e"
id=20085 trace_id=669 func=iprope_dnat_check line=4921 msg="in-[port2], out-[]"
id=20085 trace_id=669 func=iprope_dnat_check line=4934 msg="result: skb_flags-02000000, vid-0, ret-no-match, act-accept, flag-00000000"
id=20085 trace_id=669 func=vf_ip_route_input_common line=2590 msg="find a route: flag=00000000 gw-10.0.3.100 via port3"
id=20085 trace_id=669 func=iprope_fwd_check line=710 msg="in-[port2], out-[port3], skb_flags-02000000, vid-0, app_id: 0, url_cat_id: 0"
id=20085 trace_id=669 func=fw_forward_handler line=749 msg="Allowed by Policy-1:"
id=20085 trace_id=670 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.3.100:22->10.0.1.100:42692) from port3. flag [S.], seq 1107817798, ack 276815007, win 28960"
id=20085 trace_id=670 func=resolve_ip_tuple_fast line=5408 msg="Find an existing session, id-00066c8e, reply direction"
id=20085 trace_id=670 func=vf_ip_route_input_common line=2590 msg="find a route: flag=04000000 gw-10.0.2.2 via port2"
id=20085 trace_id=671 func=print_pkt_detail line=5333 msg="vd-root:0 received a packet(proto=6, 10.0.1.100:42692->10.0.3.100:22) from port2. flag [.], seq 276815007, ack 1107817799, win 229"
id=20085 trace_id=671 func=resolve_ip_tuple_fast line=5408 msg="Find an existing session, id-00066c8e, original direction"



FG2 # get router info routing-table all

Routing table for VRF=0
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
       O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2
       i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
       * - candidate default

S*      0.0.0.0/0 [10/0] via 10.0.2.2, port2
C       10.0.1.0/24 is directly connected, port1
C       10.0.2.0/24 is directly connected, port2
C       10.0.3.0/24 is directly connected, port3


FG2 #



As you can see as long as you have an active route to 10.0.1.2 via port2 (it can be a default gateway) the reply packet goes via non-optimal path.

Comments

  1. Hi and thanks for the article. I'm surprised that in case#1 the Fortigate considers the packet coming back from port2 to be part of the same session "0001e45d". I thought it would just block the packet as the interface is not the same is identified in the session establishment.

    ReplyDelete

Post a Comment

Popular posts from this blog

What should you know about HA 'override enabled' setting on Fortigate?

High availability is mandatory in most of today's network designs. Only very small companies or branches can run their business without redundancy. When you have Fortigate firewall in your network you have many options to increase network availability. You can use Fortigate Clustering Protocol ( FGCP ) or Virtual Router Redundancy Protocol ( VRRP ). FGCP has two modes: 'override' disabled (default) and 'override' enabled . I'm not going to explain how to set up HA as you can find many resources on Fortinet websites: https://cookbook.fortinet.com/high-availability-two-fortigates-56/ https://cookbook.fortinet.com/high-availability-with-fgcp-56/ Let's recap what is the main difference between them. The default HA setting is 'override' disabled and this is an order of selection an active unit: 1) number of monitored interfaces - when both units have the same number of working (up) interfaces check next parameter 2) HA uptime - an

FortiGate and GRE tunnel

Recently I worked on one project where a client requested to re-route web traffic to the GRE tunnel to perform traffic inspection. I would like to share with you what is required if you configure it on FortiGate. We need a new GRE interface and policy base routing (PBR) to change the route for specific source IPs. Of course you need firewall policies to permit the traffic. Let's start with GRE interface. Unfortunately you can't configure it using the GUI, only CLI is the option: config system gre-tunnel edit "gre1" set interface "port1" set local-gw 55.55.55.55 set remote-gw 44.44.44.44 next end When the end peer is Cisco router, you need to set the IP for the GRE interface: config system interface edit gre1 set ip 192.168.10.10 255.255.255.255 set remote-ip192.168.10.20 end In next step we need to fix routing. We need the alternate path via GRE but to keep the route in the active routing table you need to set the same AD (adminis