Description


This article describes the issue of Filter Based Forwarding (FBF) not working as expected on low-end SRX devices, if the outgoing interfaces are not in same VR and zone.

Symptoms


FBF route packets, as per the firewall filter, are frequently used in a dual ISP scenario. However, the real traffic flow may not follow the FBF rule, if the outgoing interfaces are not in same VR and zone.

Topology :

alt
FBF is used to make the client access the 50.50.50.50 telnet server via ISP1. The telnet server's default gateway is ISP2. This means that traffic from the client to the telnet server is ge-0/0/0 , ge-0/0/1 , and ISP1. The return traffic is from ISP2 , fe-0/0/4 , and ge-0/0/0 .


FBF configuration :

Root@SRX210# show

  
interfaces {
ge-0/0/0 {
unit 0 {
family inet {
filter {
input fbf;
}
address 192.168.0.254/24;
}
}
}
ge-0/0/1 {
unit 0 {
family inet {
address 172.27.103.42/24;
}
}
}
fe-0/0/4 {
unit 0 {
family inet {
address 173.27.103.42/24;
}
}
}
}
...
routing-options {
interface-routes {
rib-group inet rib1;
}
rib-groups {
rib1 {
import-rib [ inet.0 lab.inet.0 desktop.inet.0 ];
}
}
}

