Guide

BGP Prefix-List and AS-Path Filtering on Cisco

BGP has no default policy. Once a session is Established, a router accepts every route its neighbor sends, apart from paths that already contain its own AS number, and advertises its best path for every prefix to every eBGP neighbor except the one it learned that path from. That includes routes learned from another provider, so an enterprise with two upstreams becomes a transit path between them unless something stops it. Cisco IOS has two purpose-built filters for this: the prefix-list, which matches a route by prefix and length, and the AS-path access-list, which matches the autonomous systems in its path. Both are applied below, inbound and outbound, on a four-router topology and then combined in a route-map; every block of output is what IOS XE printed. If your sessions are not up yet, start with configuring eBGP peering.

eBGP at the edges, iBGP across the middle — the reference wiring for BGP, not a specific lab.

How BGP filters attach: per neighbor, per direction

Every BGP filter is bound to one neighbor and one direction. An inbound (in) filter decides which of that neighbor's routes enter your BGP table. An outbound (out) filter decides which of your best paths are sent to that neighbor. A session takes one of each command below per direction, and a route has to be permitted by every filter applied in that direction:

  • neighbor ADDRESS prefix-list NAME in|out matches on prefix and length.
  • neighbor ADDRESS filter-list NUMBER in|out matches on the AS path, using an ip as-path access-list.
  • neighbor ADDRESS route-map NAME in|out matches on either one (or on other attributes) and can also change attributes.

The example topology

R1 (10.255.0.1) and R2 (10.255.0.2) form AS 65001. They run iBGP between their loopbacks with OSPF underneath; iBGP update-source and next-hop-self covers that half. R1 peers with R3 (AS 65002) at 10.0.13.2, R2 peers with R4 (AS 65003) at 10.0.24.2, and R3 and R4 also peer with each other. AS 65001 originates 172.16.1.0/24 and 172.16.2.0/24, R3 originates 198.51.100.0/24, and R4 originates 203.0.113.0/24 and 192.0.2.0/24.

With no policy, R1 sends R3 four prefixes: its own two, plus the two R4 originates, which R1 learned from R2. It holds back only 198.51.100.0/24, the route R3 itself sent. AS 65001 is offering to carry traffic between its two providers.

R1# show ip bgp neighbors 10.0.13.2 advertised-routes
BGP table version is 8, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   172.16.1.0/24    0.0.0.0                  0         32768 i
 *>i  172.16.2.0/24    10.255.0.2               0    100      0 i
 *>i  192.0.2.0        10.255.0.2               0    100      0 65003 i
 *>i  203.0.113.0      10.255.0.2               0    100      0 65003 i

Total number of prefixes 4 

R1 advertises AS 65003's prefixes to R3. The first filter removes them. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Prefix-lists: how a line matches

A prefix-list entry is ip prefix-list NAME [seq N] permit|deny PREFIX/LENGTH [ge MIN] [le MAX]. A route matches when two things are true: its first LENGTH bits equal those of PREFIX, and its own prefix length falls in the allowed range. With neither ge nor le, the range is LENGTH alone, so the entry matches one exact prefix. le MAX allows LENGTH through MAX, ge MIN allows MIN through 32, and both together allow MIN through MAX.

Entries are checked in sequence order and the first match decides. If you leave out seq, IOS numbers entries in steps of 5, which leaves room to insert a line later. A route that matches no entry is denied, so a list made only of deny lines blocks everything.

EntryMatchesDoes not match
172.16.0.0/16172.16.0.0/16 only172.16.1.0/24, 172.16.0.0/15
172.16.0.0/16 le 24172.16.0.0/16, 172.16.4.0/22, 172.16.1.0/24172.16.1.128/25, 172.17.0.0/16
172.16.0.0/16 ge 24172.16.1.0/24, 172.16.1.1/32172.16.0.0/16, 172.16.4.0/22
172.16.0.0/16 ge 24 le 24Any /24 inside 172.16.0.0/16172.16.0.0/16, 172.16.1.128/25
0.0.0.0/0The default route onlyEvery other route
0.0.0.0/0 le 24Any route from /0 to /24, default includedAnything from /25 to /32
0.0.0.0/0 le 32Every IPv4 routeNothing

