VRF Selection Using Filter Based Forwarding – Junos

I wanted to replicate the VRF using PBR post I did over here. Anyne who has used Junos will tell you that their version of PBR, while more powerful, is a lot more complicated that Cisco’s offering.

Let’s use the following topology:

R3 is going to be my source. It will have multiple interfaces configured. When I send traffic off to R2, I would like R2 to decide which VRF the packet should go into based on the source address used by R3. R2 and R4 are going to be simple ISP PE devices. R1 and R5 are going to be in VRF’s CUS1 and CUS5 respectively.

Configuration

CPE config

All the CPE routers have their loopback configured and have a static route pointing to their connected PE.
All the CPEs are configured simiraily. I’m only going to show the configuration of one.

USER3:R3> show configuration interfaces
ae1 {
    unit 12 {
        vlan-id 12;
        family inet {
            address 10.0.4.5/30;
        }
    }
}
lo0 {
    unit 3 {
        family inet {
            address 3.3.3.3/32;
        }
    }
}

USER3:R3> show configuration routing-options
static {
    route 0.0.0.0/0 next-hop 10.0.4.6;
}

PE Config

R4 is a regular PE so nothing special:

USER4:R4> show configuration
interfaces {
    fe-0/0/3 {
        unit 24 {
            vlan-id 24;
            family inet {
                address 10.0.4.9/30;
            }
            family mpls;
        }
    }
    ae1 {
        unit 34 {
            vlan-id 34;
            family inet {
                address 10.0.2.5/30;
            }
        }
        unit 45 {
            vlan-id 45;
            family inet {
                address 10.0.8.9/30;
            }
        }
    }
    lo0 {
        unit 4 {
            family inet {
                address 4.4.4.4/32;
            }
        }
    }
}
protocols {
    mpls {
        interface fe-0/0/3.24;
    }
    bgp {
        group L3VPN {
            local-address 4.4.4.4;
            family inet-vpn {
                unicast;
            }
            peer-as 100;
            neighbor 2.2.2.2;
        }
    }
    ospf {
        area 0.0.0.0 {
            interface fe-0/0/3.24;
            interface lo0.4;
        }
    }
    ldp {
        interface fe-0/0/3.24;
    }
}
routing-instances {
    CUS1 {
        instance-type vrf;
        interface ae1.34;
        route-distinguisher 100:1;
        vrf-target target:100:1;
        routing-options {
            static {
                route 1.1.1.1/32 next-hop 10.0.2.6;
            }
        }
    }
    CUS5 {
        instance-type vrf;
        interface ae1.45;
        route-distinguisher 100:5;
        vrf-target target:100:5;
        routing-options {
            static {
                route 5.5.5.5/32 next-hop 10.0.8.10;
            }
        }
    }
}
routing-options {
    autonomous-system 100;
}

As you can see, R4 has a static route to R1 and R5 in each respective VRF. That information is then sent off to R2 as an MP-BGP update.

R2 is where all the magic happens. I need to ensure that packets coming into interface fe-0/0/3.12 via R3 is put into various VRFs based on the source address. I also need to ensure that R2 is able to get back to either these addresses over the VRF, even though interface fe-0/0/3.12 is not in a VRF.

First, let’s create a firewall filter that will match and move packets to the right VRF:

USER2:R2> show configuration firewall
family inet {
    filter VRF_FBF {
        term CUS1 {
            from {
                address {
                    192.168.1.1/32;
                }
            }
            then {
                routing-instance CUS1;
            }
        }
        term CUS5 {
            from {
                address {
                    192.168.5.5/32;
                }
            }
            then {
                routing-instance CUS5;
            }
        }
        term ANY {
            then accept;
        }
    }
}

If a packet comes in with a source address of 192.168.1.1/32, send that off to the CUS1 vrf. If it comes in with a source address of 192.168.5.5/32, send that off to the CUS2 vrf. I’ve then got a catch-all to ensure any other packets are not dropped. Once that filter is created. I need to apply it inbound in my interface:

