BGP filtering methods: Who turned off the lights?


BGP filtering is a topic that is not well understood, especially when we are talking about route-map logic. In this homemade scenario we will discuss different ways to filter prefixes or even a whole AS out of the BGP table.


  1. Initial scenario blueprint
  2. AS-PATH with filter-list in and out
  3. Distribute list with access-list
  4. Route-map logic and examples
  5. Conclusion

1.Initial scenario blueprint

We have a simple scenario with two customer sites using AS 65001, and upstream ISP providers with dual-multihomed fashion from customer side.

Dual refers to connections, and home is about ISP. Each customer router has two interfaces to multiple ISP.

We are not using L3VPNs here, this is very basic config to play with filtering.

2.Filtering different BGP AS(AS-PATH filtering)

Classic interview question for BGP: How to avoid being a transit for the ISP?

Very short answer: with a as-path access-list applied outbound

Long answer here:

With just pure BGP path selection luck or by ISP will, you (as a customer) can become a transit path for the ISP which can imply higher cost for your company and less bandwidth for you to use. This means that for example ISP R5 can use (and will use in many occasions) CE R9 or R8 to reach AS 40 for instance.

Here in this scenario from R6 ISP AS 60, to reach AS 70 R7 prefix we are using customer CE R2 ( R2 is the transit for prefix at this moment!!

In this case the reason to choose R2 is the lowest router-id in the path selection, which is the last tiebreaker.

We will block being a transit IP by only injecting to the ISP our own generated routes, and not allowing any other AS routes to be announce to the ISP.

We can do manual filtering with ip-prefix list, but this won’t be scalable as the routes will change in the future. We will use as-path filtering that works by matching the

AS number instead.

Before applying any filters from R2 CE , list of routes we are injecting to R6:

Config for both our CEs R2 and R3:

ip as-path access-list 1 permit ^$

Later we apply to each ISP neighbor from both CEs with a filter list(also we can use a route-map)

R2 config:

neighbor filter-list 1 out (ISP R7)

neighbor filter-list 1 out (ISP R6)

R3 config:

neighbor filter-list 1 out (ISP R6)

neighbor filter-list 1 out (ISP R7)

As a final step:

We refresh the BGP adj-in table: clear ip bgp * soft

We check again from R6 and R7 perspective:

See now how from ISP R6 we don’t have the choice to go through the customer site to reach for example prefix (prefix belongs to R7 ISP).

See how this filter works from CE side R2, we can try the regular expression ^$ that we used in the filter list:

Also, we can see what we announce to the neighbor R6 for example:

Notice how show ip bgp neighbor x.x.x.x advertise-routes will show what we will inject to the neighbor after applying our local policies, so here is showing already the result of the filtering!!

Compare it with the same command before applying the filter list that is shown a few pictures above.

Blocking all routes originated in AS 40

From R2 again, now we want to block any routes coming from AS 40 as origin.

Before for example applying the regular expression filtering, we can test it to see what will block:

Regexp _40$ means any route that their origin is AS 40

We will use another as-path access-list as this one will be applied in the inbound direction:

Config for R2 and R3:

ip as-path access-list 2 deny _40$

ip as-path access-list 2 permit .*

Applied in the outbound direction to both ISP:


  • neighbor filter-list 2 in
  • neighbor filter-list 2 in


  • neighbor filter-list 2 in
  • neighbor filter-list 2 in

Remember to clear ip bgp * soft after applying any policy to make it work!!

After, we can see how prefix (which was the only originated in AS 40) is no longer in the RIB:

3.Distribute list filtering

This is used to filter a prefix more than a whole AS, for example we want to block prefix before it enters R2 and R3 side.

Before blocking anything, we can see how we have the prefix installed in the RIB:

After blocking in both R2 and R3 by applying the distribute list in the inbound direction:

R2 and R3 config:

access-list 1 deny

access-list 1 permit any


neighbor distribute-list 1 in

neighbor distribute-list 1 in.


neighbor distribute-list 1 in

neighbor distribute-list 1 in

4.Route-map filtering logic

Route-map have a sequence number which allows fast and concise editing, other lists have to be deleted completely and redone to do any changes. Route-maps are very flexible in that regard.

First let’s understand the logic of route-map which is confusing for many people, the key here is that what determines if a route is allowed or not is the permit or deny of the route-map statement.

For example:

Route-map Test permit 10

  • Match ACL:
    • Access-list 5 permit will be allowed
    • Access-list 5 deny  will be ignored, not even blocked. Will continue to the next statement of the route-map!

Route-map Test deny 20

  • ACL or prefix list statement matched:
    • Ip prefix-list 1 permit  will be denied
    • Ip prefix-list 1 deny  will be ignored, continue to the next route-map statement to decide its fate!

Route-map Test permit 50

  • Nothing match here, meaning will match everything.

If we leave it like this, the only thing here that will be blocked is that matches the deny in route-map statement 20:

  • The statement from sequence 10, Access-list 5 deny and the statement from sequence 20 ip prefix-list 1 deny now arrive here.
  • Those two prefixes that were denied in the ACL and prefix list will be allowed in the end, as they will match the permit in the route-map permit 50.
Summary route-map logic:
  • Route-map permit + ACL permit = allow
  • Route-map permit + ACL deny = ignore and move to next route-map line
  • Route-map deny + ACL permit = block it
  • Route-map deny + ACL deny = ignore it and move to next route-map line

Remember that if a ACL have a deny means, that the route-map won’t match it. Not necessarily means it will be denied, it will depend on next route-map statements.

Example 1:

Let’s give a local pref value to some routes coming into R2.

Let’s say we want to have R2 as the exit point for prefixes and originated from R10 loopback:

R2 config:

Prefix-list 1:

ip prefix-list 1 seq 10 permit

ip prefix-list 1 seq 15 permit

ip prefix-list 1 seq 16 deny

ip prefix-list 1 seq 17 deny


 route-map Caja permit 10

 match ip address prefix-list 1

 set local-preference 200

BGP config:

neighbor route-map Caja in

neighbor route-map Caja in


We are blocking everything except what matches the permit statement in the prefix list 1.

But we noticed that we are missing all other prefixes coming from the ISP now!

Because there is a hidden implicit deny at the end of each route-map, all other prefixes will be denied!

To fix that, and only apply local pref 200 to the two routes that are permitted in the ip prefix list but still allow the other routes, you have to add another route-map statement with a permit and nothing to match.

That will allow everything, including the deny prefixes that we set in the ip prefix list, but this time won’t get any local pref value.


 route-map Caja permit 10

 match ip address prefix-list 1

 set local-preference 200

route-map Caja permit 70

See how only the two ip prefix-list 1 prefixes with a permit matched and got the local pref 200.

Example 2:

Now we will have a new route-map using the same prefix list 1:

Prefix-list 1:

ip prefix-list 1 seq 10 permit

ip prefix-list 1 seq 15 permit

ip prefix-list 1 seq 16 deny

ip prefix-list 1 seq 17 deny


Route-map test deny 10

Match ip address prefix 1

Route-map test permit 50

Here we have a deny in the route map, so whatever will be inside the prefix list with a permit will be matched by the route-map deny statement and whatever inside the prefix-list with a deny will be ignored and moved to the next route-map statement which is a permit any, route-map test permit 50 will permit anything as it doesn’t have any match inside.

When applied to both neighbors as before:

We are denying the two prefix in the prefix-list 1 that have a permit, because the route-map statement had a deny. “We are denying to permit those prefixes”.


I hope that this was informative and that you take the time to try it yourself to have some fun with filtering in a controlled environment.

Route-maps require a lot of practice on your own to get the idea, go for it!

Any doubts with route-maps?

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Leave a Reply