This article describes 3 different techniques to filter inbound BGP routes.
Let's consider a scenario where we have 2 different companies. The first company has its own DC running OSPF internally with everything in area 0, its own ASN and BGP peering to ISP A. The second company has another DC, which is also running OSPF internally in area 0, with a different ASN and BGP peering to ISP A.
Fig.1 Topology
The first company acquires the second one, and we face the challenge to connect the 2 DC environments to each other. As part of the design, we decide to establish direct fiber between the companies. Once this is in place, we would like to have all traffic between the DC's to use this link, instead of going through ISP A. However we notice that the routes from the 80.80.0.0/16 address space learned through BGP and redistributed into OSPF take precedence over the OSPF learned routes.
In order to resolve this issue, we need to have some mechanisms in place that prevents routes announced from DC1 to ISP A via eBGP to be learned via BGP and injected back into OSPF in the DC2 and vice versa. You can find the lab file at the end of this post.
Method 1: The traditional way of doing it
The first option is probably also the most obvious. We filter the inbound BGP routes with a prefix-list and a route-map. Let's check how routing towards the public IPv4 subnets looks like in the DC's first.
R1-DC01# show ip route 80.80.200.0Routing entry for 80.80.200.0/24 Known via "ospf 1", distance 110, metric 1 Tag 65100, type extern 2, forward metric 20 Last update from 10.100.12.2 on Ethernet0/0, 00:03:57 ago Routing Descriptor Blocks: * 10.100.12.2, from 10.100.100.2, 00:03:57 ago, via Ethernet0/0 Route metric is 1, traffic share count is 1 Route tag 65100
R2-DC01# show ip route 80.80.200.0Routing entry for 80.80.200.0/24 Known via "bgp 65001", distance 20, metric 0 Tag 65100, type external Redistributing via ospf 1 Advertised by ospf 1 subnets Last update from 100.100.23.3 00:04:42 ago Routing Descriptor Blocks: * 100.100.23.3, from 100.100.23.3, 00:04:42 ago Route metric is 0, traffic share count is 1 AS Hops 2 Route tag 65100
R5-DC02#show ip route 80.80.100.0Routing entry for 80.80.100.0/24 Known via "bgp 65002", distance 20, metric 0 Tag 65100, type external Last update from 100.100.45.4 00:10:10 ago Routing Descriptor Blocks: * 100.100.45.4, from 100.100.45.4, 00:10:10 ago Route metric is 0, traffic share count is 1 AS Hops 2 Route tag 65100
R6-DC02#show ip route 80.80.100.0Routing entry for 80.80.100.0/24 Known via "ospf 1", distance 110, metric 1 Tag 65100, type extern 2, forward metric 20 Last update from 10.200.56.5 on Ethernet0/0, 00:00:17 ago Routing Descriptor Blocks: * 10.200.56.5, from 10.200.200.5, 00:00:17 ago, via Ethernet0/0 Route metric is 1, traffic share count is 1 Route tag 65100
So, we have 2 problems. Edge routers R2 and R5 are injecting the BGP route due to the lower administrative distance of BGP, while the core routers R1 and R6 are injecting it because the metric for the redistributed route from BGP to OSPF is "1", unless if specified manually. We implement the following prefix list and route map on R2 and R5 and apply it to the peering towards R3 and R4 in the inbound direction.
R2-DC01#ip prefix-list INTERNAL seq 10 permit 80.80.0.0/16 ge 24route-map FILTER-IN deny 10 match ip address prefix-list INTERNALroute-map FILTER-IN permit 20
router bgp 65001 bgp log-neighbor-changes neighbor 100.100.23.3 remote-as 65100 address-family ipv4 network 80.80.100.0 mask 255.255.255.0 neighbor 100.100.23.3 activate neighbor 100.100.23.3 route-map FILTER-IN in
R5-DC02#ip prefix-list INTERNAL seq 10 permit 80.80.0.0/16 ge 24route-map FILTER-IN deny 10 match ip address prefix-list INTERNALroute-map FILTER-IN permit 20
router bgp 65002 neighbor 100.100.45.4 remote-as 65100 address-family ipv4 network 80.80.200.0 mask 255.255.255.0 neighbor 100.100.45.4 activate neighbor 100.100.45.4 route-map FILTER-IN in
Now let's have a look at the routing table, just to be sure.
R1-DC01#show ip route 80.80.200.0Routing entry for 80.80.200.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 10 Last update from 10.100.200.6 on Ethernet0/1, 00:05:04 ago Routing Descriptor Blocks: * 10.100.200.6, from 10.200.200.6, 00:05:04 ago, via Ethernet0/1 Route metric is 20, traffic share count is 1
R2-DC01#show ip route 80.80.200.0Routing entry for 80.80.200.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 20 Last update from 10.100.12.1 on Ethernet0/0, 00:05:45 ago Routing Descriptor Blocks: * 10.100.12.1, from 10.200.200.6, 00:05:45 ago, via Ethernet0/0 Route metric is 20, traffic share count is 1
R5-DC02#show ip route 80.80.100.0Routing entry for 80.80.100.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 20 Last update from 10.200.56.6 on Ethernet0/0, 00:08:54 ago Routing Descriptor Blocks: * 10.200.56.6, from 10.100.100.1, 00:08:54 ago, via Ethernet0/0 Route metric is 20, traffic share count is 1
R6-DC02#show ip route 80.80.100.0Routing entry for 80.80.100.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 10 Last update from 10.100.200.1 on Ethernet0/1, 00:09:50 ago Routing Descriptor Blocks: * 10.100.200.1, from 10.100.100.1, 00:09:50 ago, via Ethernet0/1 Route metric is 20, traffic share count is 1
As you can see from the routing tables, we are now using the direct link between the DC's, just as we wanted it. This solution comes though with the challenge of keeping the prefix-list updated. Easy, right? Until when you spend hours trying to find and update some prefix-list or ACL somewhere in the network.
Method 2: The well known attribute
Even though the first method solves the design requirement, we have the challenge of keeping the prefix-list updated. Since we have 1 AS for each DC, we could do the filtration based on the BGP well known attribute ASN. Instead of building a route-map, we just need to create an as-path filter and apply it directly to the peer with a filter list. Let's make it happen.
Here is how the configuration looks like:
R2-DC01#ip as-path access-list 1 deny ^65002$ip as-path access-list 1 permit .*
router bgp 65001 address-family ipv4 neighbor 100.100.23.3 filter-list 1 in exit-address-family
R5-DC02#ip as-path access-list 1 deny ^65001$ip as-path access-list 1 permit .*
router bgp 65002 address-family ipv4 neighbor 100.100.45.4 filter-list 1 in
The end result is the same. The routes containing AS 65002 in the as-path are filtered inbound on R2 and the ones containing AS 65001 are filtered inbound in R5. The final routing table looks exactly the same as the final one on method 1. This method is widely adapted, but we just need to keep in mind that it will filter any routes containing the respective AS on the path.
Method 3: Some magic?
Well let's say that managment doesn't like route-maps, acl's or filter lists, and they want the whole config to be done within the BGP process. Typical manager, right? Just find a solution and fix it.
However, we can use a magic trick, local-as, which makes us appear as if we were members of another AS than the actual one. We will implement the changes on DC2. This is very handy in cases of acquisitions, where we don't want to change our original peering agreements.
After the local-as configuration is applied, both the real ASN and the local-as are added to the AS path. In our case, routes transiting ISP A, would have both AS 65001 and 65002 when they reach DC1. The BGP loop prevention mechanism would then drop advertisements inbound on DC01, since the local ASN is part of the AS_Path in a route received through eBGP. Let's have a look at the configuration that is necessary to make this happen.
First, let's look at the advertisements on R2 and R5:
R2-DC01#show ip bgp 80.80.200.0BGP routing table entry for 80.80.200.0/24, version 13Paths: (1 available, best #1, table default) Not advertised to any peer Refresh Epoch 1 65100 65002 100.100.23.3 from 100.100.23.3 (100.100.100.3) Origin IGP, localpref 100, valid, external, best rx pathid: 0, tx pathid: 0x0
R5-DC02#show ip bgp 80.80.100.0BGP routing table entry for 80.80.100.0/24, version 22Paths: (1 available, best #1, table default) Not advertised to any peer Refresh Epoch 1 65100 65001 100.100.45.4 from 100.100.45.4 (100.100.100.4) Origin IGP, localpref 100, valid, external, best rx pathid: 0, tx pathid: 0x0
So in this case we see only the ASN of ISP A and the one from the other DC. In order to implement the solution, we need to change the BGP process id on R5, and configure the local-as for the peering towards R4.
The final config on R5 looks like this:
R5-DC02#show run | se router bgprouter bgp 65001 bgp log-neighbor-changes neighbor 100.100.45.4 remote-as 65100 neighbor 100.100.45.4 local-as 65002 ! address-family ipv4 neighbor 100.100.45.4 activate exit-address-family
In order to verify the presence of both AS65001 and 65002 on the route advertised from R5, we can use the ISP routers R3 or R4. We can also check that the routes for the 80.80.x.x are no longer pointing towards ISP A on R2 and R5.
R3-ISP# show ip bgp 80.80.200.0BGP routing table entry for 80.80.200.0/24, version 17Paths: (1 available, best #1, table default) Advertised to update-groups: 10 Refresh Epoch 1 65002 65001 100.100.34.4 from 100.100.34.4 (100.100.100.4) Origin IGP, metric 20, localpref 100, valid, internal, best
R2-DC01#show ip route 80.80.200.0Routing entry for 80.80.200.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 20 Last update from 10.100.12.1 on Ethernet0/0, 00:11:02 ago Routing Descriptor Blocks: * 10.100.12.1, from 10.200.200.6, 00:11:02 ago, via Ethernet0/0 Route metric is 20, traffic share count is 1
R5-DC02#show ip route 80.80.100.0Routing entry for 80.80.100.0/24 Known via "ospf 1", distance 110, metric 20, type extern 2, forward metric 20 Last update from 10.200.56.6 on Ethernet0/0, 00:10:07 ago Routing Descriptor Blocks: * 10.200.56.6, from 10.100.100.1, 00:10:07 ago, via Ethernet0/0 Route metric is 20, traffic share count is 1
Conclusion
We looked at 3 different ways to filter inbound eBGP advertisements and routes, route-maps and prefix-lists, as-path acl and filter-lists, and the magic trick with local-as. All three methods have their ups and downs, but the end result is the same in our specific scenario.
References
Lab