Filtering announcements
In the simple two-router BGP setup, filtering announcements is very straightforward: each router is configured with the required filters. It’s recommended to have two filters, one that only allows the network’s own prefixes in outgoing eBGP updates, and one that only allows AS paths with just the network’s AS number:
!
router bgp 65000
network 10.0.64.0 mask 255.255.252.0
neighbor 172.19.0.1 remote-as 65065
neighbor 172.19.0.1 filter-list 2 out
neighbor 172.19.0.1 prefix-list export out
!
ip as-path access-list 2 permit ^$
!
ip prefix-list export permit 10.0.64.0/22
!
ip route 10.0.64.0 255.255.252.0 null0
!
In this example, AS path access list 2 only permits empty AS paths. All prefixes received over eBGP have an AS path one or more ASes in it, so those prefixes aren’t allowed in outgoing updates. Prefixes originated in the local AS have an empty AS path at the time the filter is applied, the local AS number is added to the AS path between the moment the filter is applied and the moment the update is transmitted over eBGP. The prefix list named export only allows the locally originated /22.
Both the AS path filter list and the prefix list specify what’s allowed and then end, depending on the “implicit deny” property of Cisco access lists: everything that is not explicitly allowed by an access list is denied.
Having both access lists in place provides protection against the situation where one of the filters doesn’t function properly. This way, it’s possible to update a filter by pasting a new one to the router’s command line as follows:
!
no ip prefix-list export
ip prefix-list export permit 10.0.64.0/22
ip prefix-list export permit 10.0.64.0/23
ip prefix-list export permit 10.0.66.0/23
!
Note: during the moment or two that the export prefix list isn’t present (even though it’s referenced in the BGP section of the configuration), all updates are allowed through. |
With two filters present, the AS path access list still makes sure no improper updates leak out to the rest of the world while the modified prefix list is being pasted into the configuration. And yes, without a second filter, that does happen. If the BGP neighbor has a prefix limit applied to the session, the updates that slip through can easily be enough to trigger the maximum prefix limit so it’s necessary to ask the other side to clear the session manually. So when only a single filter is present, be sure to use a more conservative way to modify filters; i.e., by adding/removing individual lines rather than replacing the entire filter.
However, in larger networks having an outgoing AS path access list as well as an outgoing prefix list comes problematic. In really large networks, those filters may become unmanageably large. But even in medium-sized networks, having to reconfigure all routers when a new prefix gets added quickly becomes problematic. This is especially true in ISP networks where new customers often bring new prefixes and new ASes that should be allowed by the filters.
An alternative to enumerating all ASes and prefixes that are allowed is to tag all prefixes that should be advertised with a community and then filter on that community on outgoing eBGP sessions. This is a little more complex initially, but the big advantage is that it’s only necessary to filter prefixes on the routers where they’re originated or are learned over eBGP. This means the configurations of all other routers remain unchanged when a new prefix is added.
This is the configuration for a router that originates a prefix:
!
router bgp 65000
network 10.0.64.0 mask 255.255.252.0 route-map set-self
!
ip route 10.0.64.0 255.255.252.0 null0
!
route-map set-self permit 10
set community 65000:1
!
The network statement refers to a route map named set-self, which applies the community 65000:1 to the prefix as it’s injected into BGP. Communities are 32-bit numbers, which are generally expressed as two 16-bit decimal numbers with a colon between them. It’s best practice to use either the network’s (16-bit) AS number or a private AS number as the first value, to avoid clashing with the community values used by other networks and potentially triggering unintended actions.
This is the configuration applied to a customer’s BGP session:
!
router bgp 65000
neighbor 198.51.100.2 remote-as 64999
neighbor 198.51.100.2 route-map custa-in in
neighbor 198.51.100.2 filter-list 19 out
neighbor 198.51.100.2 prefix-list custa-pfx in
!
ip as-path access-list 19 permit ^(64999_)+$
!
ip prefix-list custa-pfx permit 172.29.0.0/16
ip prefix-list custa-pfx permit 172.30.0.0/16
!
route-map custa-in permit 10
set local-preference 200
set community 65000:2 additive
!
Because typically, ISPs don’t do much filtering on the peering sessions between them, it’s of paramount importance for ISPs to make sure they only allow legitimate advertisements from their customers. So here, once again two filters are used: an AS path filter list and a prefix list make sure only the prefixes that belong to the customer are accepted. The AS path filter list uses a regular expression that matches the beginning of the AS path (the ^ character) followed by the customer’s AS number a space: 64999_. That sequence is put between parentheses so the + character applies to the entire sequence, allowing it to be present one or more times. Then the $ character marks the end of the AS path, so there is no room for any other AS numbers. In other words: the customer may announce prefixes with an AS path that contains the customer’s own AS number one or more times, but no other AS numbers.
The prefix list allows two prefixes. If a prefix is allowed by both the AS path filter and the prefix list, the route map custa-in is applied, which applies the community 65000:2 to the prefix. The additive keyword preserves the community values that were already present. The route map also sets the local preference to 200, so routes received directly from the customer are always preferred over the same prefixes learned from other ISPs.
At this point, the BGP table holds prefixes with community 65000:1 that are originated within the network itself and prefixes with community 65000:2 that were learned from customers. The following BGP configuration allows these prefixes to be advertised to external (non-customer) networks. This configuration is the same on all the network’s routers, whether those routers originate prefixes or learn prefixes from customers or not.
!
router bgp 65000
neighbor 172.19.0.1 remote-as 65065
neighbor 172.19.0.1 route-map strip-comm in
neighbor 172.19.0.1 route-map allow-out out
!
ip community-list standard del-comm permit 65000:1
ip community-list standard del-comm permit 65000:2
!
ip community-list standard allowed-out-deny deny 65000:1
ip community-list standard allowed-out-deny deny 65000:2
ip community-list standard allowed-out-deny permit
!
route-map strip-comm permit 10
set comm-list del-comm delete
!
route-map allow-out deny 10
match community allowed-out-deny
!
route-map allow-out permit 20
set comm-list del-comm delete
!
In this configuration, the BGP session with AS 65065 is configured with two route maps: one that is applied to incoming updates and one that is applied to outgoing updates. The incoming one is simple enough: it uses the community list filter “del-comm” to match the communities 65000:1 and 65000:2 that are used to tag the network’s own and the network’s customer routes. If those communities are present, they’re removed from the prefixes received from AS 65065. This way, nothing unexpected happens should those communities be applied elsewhere by accident or maliciously.
The route map allow-out is a bit more unusual, as it uses deny 10 for the first clause rather than the expected permit 10. The match then points towards the allowed-out-deny community list. There, things get a bit tricky, because here the communities that should actually be allowed are denied, while all prefixes that don’t have either of these communities on them are permitted. But because this is a deny route map clause, the prefixes matched in the match section are actually denied and filtered out. The prefixes denied in the community list have now encountered a double negative and are therefore permitted to progress further.
Of course the same effect could have been achieved with a regular permit route map and a deny community filter… Except that in that case, a match would simply have allowed the prefixes to be advertised—with no opportunity to apply any further route map actions. In this example, the prefixes that survive the deny 10 clause (because they have the 65000:1 or 65000:2 community) go on to the permit 20 clause. There, the 65000:1 and 65000:2 communities are removed because the rest of the internet doesn’t have any use for them. At this point, it’s also possible to apply additional actions, such as setting the Multi Exit Discriminator or performing AS path prepending.
Note that the above only applies to outgoing filters on BGP sessions to other networks. There are also two other types of filters that are important: incoming filters on BGP sessions and outgoing filters on router interfaces.
Although ISPs advertise connectivity to the entire world in BGP, there are two types of prefixes that are best filtered out from ISPs and peering partners: the network’s own prefixes and Internet Exchange prefixes. By accepting more specific routes towards its own address space, a network may be tricked into sending traffic for internal destinations towards an external network. And accepting more specific routes for an Internet Exchange peering LAN leaves a network vulnerable to mistakes that may take down its peering sessions. As such, it’s best to filter out these prefixes and all more specific sub-prefixes:
!
ip prefix-list import deny 10.0.64.0/22 le 32
ip prefix-list import permit 0.0.0.0/0 le 24
!
This filter filters out the 10.0.64.0/22 prefix as well as all longer (more specific) prefixes that fall within that /22, such as 10.0.64.0/23, 10.0.66.0/23, 10.0.64.0/24, 10.0.65.0/24 and so on. It then permits all prefixes as long as the prefix length is at least (le = less or equal) 24 bits.
So it’s still a good idea to have a filter like this on all non-customer eBGP sessions, which means that all routers must be reconfigured when new prefixes are added to the network. However, this doesn’t have to happen immediately: everything still works without updating this filter, it’s just that the protection against one (rare) type of attack isn’t in place yet.
Note: customer prefixes should not be filtered in this manner. If the connection to a customer goes down, the customer’s prefixes may legitimately arrive through one of the customer’s other ISPs. |
On the interfaces that connect to ISPs and peering partners, it’s best practice to only allow outgoing packets with source addresses that belong to the network. So if a computer connected to the network sends out packets with spoofed source addresses, those packets aren’t propagated to the rest of the internet. (See BCP 38.) However, these anti-spoofing filters don’t have to be applied at the edge of the network. They can also be applied on the interfaces that receive packets from servers or users.