Juniper SRX Filter-based Forwarding (FBF) Policy Based Routing

Sep 15, 2022

If you're a Cisco Guy (or Girl, I'm not biased; both sexes are welcome to the Cisco Pain Train), you'll likely have come across a need for Policy Based Routing (PBR) to change the normal Destination IP-based logic of Network Routing to instead be a Source-IP or Interface-based logic, for some purpose of bypass. On Cisco gear, this is normally achieved via Route Maps or Route Policy Language (RPL) matching Access Control Lists (ACLs), Prefix Lists, Interfaces or some other attribute to match the desired traffic flows to "PBR" away from normal Routing.

Junos - or specifically Filter-based Forwarding (FBF) - takes a very different approach to achieving this, which may take your "Cisco brain" a bit of context-switching to adapt to, namely:

Worked example

A worked example probably helps here, so suppose we have the following:

Topology

A picture paints a thousand words, so that summates as:

Juniper PBR Filter-based Forwarding Topology

Configuration

Let's look at the raw config first, and then deconstruct it down to what this is doing. For brevity I've omitted the GRE Tunnel configuration, but if you're interested I suggest you read about Juniper SRX Overlay and Underlay VRF-seperated GRE Tunnels.

Ditto, in practice you'd want to Source NAT (SNAT) the traffic to a Public IPv4 to make it routable on the Internet, but again, for brevity I'm omitting that and focusing only on the PBR-required configuration itself - as you might want to adopt similar for Private-to-Private PBR requirements.

set routing-instances Internet-Bypass-ZIA instance-type forwarding
set routing-instances Internet-Bypass-ZIA routing-options static route 0.0.0.0/0 next-hop 203.0.113.1
set routing-instances Internet-Bypass-ZIA routing-options instance-import POL_EXPORT_FROM_Prod-VRF_TO_Internet-Bypass-ZIA
set routing-instances Internet-Bypass-ZIA routing-options instance-import POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA
!
set firewall family inet filter PBR-BYPASS-ZSCALER-ZIA term PBR-DIRECT-INTERNET from source-address 10.2.0.0/24
set firewall family inet filter PBR-BYPASS-ZSCALER-ZIA term PBR-DIRECT-INTERNET from destination-address 0.0.0.0/0
set firewall family inet filter PBR-BYPASS-ZSCALER-ZIA term PBR-DIRECT-INTERNET from destination-port https
set firewall family inet filter PBR-BYPASS-ZSCALER-ZIA term PBR-DIRECT-INTERNET then routing-instance Internet-Bypass-ZIA
set firewall family inet filter PBR-BYPASS-ZSCALER-ZIA term term-999 then accept
!
set policy-options prefix-list PFX_FROM_Prod_TO_Internet-Bypass-ZIA 10.99.99.0/30
set policy-options prefix-list PFX_FROM_Prod_TO_Internet-Bypass-ZIA 10.0.0.0/8
set policy-options policy-statement POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA term 10 from instance Prod
set policy-options policy-statement POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA term 10 from prefix-list PFX_FROM_Prod_TO_Internet-Bypass-ZIA
set policy-options policy-statement POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA term 10 then accept
set policy-options policy-statement POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA term 999 from instance Prod
set policy-options policy-statement POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA term 999 then reject
!
set policy-options prefix-list PFX_FROM_Internet_TO_Internet-Bypass-ZIA 203.0.113.0/30
set policy-options policy-statement POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA term 10 from instance Internet
set policy-options policy-statement POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA term 10 from prefix-list PFX_FROM_Internet_TO_Internet-Bypass-ZIA
set policy-options policy-statement POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA term 10 then accept
set policy-options policy-statement POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA term 999 from instance Internet
set policy-options policy-statement POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA term 999 then reject
!
set interfaces xe-0/0/1 unit 10 family inet filter input PBR-BYPASS-ZSCALER-ZIA

Break it down now y'all

That's quite a chunk to digest, so let's break it into chunks of what it achieves, using each exclamation mark (!) as a section divider:

  1. Create a new VRF Internet-Bypass-ZIA for the PBR to occur within; map the Internet-facing WAN and Prod-facing LAN Interfaces and next-hop Prefixes into it, and set a Static Default Route out of it via the Internet-facing WAN interface
  2. Define a FBF/PBR policy called PBR-BYPASS-ZSCALER-ZIA which has one term/policy statement called PBR-DIRECT-INTERNET that matches HTTPS requests from only the "Direct Internet access" Subnet 10.2.0.0/24, and bypasses (does not PBR) any other flows (i.e. leaves them as-was to flow via Zscaler Internet as if the PBR configuration didn't exist)
  3. Create a Routing Policy POL_EXPORT_FROM_Prod_TO_Internet-Bypass-ZIA to inter-VRF the LAN-facing 10.99.99.0/30 Handoff/Linknet and associated next-hop 10.0.0.0/8 Route from the Prod VRF into the PBR Internet-Bypass-ZIA VRF
  4. Create a Routing Policy POL_EXPORT_FROM_Internet_TO_Internet-Bypass-ZIA to inter-VRF the WAN-facing 203.0.113.0/30 Handoff/Linknet from the Internet VRF into the PBR Internet-Bypass-ZIA VRF
  5. Tie it all together by applying the FBF/PBR policy PBR-BYPASS-ZSCALER-ZIA to ingress LAN-facing interface xe-0/0/1.10
    1. Note if we changed the FBF/PBR policy PBR-BYPASS-ZSCALER-ZIA term-999 line from "...then accept" to "...then reject" - or just did not have that line - then any non-PBR'd traffic would not just not be PBR'd, it'd be dropped entirely - so be very careful that the PBR/FBF policy is 100% correct before you apply it to the ingress interface

One hop this time

Hopefully this has been a useful jaunt through the differences Junos SRX uses to perform what we Cisco folk would know as PBR, and shows how it works in practice, effectively using a "third" VRF - in our example - which acts as a PBR Container to glue it all together. In practice this is nice as it keeps it obvious which flows/Source IPs/Destination IPs are being PBR'd and which aren't, however it can be confusing to wrap your head around. I also found a few gotchas if you forget/mismatch the Linknets to "import" the WAN/LAN interfaces into what is effectively a "foreign VRF" from their respective "Prod" or "Internet" native VRFs.