VRF Export Maps
By stretch | Thursday, September 26, 2013 at 10:48 p.m. UTC
VRFs are an excellent tool for maintaining segregated routing topologies for separate customers or services. I've previously covered inter-VRF routing using route targets, but what if we only want to export a subset of the routes within a VRF? Here's a scenario in which this would be desirable.
Customers A and B each have a site network and a colocation network, and both customers need access to the 192.168.0.0/24 network in the Services VRF. The customers must utilize unique IP space in order to prevent overlapping networks, so each customer has been allocated dedicated IP space from their common provider out o 10.0.0.0/8. Unfortunately, customer A is still has some networks within the 172.16.0.0/16. These networks need to access services in the host colo, but the service provider can't allow this space to be advertised into the Services VRF as it's not approved IP space.
Our goal is to export only the networks within the 10.0.0.0/8 space from the customer VRFs to the Services VRF. How can we accomplish this?
Let's have a look at the initial network state. (This lab was performed using a single router for simplicity. In the real world, these customers would typically be connected via an MPLS VPN.) Each customer and colo network has its own VRF and dedicated route target (RT). The Services VRF has been configured with an import/export RT pair for scalability reasons. No export among VRFs has yet been configured.
ip vrf Customer_A rd 65000:1001 route-target export 65000:1001 route-target import 65000:1001 ! ip vrf Customer_A_Colo rd 65000:2001 route-target export 65000:2001 route-target import 65000:2001 ! ip vrf Customer_B rd 65000:1002 route-target export 65000:1002 route-target import 65000:1002 ! ip vrf Customer_B_Colo rd 65000:2002 route-target export 65000:2002 route-target import 65000:2002 ! ip vrf Services rd 65000:100 route-target export 65000:100 route-target import 65000:100 route-target import 65000:101 ! interface Loopback100 ip vrf forwarding Services ip address 192.168.0.1 255.255.255.0 ! interface Loopback1001 ip vrf forwarding Customer_A ip address 172.16.0.1 255.255.0.0 secondary ip address 10.1.1.1 255.255.255.0 ! interface Loopback1002 ip vrf forwarding Customer_B ip address 10.1.2.1 255.255.255.0 ! interface Loopback2001 ip vrf forwarding Customer_A_Colo ip address 10.2.1.1 255.255.255.0 ! interface Loopback2002 ip vrf forwarding Customer_B_Colo ip address 10.2.2.1 255.255.255.0 ! router bgp 65000 ! address-family ipv4 vrf Services redistribute connected exit-address-family ! address-family ipv4 vrf Customer_B_Colo redistribute connected exit-address-family ! address-family ipv4 vrf Customer_B redistribute connected exit-address-family ! address-family ipv4 vrf Customer_A_Colo redistribute connected exit-address-family ! address-family ipv4 vrf Customer_A redistribute connected exit-address-family
First, we want to enable route exchange between each customer VRF and its respective colo. This is easily accomplished by adding an additional import RT to each customer VRF:
ip vrf Customer_A route-target import 65000:2001 ! ip vrf Customer_A_Colo route-target import 65000:1001 ! ip vrf Customer_B route-target import 65000:2002 ! ip vrf Customer_B_Colo route-target import 65000:2001
The Customer_A VRF now has a route for the Customer_A_Colo networks, and vice versa. The same goes for Customer_B and its colo network. You could check the routing table for each VRF independently (show ip route vrf NAME
), or you can use the command show ip bgp vpnv4 all
to quickly dump the routes from all VRFs:
Router# show ip bgp vpnv4 all BGP table version is 18, local router ID is 1.1.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65000:100 (default for vrf Services) *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1001 (default for vrf Customer_A) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1002 (default for vrf Customer_B) *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2001 (default for vrf Customer_A_Colo) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2002 (default for vrf Customer_B_Colo) *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ?
Notice that the Customer_A and Customer_A_Colo VRFs both contain the same set of routes, as do the two VRFs for Customer B. (If the routes don't appear to be exchanged, ensure that MP-BGP is running and has a router ID configured.)
Next, we need to exchange routes among the four customer VRFs and the common services VRF. We do this by adding the import and export RT for the Services VRF.
ip vrf Customer_A route-target import 65000:100 route-target export 65000:101 ! ip vrf Customer_A_Colo route-target import 65000:100 route-target export 65000:101 ! ip vrf Customer_B route-target import 65000:100 route-target export 65000:101 ! ip vrf Customer_B_Colo route-target import 65000:100 route-target export 65000:101
We can see that the Services VRF now see all customer routes, and all customer VRFs have a route to the services network:
Router# show ip bgp vpnv4 all BGP table version is 38, local router ID is 1.1.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65000:100 (default for vrf Services) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1001 (default for vrf Customer_A) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1002 (default for vrf Customer_B) *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2001 (default for vrf Customer_A_Colo) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2002 (default for vrf Customer_B_Colo) *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ?
But now we have a problem: The legacy 172.16.0.0/16 prefix from Customer_A is polluting the Services VRF. We need to find a way to prevent it from being exported to the Services VRF while still permitting the valid 10.1.1.0/24 route. This is where export maps come in handy.
Export Maps
Let's take a closer look at the routes being exported from the Customer_A VRF:
Router# show ip bgp vpnv4 vrf Customer_A 10.1.1.0 BGP routing table entry for 65000:1001:10.1.1.0/24, version 25 Paths: (1 available, best #1, table Customer_A) Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:101 RT:65000:1001 mpls labels in/out 18/aggregate(Customer_A) Router# show ip bgp vpnv4 vrf Customer_A 172.16.0.0 BGP routing table entry for 65000:1001:172.16.0.0/16, version 42 Paths: (1 available, best #1, table Customer_A) Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:101 RT:65000:1001 mpls labels in/out 17/aggregate(Customer_A)
Recall that a route target is just a type of BGP community. Here we can see that the two route targets (communities) we configured using the route-target export
command under VRF configuration have been attached to both routes from this VRF, as expected. The 65000:101 RT is what's causing the Services VRF to import these routes. What we want to do is prevent the 65000:101 RT from being added to the 172.16.0.0/16 route while still including it on the 10.1.1.0/24 route.
We can define a route-map to overwrite the set of RTs attached to a route with whatever we want, and apply it to the Customer_A VRF as an export map. We'll use a prefix list to match any routes within 172.16.0.0/16.
ip prefix-list Customer_A_Legacy seq 5 permit 172.16.0.0/16 le 32 ! route-map Customer_A_Export permit 10 match ip address prefix-list Customer_A_Legacy set extcommunity rt 65000:1001
Note that the set extcommunity
command in this instance is not adding an RT (because we did not include the additive
keyword). Rather, we are overwriting the existing set of RTs with our own set (which happens to be only a single RT). Essentially, this line says, "Get rid of any existing RTs and add an RT for 65000:1001."
The route map is applied to the VRF using the export map
command:
ip vrf Customer_A export map Customer_A_Export
Let's take a look at those two routes again:
Router# show ip bgp vpnv4 vrf Customer_A 10.1.1.0 BGP routing table entry for 65000:1001:10.1.1.0/24, version 25 Paths: (1 available, best #1, table Customer_A) Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:101 RT:65000:1001 mpls labels in/out 18/aggregate(Customer_A) Router# show ip bgp vpnv4 vrf Customer_A 172.16.0.0 BGP routing table entry for 65000:1001:172.16.0.0/16, version 45 Paths: (1 available, best #1, table Customer_A) Flag: 0xA00 Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:1001 mpls labels in/out 17/aggregate(Customer_A)
Success! The route for 172.16.0.0/16 no longer has the 65000:101 RT attached to it, which means it should no longer be imported by the Services VRF. The Customer_A_Colo VRF will still import the route because of the 65000:1001 RT.
Router# show ip bgp vpnv4 all BGP table version is 47, local router ID is 1.1.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65000:100 (default for vrf Services) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1001 (default for vrf Customer_A) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1002 (default for vrf Customer_B) *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2001 (default for vrf Customer_A_Colo) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2002 (default for vrf Customer_B_Colo) *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ?
Great, that's exactly what we wanted!
By the way, did you notice that our route map is not permitting any other routes, yet the 10.1.1.0/24 network is still exported? This is contrary to how route maps typically work and an important caveat to remember. Think of it this way: Your export map matches exported routes which you want to modify, not the routes you want to export in the first place.
There's one last concern to address with our solution. The current configuration explicitly denies certain routes and allows all others. This is contrary to the preferred practice of allowing only routes which we explicitly permit and denying everything else. If customer A was to announce another unwanted network (e.g. 172.17.0.0/16), our export map wouldn't prevent it from being exported to the Services VRF.
We can fix this by inverting our VRF export logic: Instead of removing the 65000:101 RT from routes we don't want, we'll only add it to routes we do want. First, let's remove the route-target export 65000:101
from the Customer_A VRF. This will remove both Customer_A routes from the Services VRF.
ip vrf Customer_A no route-target export 65000:101 no export map Customer_A_Export
Next, we'll recreate our prefix list and route-map to reflect the new logic:
no route-map Customer_A_Export no ip prefix-list Customer_A_Legacy ! ip prefix-list Customer_A_Networks permit 10.1.1.0/24 ! route-map Customer_A_Export permit 10 match ip address prefix-list Customer_A_Networks set extcommunity rt 65000:101 additive ! ip vrf Customer_A export map Customer_A_Export
We still see the same BGP communities as with the previous configuration: Only the 10.1.1.0/24 network has the 65000:101 RT attached.
Router# show ip bgp vpnv4 vrf Customer_A 10.1.1.0 BGP routing table entry for 65000:1001:10.1.1.0/24, version 71 Paths: (1 available, best #1, table Customer_A) Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:101 RT:65000:1001 mpls labels in/out 18/aggregate(Customer_A) Router# show ip bgp vpnv4 vrf Customer_A 172.16.0.0 BGP routing table entry for 65000:1001:172.16.0.0/16, version 65 Paths: (1 available, best #1, table Customer_A) Not advertised to any peer Local 0.0.0.0 from 0.0.0.0 (1.1.1.1) Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best Extended Community: RT:65000:1001 mpls labels in/out 17/aggregate(Customer_A)
But now, if we add a second rogue network to the Customer_A VRF, it won't get exported to the Services VRF because it won't be matched by our prefix list.
Router# show ip bgp vpnv4 all BGP table version is 76, local router ID is 1.1.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65000:100 (default for vrf Services) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1001 (default for vrf Customer_A) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 172.17.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:1002 (default for vrf Customer_B) *> 10.1.2.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2001 (default for vrf Customer_A_Colo) *> 10.1.1.0/24 0.0.0.0 0 32768 ? *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 172.16.0.0 0.0.0.0 0 32768 ? *> 172.17.0.0 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ? Route Distinguisher: 65000:2002 (default for vrf Customer_B_Colo) *> 10.2.1.0/24 0.0.0.0 0 32768 ? *> 10.2.2.0/24 0.0.0.0 0 32768 ? *> 192.168.0.0 0.0.0.0 0 32768 ?
There's one important caveat to address before we wrap up. Although the Services VRF doesn't have a route to the 172.16.0.0/16 network at customer A, it's still possible for customer A to send traffic from this network into the Services VRF. Return traffic won't make it back, however this leaves the door open for denial of service attacks (for example, spoofing traffic so that it appears to come from customer B, and flooding that customer with responses). Additional controls such as unicast RPF or even plain old access lists are needed at the customer edge to block invalid traffic.
Posted in Routing
Comments
September 26, 2013 at 10:51 p.m. UTC
One of the best primers I have read on this topic, by far. Thank you.
September 27, 2013 at 7:45 a.m. UTC
I follow your blog since some time now and I have to say I really like how clear and concise the explanations are. I rarely see that in a tech blog. Great job!
September 27, 2013 at 2:21 p.m. UTC
This is a really great and especially clear explanation!
September 27, 2013 at 6:21 p.m. UTC
Jeremy,
I assume there is a typo in the diagram for Customer_B. Should it be 10.1.2.0/24?
September 30, 2013 at 7:14 p.m. UTC
Great job!!
October 3, 2013 at 12:55 p.m. UTC
Great addition to an excellent set of VRF blogs!
October 18, 2013 at 4:37 p.m. UTC
ip vrf Customer_B_Colo
route-target import 65000:2001
Should this not be importing 65000:1002 for Customer B 10.2.1.0/24 network ?
If configured as per the example Customer B colo will be importing Customer_A colo routes.
October 29, 2013 at 7:10 p.m. UTC
networkdude1 (guest)
Of course you are right there is a typo
B Colo shall import 65000:1002
November 26, 2013 at 7:04 a.m. UTC
Excellent writing. Thanks a LOT.
What is the reason for importing the routes of a VRF into the same originating VRF? This looks like a re-import. I know of running installations of such VRF export/import scenarios that do not have it.
ip vrf Customer_A rd 65000:1001 route-target export 65000:1001 route-target import 65000:1001 ⇦ ??
November 29, 2013 at 2:49 a.m. UTC
@JPI,
Importing the route-target will grab those MPBGP vpnv4 routes that were exported to that same route-target from other routers. This is necessary if you have the same VRF on multiple routers and they are sharing routes via MPBGP.
Stretch explains this well in his previous blog post here: http://packetlife.net/blog/2013/jun/10/route-distinguishers-and-route-targets/
February 28, 2014 at 2:26 a.m. UTC
It's very clear and helpful for me!
Thank you very much, Jeremy!
July 4, 2014 at 4:00 p.m. UTC
Can you please write an article of importing and exporting routes using mpls vpn..so let say PE-A is connected to PE-B and PE-C and PE-A is sending vrf B route to PE-B and vrf C routes to PE-C, I nee to leak routes between B and C over the mpls hub. How can I do that?
February 8, 2015 at 12:31 p.m. UTC
it is very helpful to understand export map and additive comand
March 31, 2015 at 8:13 p.m. UTC
Hey, Jeremy, just want to say thanks for all you do with your blog. Seems like every time I need to check some Cisco arcana, Google points me here. (Maybe because I live in Raleigh?) This time I needed to refresh the noggin on whether export map overwrites route-target export commands. Sure enough, Google's first link gives me the answer straight from your blog!
April 23, 2015 at 1:37 p.m. UTC
can you give a blog about ospf DN bit for its suitable network architecture? Thank you a lot!
June 24, 2015 at 7:13 a.m. UTC
Very best topic, very clear and helpful for me! Thank you very much, Jeremy!
December 3, 2015 at 2:04 p.m. UTC
Very Clear. Thanks