Step 1 — Advertise only your own prefixes with an outbound prefix-list

AS 65001 owns 172.16.0.0/16 and advertises /24s from it, so one entry describes everything R1 should send: 172.16.0.0/16 le 24. Without le 24, the entry would match only a 172.16.0.0/16 route, which R1 does not have, and R1 would send R3 nothing at all.

Build the list and test it before you bind it to a neighbor. show ip bgp prefix-list NAME lists the routes in your BGP table that conform to the list, and show ip prefix-list NAME PREFIX first-match names the entry a given prefix hits — entry 5 below, still on a hit count of 0 because the list is not attached to anything yet. Neither command changes anything, so a typo shows up here instead of on the session.

R1(config)# ip prefix-list AS65001-OUT permit 172.16.0.0/16 le 24
R1(config)# end
R1# show ip prefix-list AS65001-OUT
ip prefix-list AS65001-OUT: 1 entries
   seq 5 permit 172.16.0.0/16 le 24
R1# show ip prefix-list AS65001-OUT 172.16.2.0/24 first-match
   seq 5 permit 172.16.0.0/16 le 24 (hit count: 0, refcount: 1)
R1# show ip bgp prefix-list AS65001-OUT
BGP table version is 8, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   172.16.1.0/24    0.0.0.0                  0         32768 i
 *>i  172.16.2.0/24    10.255.0.2               0    100      0 i

No seq was typed; IOS numbered the entry 5. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Apply it and soft-reset the session

Bind the list with out, then run clear ip bgp 10.0.13.2 soft out. Adding the filter does not by itself re-evaluate the routes the two routers have already exchanged; the soft reset is what applies it. R1 runs its table through the new policy and sends R3 the resulting updates and withdrawals, without dropping the TCP session.

Read the result from R1's side. advertised-routes now lists only AS 65001's prefixes, show ip prefix-list detail shows two hits on entry 5 — one per permitted route — and show ip bgp neighbors names the list and its direction.

R1(config)# router bgp 65001
R1(config-router)# neighbor 10.0.13.2 prefix-list AS65001-OUT out
R1(config-router)# end
R1# clear ip bgp 10.0.13.2 soft out
R1# show ip bgp neighbors 10.0.13.2 advertised-routes
BGP table version is 8, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   172.16.1.0/24    0.0.0.0                  0         32768 i
 *>i  172.16.2.0/24    10.255.0.2               0    100      0 i

Total number of prefixes 2 
R1# show ip prefix-list detail AS65001-OUT
ip prefix-list AS65001-OUT:
   count: 1, range entries: 1, sequences: 5 - 5, refcount: 4
   seq 5 permit 172.16.0.0/16 le 24 (hit count: 2, refcount: 1)
R1# show ip bgp neighbors 10.0.13.2 | include filter
  Outgoing update prefix filter list is AS65001-OUT

Only AS 65001's prefixes remain, so R3 no longer learns AS 65003's routes through AS 65001. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

AS-path access-lists: matching on the path

An AS-path access-list, ip as-path access-list NUMBER permit|deny REGEX, matches a regular expression against the AS path written out as text, such as 65003 65002. The leftmost AS is the neighbor that sent the route and the rightmost AS originated it. As with a prefix-list, entries are read top-down and a path that matches nothing is denied.

An unanchored expression matches anywhere in that text. 65003 on its own also matches 165003 and 650031, both valid 4-byte AS numbers, so anchor every expression to the position you mean. The pieces you need:

  • ^ is the start of the path and $ is the end.
  • _ matches a delimiter: a space, a comma, a brace, or the start or end of the path.
  • . is any single character, * repeats the previous item zero or more times, + one or more times, and ( ) groups items.
  • ^$ is an empty path: a route originated inside your own AS.
  • ^65003$ is a route originated by AS 65003 and received directly from it.
  • ^65003_ is any route received from AS 65003.
  • _65003$ is any route originated by AS 65003, however far away.
  • _65003_ is any route that passed through AS 65003.

