Friday, April 17, 2015

BGP Route Filtering using AS_PATH list

When using BGP, it is possible to filter out routes using a special kind of access-list called an as-path access-list. This allows for matching based on the AS_PATH PA, which includes the AS_SEQ, AS_SET as well as the AS_CONFED_SEQ and AS_CONFED_SET.

The difficult part of this is not the configuration. You basically create an access-list that filters what is matched with deny statement and allows what is permitted. This access-list is then applied to a neighbor under the BGP router process in either the inbound or outbound direction.

The difficulty with as-path access-lists is the matching logic, which is based on regular expressions (regex). Not all people are familiar with regex, but if you have used grep, for example, you may be quite firm with the syntax. I want to make it clear that I am in no way a regex pro and I am in no way certain that the syntax below is the best to accomplish the tasks given, but they work in this very limited scenario.

Below is the topology used for the BGP as-path access-list configuration.
AS-Path access-list filtering topology
Before changing anything, we take a look at the BGP table of R4.
R4#show ip bgp | begin Network
     Network          Next Hop            Metric LocPrf Weight Path
 *   20.0.0.0/24      10.0.14.1                                              0 1 2 i
 *>                         10.0.34.3                                              0 3 2 i
 *   21.0.0.0/24      10.0.14.1                                              0 1 2 i
 *>                         10.0.34.3                                              0 3 2 i
 *   22.0.0.0/24      10.0.14.1                                              0 1 2 i
 *>                         10.0.34.3                                              0 3 2 i
 *   23.0.0.0/24      10.0.14.1                                              0 1 2 i
 *>                         10.0.34.3                                              0 3 2 i
 *   30.0.0.0/24      10.0.14.1                                              0 1 2 3 i
 *>                         10.0.34.3                0                            0 3 i
 *   31.0.0.0/24      10.0.14.1                                              0 1 2 3 i
 *>                         10.0.34.3                0                            0 3 i
 *   32.0.0.0/24      10.0.14.1                                              0 1 2 3 i
 *>                         10.0.34.3                0                            0 3 i
 *   33.0.0.0/24      10.0.14.1                                              0 1 2 3 i
 *>                         10.0.34.3                0                            0 3 i
 *>  40.0.0.0/24      0.0.0.0                  0                     32768 i
 *>  41.0.0.0/24      0.0.0.0                  0                     32768 i
 *>  42.0.0.0/24      0.0.0.0                  0                     32768 i
 *>  43.0.0.0/24      0.0.0.0                  0                     32768 i
There are multiple entries for the networks advertised on R3 and R2. What we want to do is this:

  • Filter out routes on R4 received from R1 where the AS path is longer than 2 hops.
  • Filter out routes on R4 received from R3 where the last AS in the path is AS 2.
We will create two as-path access-lists and apply them for each neighbor (R1 and R3) in the inbound direction. But first we need to figure out the regex that fits the criteria. One way to do that is by filtering the BGP table using the regexp keyword with the regular expression to fine tune the matching without applying a routing policy to the traffic.

Below we try out a regex string for the first requirement.
R4#show ip bgp regexp ^1_.+_.+$
<output omitted>
     Network          Next Hop            Metric LocPrf Weight Path
 *   30.0.0.0/24      10.0.14.1                                             0 1 2 3 i
 *   31.0.0.0/24      10.0.14.1                                             0 1 2 3 i
 *   32.0.0.0/24      10.0.14.1                                             0 1 2 3 i
 *   33.0.0.0/24      10.0.14.1                                             0 1 2 3 i