policies {
from-zone trust to-zone lab {
policy p1 {
match {
source-address any;
destination-address any;
application any;
}
then {
permit;
}
}
}
from-zone lab to-zone trust {
policy p1 {
match {
source-address any;
destination-address 192.168.0.1;
application tcp3389;
}
then {
permit;
}
}
}
from-zone desktop to-zone trust {
policy p2 {
match {
source-address any;
destination-address any;
application any;
}
then {
permit;
}
...
firewall {
filter fbf {
term 1 {
from {
source-address {
192.168.0.1/32;
}
}
then {
count lab;
routing-instance lab;
}
}
term 2 {
from {
source-address {
0.0.0.0/0;
}
}
then {
count desktop;
routing-instance desktop;
}
}
}
}
routing-instances {
lab {
instance-type virtual-router;
interface ge-0/0/1.0;
routing-options {
static {
route 0.0.0.0/0 next-hop 172.27.103.1;
}
}
}
desktop {
instance-type virtual-router;
interface fe-0/0/4.0;
routing-options {
static {
route 0.0.0.0/0 next-hop 173.27.103.1;
}
...
security {
flow {
tcp-session {
no-syn-check;
}
}
}

Here are the flow sessions:

root@srx210# run show security flow session destination-port 23
Session ID: 12732, Policy name: p1/6, Timeout: 4, Valid
In: 192.168.0.1/61733 --> 50.50.50.50/23;tcp, If: ge-0/0/0.0, Pkts: 1, Bytes: 52
Out: 50.50.50.50/23 --> 192.168.0.1/61733;tcp, If: ge-0/0/1.0, Pkts: 0, Bytes: 0
Total sessions: 1

root@srx210# run show security flow session source-port 23
Session ID: 12379, Policy name: p1/9, Timeout: 1790, Valid
In: 50.50.50.50/23 --> 192.168.0.1/61733;tcp, If: fe-0/0/4.0, Pkts: 4, Bytes: 236
Out: 192.168.0.1/61733 --> 50.50.50.50/23;tcp, If: ge-0/0/0.0, Pkts: 4, Bytes: 190
Total sessions: 1
There are two sessions for this traffic; the first session is created by the Client TCP sync and the second session is created by the return TCP sync ack from the telnet server. There is only one sync packet, which matches the first session, and all the other packets match the second session. This is not what is expected, as per the FBF rule.



Solution

Why are two sessions present? Why does the subsequent traffic match the second session?

The root cause is that the outgoing interfaces are not in the same VR and Zone. 

When packets are matched on 6-tuple (proto, saddr, daddr, sport, dport, and sess_token), the packets will then be matched to the session. In the above topology, the TCP sync ack packet from the telnet server will not match the first session, as the sess_token does not match.

The TCP sync ack will follow the first packet's flow path. There is already a policy, which permits traffic from the desktop zone to the trust zone, and tcp-syn-check is disabled. The TCP sync ack packet will create a new session, as shown below:
Root@srx210#run show log flow

May 23 07:05:23 07:05:22.977374:CID-0:RT:<50.50.50.50/23->192.168.0.1/61733;6> matched filter b:

May 23 07:05:23 07:05:22.977374:CID-0:RT:packet [52] ipid = 1073, @421fcf9e

May 23 07:05:23 07:05:22.977374:CID-0:RT:---- flow_process_pkt: (thd 1): flow_ctxt type 13, common flag 0x0, mbuf 0x421fcd80, rtbl_idx = 5

May 23 07:05:23 07:05:22.977374:CID-0:RT: flow process pak fast ifl 69 in_ifp fe-0/0/4.0                                      <<<<<<<<< return traffic's ingress interface

May 23 07:05:23 07:05:22.977374:CID-0:RT: fe-0/0/4.0:50.50.50.50/23->192.168.0.1/61733, tcp, flag 12 syn ack                  <<<<<<<<< tcp sync ack

May 23 07:05:23 07:05:22.977374:CID-0:RT: find flow: table 0x52301870, hash 14992(0xffff), sa 50.50.50.50, da 192.168.0.1, sp 23, dp 61733, proto 6, tok 20486

May 23 07:05:23 07:05:22.977374:CID-0:RT: no session found, start first path. in_tunnel - 0, from_cp_flag - 0                 <<<<<<<<< no session matched because the session token is different

May 23 07:05:23 07:05:22.977374:CID-0:RT: flow_first_create_session                                                           <<<<<<<<< new session created

May 23 07:05:23 07:05:22.977374:CID-0:RT: flow_first_in_dst_nat: in <fe-0/0/4.0> , out <N/A> dst_adr 192.168.0.1, sp 23, dp 61733

May 23 07:05:23 07:05:22.977374:CID-0:RT: chose interface fe-0/0/4.0 as incoming nat if.

May 23 07:05:23 07:05:22.977374:CID-0:RT:flow_first_rule_dst_xlate: DST no-xlate: 0.0.0.0(0) to 192.168.0.1(61733)

May 23 07:05:23 07:05:22.977374:CID-0:RT:flow_first_routing: vr_id 5, call flow_route_lookup(): src_ip 50.50.50.50, x_dst_ip 192.168.0.1, in ifp fe-0/0/4.0, out ifp N/A sp 23, dp 61733, ip_proto 6, tos 0

May 23 07:05:23 07:05:22.977374:CID-0:RT:Doing DESTINATION addr route-lookup

May 23 07:05:23 07:05:22.977374:CID-0:RT: routed (x_dst_ip 192.168.0.1) from desktop (fe-0/0/4.0 in 0) to ge-0/0/0.0, Next-hop: 192.168.0.1

May 23 07:05:23 07:05:22.977374:CID-0:RT: policy search from zone desktop-> zone trust (0x0,0x17f125,0xf125)

May 23 07:05:23 07:05:22.977374:CID-0:RT: app 0, timeout 1800s, curr ageout 20s

May 23 07:05:23 07:05:22.977374:CID-0:RT:flow_first_src_xlate: nat_src_xlated: False, nat_src_xlate_failed: False

May 23 07:05:23 07:05:22.977374:CID-0:RT:flow_first_src_xlate: src nat returns status: 0, rule/pool id: 0/0, pst_nat: False.

May 23 07:05:23 07:05:22.977374:CID-0:RT: dip id = 0/0, 50.50.50.50/23->50.50.50.50/23 protocol 0

May 23 07:05:23 07:05:22.977374:CID-0:RT: choose interface ge-0/0/0.0 as outgoing phy if

May 23 07:05:23 07:05:22.977374:CID-0:RT:is_loop_pak: No loop: on ifp: ge-0/0/0.0, addr: 192.168.0.1, rtt_idx:0
........

Why does the traffic always match the second session, even when there is FBF?
  • FBF impacts only the route-lookup and identifies the egress interface; it will not impact the session match.
  • The two sessions have the same wings from 192.168.0.1 to 50.50.50.50 , as they have the same ingress interface - ge-0/0/0.0 . SRX will match the latest wing in the session; so it matches the second session.
  • As a result, the first TCP sync packet will follow the FBF rule and all the other packets will follow the second session's packet path, which is not expected.

The workaround is to make the outgoing interfaces part of the same VR and Zone, so that the return traffic will match the session, as they will have the same session token. The result  will be only one session for the traffic.