Test the expression before you build the list

show ip bgp regexp runs an expression against your BGP table directly. On R2, ^65003$ matches the two routes R4 originated. That expression has a weakness: if R4 ever prepends its own AS, the path becomes 65003 65003 and no longer matches. ^65003(_65003)*$ accepts one or more copies of 65003 and nothing else. Here it matches the same two routes, because R4 does not prepend.

Once the expression is right, put it in a list. show ip as-path-access-list prints the list, and show ip bgp filter-list shows which routes in the table it permits.

R2# show ip bgp regexp ^65003$
BGP table version is 6, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i
R2# show ip bgp regexp ^65003(_65003)*$
BGP table version is 6, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

R2(config)# ip as-path access-list 20 permit ^65003$
R2(config)# end
R2# show ip as-path-access-list 20
AS path access list 20
     permit ^65003$
R2# show ip bgp filter-list 20
BGP table version is 6, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

Both expressions match the same two routes, the ones R4 originated. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Step 2 — Accept only a neighbor's own routes with a filter-list

R4 sends R2 its own two prefixes plus 198.51.100.0/24, which R4 learned from R3, so that route carries the path 65003 65002. If R2 should use R4 only for AS 65003's own networks, ^65003$ is the whole policy: it permits a path that is exactly R4's AS and nothing longer.

R2# show ip bgp neighbors 10.0.24.2 routes
BGP table version is 6, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *    198.51.100.0     10.0.24.2                              0 65003 65002 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

Total number of prefixes 3 

Before the filter: R2 accepts R4's own routes and the route R4 carries for AS 65002. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Apply the filter-list inbound

Bind list 20 with filter-list 20 in and soft-reset inbound. clear ip bgp 10.0.24.2 soft in asks R4 to resend its routes through the route refresh capability, which IOS routers negotiate by default, so the session stays up.

R2 still reaches 198.51.100.0/24. The path left in its table is the internal one from R1 at 10.255.0.1, which is where AS 65002's routes should come from. The last line of the block is the neighbor's Local Policy Denied Prefixes counter for filter-lists, outbound first and inbound second: one route rejected on the way in.

R2(config)# router bgp 65001
R2(config-router)# neighbor 10.0.24.2 filter-list 20 in
R2(config-router)# end
R2# clear ip bgp 10.0.24.2 soft in
R2# show ip bgp neighbors 10.0.24.2 routes
BGP table version is 6, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