Below is a breakdown of the regular expression and what it does in this context.
The caret (^) forces the string to match from the beginning of the path. Without it, it would mean that any number of ASes could precede AS 1.
The 1 followed by the underscore (_) matches on exactly the AS of 1 with the underscore being any delimiter - in this case a space. Without the underscore this would match AS 1, 12, 1234 and so on.
The dot (.) means any character and the plus (+) means one or more instances of the preceding character (which would be any character). So, at least one character of any kind should be in last two sections.
The underscore (_) again means that there must be another delimiter.
This is sequence is repeated once more, but without the trailing underscore (_) to make sure it can match any paths that may be longer than just three.
The final metacharacter is the almighty dollar sign ($), which means end of file.
What we get should match a path coming from AS 1 and then at least 2 more ASes following that. We could have made them all three ASes .+ if we wanted to be able to reuse the matching logic on other portions that doesn't match AS 1 first, but in this case I chose not to.

Now onto testing a string for the second requirement - matching any AS path where the final AS is exactly 2.
R4#show ip bgp regexp ^.*_2$
<output omitted>
     Network          Next Hop            Metric LocPrf Weight Path
 *   20.0.0.0/24      10.0.34.3                                             0 3 2 i
 *>                         10.0.14.1                                             0 1 2 i
 *   21.0.0.0/24      10.0.34.3                                             0 3 2 i
 *>                         10.0.14.1                                             0 1 2 i
 *   22.0.0.0/24      10.0.34.3                                             0 3 2 i
 *>                         10.0.14.1                                             0 1 2 i
 *   23.0.0.0/24      10.0.34.3                                             0 3 2 i
 *>                         10.0.14.1                                             0 1 2 i
Here we just do the .* matching after the start of file metacharacter and finish off with the _2 just before the end of file metacharacter. The asterisk (*) works almost identical to the plus (+) used previously, but with the difference that it can match zero instances of the preceding character - so it can essentially match on nothing as well.

So, we now have the two regex strings we need to create the as-path access-lists.
R4#configure terminal
R4(config)#ip as-path access-list 1 deny ^1_.+_.+$
R4(config)#ip as-path access-list 1 permit .*
R4(config)#ip as-path access-list 2 deny ^.*_2$
R4(config)#ip as-path access-list 2 permit .*
R4(config)#router bgp 4
R4(config-router)#neighbor 10.0.14.1 filter-list 1 in
R4(config-router)#neighbor 10.0.34.3 filter-list 2 in
R4(config-router)#end
R4#clear ip bgp * in
With as-path access-list filtering, what is denied by the access-list is what is filtered and what is permitted is left unfiltered. The second line of of both as-path access-lists is akin to the any of regular ip access-lists. It changes the implied deny any to an explicit permit any instead.

This is now the BGP table of R4 after the filtering is done.
R4#show ip bgp | begin Network
     Network          Next Hop            Metric LocPrf Weight Path
 *>  20.0.0.0/24      10.0.14.1                                            0 1 2 i
 *>  21.0.0.0/24      10.0.14.1                                            0 1 2 i
 *>  22.0.0.0/24      10.0.14.1                                            0 1 2 i
 *>  23.0.0.0/24      10.0.14.1                                            0 1 2 i
 *>  30.0.0.0/24      10.0.34.3                0                          0 3 i
 *>  31.0.0.0/24      10.0.34.3                0                          0 3 i
 *>  32.0.0.0/24      10.0.34.3                0                          0 3 i
 *>  33.0.0.0/24      10.0.34.3                0                          0 3 i
 *>  40.0.0.0/24      0.0.0.0                    0                  32768 i
 *>  41.0.0.0/24      0.0.0.0                    0                  32768 i
 *>  42.0.0.0/24      0.0.0.0                    0                  32768 i
 *>  43.0.0.0/24      0.0.0.0                    0                  32768 i
We have now accomplished the two requirements stated earlier using as-path access-list filtering.

To summarise: as-path access-list filtering is done using regular expressions. You can test out regular expressions using the show ip bgp regexp <regex string> command. The as-path access-list is applied using the neighbor <ip address> filter-list <as-path acl #> in|out command under the BGP router process. The regex examples in this post are quite simple - regex is a VERY powerful tool for matching and can be used for much more than just BGP.

No comments:

Post a Comment