USER2:R2> show configuration interfaces fe-0/0/3.12
vlan-id 12;
family inet {
    filter {
        input VRF_FBF;
    }
    address 10.0.4.6/30;
}

This is great for packets coming into R2 from R3, but what about getting back? I could create static routes in each VRF, but the actual link between R2 and R3 is not in any VRF. i.e. the next-hops will not be able to be resolved. I could have a static route pointing to the default/global vrf, but I could also use a rib-group to get that interface into both vrfs.

Let’s try the second option. I wanted to get 10.0.4.4/30 into both VRFs. I also want to ensure only this link gets into the vrf and not all the others.

USER2:R2> show configuration policy-options
policy-statement R2-R3-LINK {
    term 1 {
        from {
            route-filter 10.0.4.4/30 exact;
        }
        then accept;
    }
    term 2 {
        then reject;
    }
}

USER2:R2> show configuration routing-options rib-groups
GLOBAL_TO_VRF {
    import-rib [ inet.0 CUS1.inet.0 CUS5.inet.0 ];
    import-policy R2-R3-LINK;
}

USER2:R2> show configuration routing-options interface-routes
rib-group inet GLOBAL_TO_VRF;

The above says to match 10.0.4.4/30 and nothing else. That is applied to interface-routes which calls a rib-group. That rib-group states that when the interface route is placed in the default/global RIB, place it in CUS1 and CUS5’s RIB at the same time.

Verification

The end result of this is from from R2’s perspective, in the CUS1 RIB I should see R1’s address, R3’s 192.168.1.1/32 address, the R2-R3 link, and the R4-R1 link:

USER2:R2> show route table CUS1

CUS1.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[BGP/170] 01:17:21, localpref 100, from 4.4.4.4
                      AS path: I
                    > to 10.0.4.9 via ae1.24, Push 299792
10.0.2.4/30        *[BGP/170] 01:17:21, localpref 100, from 4.4.4.4
                      AS path: I
                    > to 10.0.4.9 via ae1.24, Push 299792
10.0.4.4/30        *[Direct/0] 00:56:02
                    > via fe-0/0/3.12
192.168.1.1/32     *[Static/5] 00:56:02
                    > to 10.0.4.5 via fe-0/0/3.12

If we check CUS5’s RIB, I should see R5’s address, R3’s 192.168.5.5/32 address, the R2-R3 link again, and the R4-R5 link:

USER2:R2> show route table CUS5

CUS5.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

5.5.5.5/32         *[BGP/170] 01:23:36, localpref 100, from 4.4.4.4
                      AS path: I
                    > to 10.0.4.9 via ae1.24, Push 299808
10.0.4.4/30        *[Direct/0] 00:58:51
                    > via fe-0/0/3.12
10.0.8.8/30        *[BGP/170] 01:23:36, localpref 100, from 4.4.4.4
                      AS path: I
                    > to 10.0.4.9 via ae1.24, Push 299808
192.168.5.5/32     *[Static/5] 00:58:51
                    > to 10.0.4.5 via fe-0/0/3.12

So our control plane is working perfectly fine. Let’s check our data plane for the final verification:

USER3:R3> ping 1.1.1.1 source 192.168.1.1 rapid
PING 1.1.1.1 (1.1.1.1): 56 data bytes
!!!!!
--- 1.1.1.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1.252/1.466/1.823/0.211 ms

USER3:R3> ping 1.1.1.1 source 192.168.5.5 rapid
PING 1.1.1.1 (1.1.1.1): 56 data bytes
.....
--- 1.1.1.1 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

R3 to R1 is working as expected. Let’s check R3 to R5:

USER3:R3> ping 5.5.5.5 source 192.168.5.5 rapid
PING 5.5.5.5 (5.5.5.5): 56 data bytes
!!!!!
--- 5.5.5.5 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1.262/1.358/1.577/0.115 ms

USER3:R3> ping 5.5.5.5 source 192.168.1.1 rapid
PING 5.5.5.5 (5.5.5.5): 56 data bytes
.....
--- 5.5.5.5 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

No problems there.

© 2009-2019 Darren O'Connor All Rights Reserved -- Copyright notice by Blog Copyright