Total number of prefixes 2 
R2# show ip bgp 198.51.100.0/24
BGP routing table entry for 198.51.100.0/24, version 5
Paths: (1 available, best #1, table default)
  Advertised to update-groups:
     1         
  Refresh Epoch 1
  65002
    10.255.0.1 (metric 11) from 10.255.0.1 (10.255.0.1)
      Origin IGP, metric 0, localpref 100, valid, internal, best
...
R2# show ip bgp neighbors 10.0.24.2 | include filter
  Incoming update AS path filter list is 20
    filter-list:                          0          1

198.51.100.0/24 is gone from R4's routes, and the denied counter reads one prefix inbound. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Step 3 — The AS-path way to stop transit

Step 1 stopped the leak by listing AS 65001's address space, which means editing the list every time the AS adds a prefix. The AS-path version describes the property you care about instead: only routes that originated inside AS 65001 may leave. In R1's table those routes have an empty path. That covers 172.16.1.0/24, which R1 originates, and 172.16.2.0/24, which R1 learned from R2, because iBGP does not add an AS number.

An outbound filter-list is checked against the path as it sits in the table, before R1 adds 65001 on the way out. ^$ is therefore the correct expression, and ^65001$ would match nothing R1 holds.

R1# show ip bgp regexp ^$
BGP table version is 8, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   172.16.1.0/24    0.0.0.0                  0         32768 i
 *>i  172.16.2.0/24    10.255.0.2               0    100      0 i

R1(config)# ip as-path access-list 10 permit ^$
R1(config)# router bgp 65001
R1(config-router)# neighbor 10.0.13.2 filter-list 10 out
R1(config-router)# end
R1# clear ip bgp 10.0.13.2 soft out
R1# show ip bgp neighbors 10.0.13.2 advertised-routes
BGP table version is 8, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   172.16.1.0/24    0.0.0.0                  0         32768 i
 *>i  172.16.2.0/24    10.255.0.2               0    100      0 i

Total number of prefixes 2 
R1# show ip bgp neighbors 10.0.13.2 | include filter
  Outgoing update AS path filter list is 10

The Step 1 prefix-list is off here, so the filter-list is the only outbound policy: ^$ matches the two routes AS 65001 originated, and only those are sent. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Stopping transitOutbound prefix-listOutbound filter-list (^$)
What it describesYour address spaceRoutes originated inside your AS
You add a new prefixNot advertised unless the list already covers itAdvertised with no change
Someone originates a prefix by mistakeBlocked unless it falls inside the permitted rangeAdvertised
Routes learned from another ASBlocked unless they fall inside the permitted rangeBlocked

Combine both in a route-map

Separate filters work when each one is a plain yes or no. When the policy is an ordered mix, such as "drop this prefix, then accept only that AS", or when some routes need an attribute changed, put the matches inside one route-map.

Two rules catch people out. First, permit in a prefix-list or AS-path list only means "this route matches"; the route-map clause's own permit or deny decides what happens to it. Second, a route-map ends with an implicit deny, so a route that matches no clause is dropped. In the map below, clause 10 drops 192.0.2.0/24, clause 20 accepts paths that are exactly 65003, and 198.51.100.0/24 falls through to the implicit deny.

Inside one clause, separate match commands must all be true. Several lists named on a single match command need only one of them to match. show route-map prints the clauses in order with the lists each one matches on; its Policy routing matches counter stays at zero because it counts policy-routed packets, not BGP routes. The same clause structure carries set local-preference or set weight when you want to prefer a path rather than drop it; BGP best path selection covers those.

R2(config)# ip as-path access-list 20 permit ^65003$
R2(config)# ip prefix-list R4-BLOCK permit 192.0.2.0/24
R2(config)# route-map R4-IN deny 10
R2(config-route-map)# match ip address prefix-list R4-BLOCK
R2(config-route-map)# exit
R2(config)# route-map R4-IN permit 20
R2(config-route-map)# match as-path 20
R2(config-route-map)# exit
R2(config)# router bgp 65001
R2(config-router)# neighbor 10.0.24.2 route-map R4-IN in
R2(config-router)# end
R2# clear ip bgp 10.0.24.2 soft in
R2# show ip bgp neighbors 10.0.24.2 routes
BGP table version is 8, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

Total number of prefixes 1 
R2# show route-map R4-IN
route-map R4-IN, deny, sequence 10
  Match clauses:
    ip address prefix-lists: R4-BLOCK 
  Set clauses:
  Policy routing matches: 0 packets, 0 bytes
route-map R4-IN, permit, sequence 20
  Match clauses:
    as-path (as-path filter): 20 
  Set clauses:
  Policy routing matches: 0 packets, 0 bytes
R2# show ip bgp neighbors 10.0.24.2 | include Route map
  Route map for incoming advertisements is R4-IN

Only 203.0.113.0/24 gets through: clause 10 drops 192.0.2.0/24 and 198.51.100.0/24 matches no clause. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Verify what a filter did

These commands answer most questions about a filter; the BGP commands cheat sheet lists the rest.

  • show ip bgp neighbors ADDRESS routes lists the routes accepted from the neighbor, after inbound policy.
  • show ip bgp neighbors ADDRESS advertised-routes lists the routes sent to the neighbor, after outbound policy.
  • show ip bgp neighbors ADDRESS received-routes lists everything the neighbor sent, before inbound policy. It needs soft-reconfiguration inbound on that neighbor, which keeps an unfiltered copy of every route in memory. Soft resets do not need it; turn it on for this comparison.
  • show ip prefix-list detail NAME shows a hit count for each entry.
  • show ip bgp neighbors ADDRESS names every filter bound to the session and its direction. Its Local Policy Denied Prefixes table counts the routes each kind of filter has rejected, outbound and inbound.
R2(config)# router bgp 65001
R2(config-router)# neighbor 10.0.24.2 soft-reconfiguration inbound
R2(config-router)# end
R2# clear ip bgp 10.0.24.2 soft in
R2# show ip bgp neighbors 10.0.24.2 received-routes
BGP table version is 11, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *    198.51.100.0     10.0.24.2                              0 65003 65002 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i

Total number of prefixes 3 
R2# show ip bgp neighbors 10.0.24.2 routes
BGP table version is 11, local router ID is 10.255.0.2
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   192.0.2.0        10.0.24.2                0             0 65003 i
 *>   203.0.113.0      10.0.24.2                0             0 65003 i
Total number of prefixes 2 

Captured with Step 2's filter-list applied: received-routes is what R4 sent, routes is what the filter let in. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Troubleshooting: a prefix-list that drops everything

A prefix-list written as a block list drops everything. Below, R1 was meant to refuse a single prefix from R3, but the list has no permit entry, so the implicit deny rejects every route R3 sends. The damage is easy to miss: 198.51.100.0/24 did not disappear. R1 now reaches R3's network the long way round, learning it from R2 on the path 65003 65002. The only clue in the summary is the 0 in the State/PfxRcd column for 10.0.13.2: a number there is a prefix count, so the session is Established and receiving nothing.

R1(config)# ip prefix-list R3-IN seq 5 deny 192.0.2.0/24
R1(config)# router bgp 65001
R1(config-router)# neighbor 10.0.13.2 prefix-list R3-IN in
R1(config-router)# end
R1# clear ip bgp 10.0.13.2 soft in
R1# show ip bgp 198.51.100.0/24
BGP routing table entry for 198.51.100.0/24, version 12
Paths: (1 available, best #1, table default)
  Flag: 0x8100
  Not advertised to any peer
  Refresh Epoch 1
  65003 65002
    10.255.0.2 (metric 11) from 10.255.0.2 (10.255.0.2)
      Origin IGP, metric 0, localpref 100, valid, internal, best
...
R1# show ip bgp summary
BGP router identifier 10.255.0.1, local AS number 65001
...
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.0.13.2       4        65002      31      41       11    0    0 00:17:16        0
10.255.0.2      4        65001      26      27       12    0    0 00:16:40        4

An Established session that receives nothing, and the detour 198.51.100.0/24 took to arrive. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Fix: end the list with a permit

Add a last entry that permits what should pass. 0.0.0.0/0 le 32 permits every IPv4 route. On an Internet edge, 0.0.0.0/0 le 24 is a common alternative because it also refuses anything longer than /24; RFC 7454 collects that check with the other prefix filters an eBGP edge should run. After the soft reset, R3's routes return except the one the deny entry names, and the hit counts show which entry matched each route.

R1(config)# ip prefix-list R3-IN seq 10 permit 0.0.0.0/0 le 32
R1(config)# end
R1# clear ip bgp 10.0.13.2 soft in
R1# show ip bgp neighbors 10.0.13.2 routes
BGP table version is 13, local router ID is 10.255.0.1
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>   198.51.100.0     10.0.13.2                0             0 65002 i
 *    203.0.113.0      10.0.13.2                              0 65002 65003 i

Total number of prefixes 2 
R1# show ip prefix-list detail R3-IN
ip prefix-list R3-IN:
   count: 2, range entries: 1, sequences: 5 - 10, refcount: 3
   seq 5 deny 192.0.2.0/24 (hit count: 1, refcount: 1)
   seq 10 permit 0.0.0.0/0 le 32 (hit count: 2, refcount: 1)

Entry 5 matched 192.0.2.0/24 once; entry 10 let the other two routes through. Output captured on Cisco IOL (IOS XE 17.16) in Cisco Modeling Labs.

Other common problems (and the fix)

  • The policy is in the config but nothing has changed yet. Run clear ip bgp ADDRESS soft in or soft out for the direction you changed. An inbound reset waits on the neighbor to resend its routes, so allow a few seconds. Never run clear ip bgp * without soft: it resets every session on the router.
  • The range misses the length. 172.16.0.0/16 matches only the /16 itself. Add le 24, or whatever your longest advertised prefix is, to match the subnets.
  • Wrong direction or wrong neighbor. An in list on a session you meant to filter out filters the wrong routes. show ip bgp neighbors ADDRESS | include filter names each list and its direction.
  • An unanchored expression. Use ^, $ and _ so the expression means one AS in one position.
  • There was nothing to filter. If your own prefix never appears in advertised-routes, even with no filter applied, the problem is origination, not policy. See why the network statement needs an exact match.

Frequently asked questions

What is the difference between a prefix-list and a distribute-list in BGP?

A distribute-list filters routes with a standard or extended access-list, which matches address bits but not prefix length, unless you use the extended ACL workaround of matching the mask in the destination fields. A prefix-list matches the prefix and its length directly, supports ge and le to cover a range of lengths, and can be edited one entry at a time by sequence number. That makes a prefix-list the clearer tool for BGP, and it is the one used throughout this guide.

Do I have to reset a BGP session after changing a filter?

Not a hard reset. Run clear ip bgp with the neighbor address and soft in or soft out, depending on the direction you changed. Until you do, the session keeps carrying what it carried before, because the new policy is only applied when a table is run through it again. A soft inbound reset uses the route refresh capability to ask the neighbor to resend its routes; a soft outbound reset runs your own table through the new policy. Either way the session stays up. A plain clear ip bgp without the soft keyword drops the session and withdraws its routes until it comes back.

What does the regular expression ^$ match in a BGP AS-path filter?

An empty AS path, which is how routes originated inside your own autonomous system appear in your BGP table, including routes learned from iBGP peers in the same AS. Applied outbound with a filter-list, it lets only your own routes out, because the check runs before your router adds its own AS number to the path. It is the standard way to stop an enterprise with two providers from acting as transit between them.

How do I permit all remaining routes at the end of a prefix-list?

End the list with a permit entry for 0.0.0.0/0 le 32, which matches every IPv4 prefix of any length. Without it, the implicit deny at the end of the list drops every route that no earlier entry permitted. Use le 24 instead of le 32 if you also want to refuse prefixes longer than /24 from the Internet.

Can a BGP neighbor have a prefix-list, a filter-list and a route-map at the same time?

Yes. Each neighbor accepts one of each per direction, and a route has to be permitted by every filter applied in that direction to be accepted or advertised. When the logic needs an ordered mix of permits and denies, or needs to change attributes such as local preference, a single route-map that matches on prefix-lists and AS-path lists is easier to read than three separate filters.

Practice BGP filtering

Write the filter yourself on real Cisco IOS in CML, then upload the config for a grade.

All BGP labs →

What grading looks like

This is what grading your config looks like

A sample result — 4 of 5 requirements met. This is exactly what you see the moment you submit.

bgp-lab-export.yaml — read 3 device configs

Score: 80% — Keep going (4 of 5 checks passed)

  • Passed: BGP process running as AS 65001 on R1
  • Passed: eBGP neighbor 10.0.13.2 in AS 65002
  • Passed: Session to 10.0.13.2 is Established
  • Passed: 172.16.1.0/24 originated by an exact match
  • Failed: next-hop-self toward the iBGP peer — missing on R2
Solution revealed

The full node-by-node answer key unlocks the moment you submit — so you see exactly what you missed.

Don't just read it — configure it

Reading is step one. Build BGP on real Cisco IOS and have your own config graded.