Latest Cisco, PMP, AWS, CompTIA, Microsoft Materials on SALE Get Now Get Now

Route Filtering with BGP, EIGRP, OSPF and Static: Three Protocols, Three Different Answers

Route filtering is not one topic. It is three, because distance-vector protocols, link-state protocols, and path-vector protocols expose fundamentally different amounts of control over what they advertise. EIGRP will filter anything, in any direction, on any interface, because it advertises routes and a route not advertised simply does not exist downstream. BGP will filter anything per neighbour per direction, for the same reason. OSPF will filter almost nothing inside an area, because every router in an area must hold an identical link-state database — that is not an implementation limitation but the property that makes SPF produce consistent results.

The consequence catches people repeatedly. distribute-list in configured under OSPF looks like it filters, is accepted without complaint, and does something quite different from what the same command does under EIGRP: it prevents routes from being installed in the local routing table while the LSAs continue to flood normally to every other router. The prefix disappears from show ip route on that router and remains in show ip ospf database everywhere including there. Engineers who learned filtering on EIGRP and apply the same reflex to OSPF produce a router that cannot reach a destination the rest of the network can, which is a black hole for anything transiting it and is invisible from anywhere else.

This article covers where each protocol can filter and what each mechanism actually does. Section one maps the three protocol families onto the control each provides. Section two covers distance-vector filtering, which is the straightforward case. Section three explains why OSPF is different and enumerates the five places it does allow filtering. Section four covers BGP and redistributed statics. Section five is the failure catalogue, dominated by filters that did not filter and filters that black-holed more than intended. Throughout, the recurring question is whether a given command stops propagation or merely stops installation, because those two look identical on the router you configured and completely different everywhere else.

Blog Claimdistribute-list in means "do not install this route" under OSPF and "do not accept this route" under EIGRP, and treating those as the same command is the single most productive misunderstanding in route filtering.
 
Three protocol families with three different filtering models: EIGRP filters the advertisement, OSPF filters only the local RIB except at specific boundaries, and BGP filters per neighbour and direction.

Where Can Each Protocol Actually Filter?

What determines the difference?

Whether the protocol advertises routes or advertises topology. EIGRP and RIP advertise routes — a neighbour is told "I can reach this prefix at this metric" — so declining to send one, or declining to accept one, removes it from the downstream view entirely. OSPF advertises link-state information that every router in the area must hold identically in order to compute a consistent shortest-path tree; removing an LSA from one router's database would make its tree disagree with its neighbours', which is exactly the condition link-state routing is designed to prevent. BGP advertises paths per neighbour and has always been a policy protocol, so filtering is a first-class feature in both directions.

A Deeper Dive into the Three Models

The three families compared

Capability EIGRP / RIP OSPF BGP
Filter inbound from a neighbour Yes — route never enters the topology table RIB only — LSDB and flooding unaffected Yes
Filter outbound to a neighbour Yes No within an area Yes
Filter at an area or domain boundary Not applicable Yes — ABR filter-list, area range Yes — per neighbour
Filter what is redistributed in Yes Yes Yes
Suppress by summarisation Yes — per interface Yes — at ABR or ASBR Yes — aggregate-address
Block whole route classes No Yes — stub and NSSA area types No
Push a filter to the peer No No Yes — ORF

Why the link-state constraint is not negotiable

SPF computes a tree from a database. If two routers in an area hold different databases, they compute different trees, and two routers with different trees can forward a packet to each other indefinitely. The requirement that every router in an area sees every LSA is therefore the loop-prevention mechanism, not an implementation detail — and any command that appeared to remove an LSA from one router's database while leaving it in another's would be introducing precisely the failure mode the protocol exists to avoid.

That is why OSPF's filtering points are all at boundaries. An ABR sits between two areas and can decide what crosses; an ASBR sits between OSPF and something else and can decide what enters. Within an area there is no boundary and therefore no place to filter. Understanding that as an architectural property rather than a missing feature is what stops the search for a command that would do it.

! Proof that OSPF's distribute-list does not stop flooding
R2(config-router)# distribute-list prefix BLOCK-THIS in
!
! On R2, the route is gone from the RIB
R2# show ip route 10.7.0.0
% Network not in table
!
! But still present in R2's own database...
R2# show ip ospf database | include 10.7.0.0
10.7.0.0        3.3.3.3         412         0x80000004 0x00A2B1
!
! ...and on every other router in the area, unaffected
R5# show ip route 10.7.0.0 | include Known via
  Known via "ospf 1", distance 110, metric 30
! ^ R2 filtered itself, and nothing else.

What each filter object can match

Object Matches Used by Notes
Standard ACL Network address only All protocols Cannot match the mask; avoid
Extended ACL Network and mask as source and destination Distance-vector, OSPF distribute-list Awkward syntax; legacy
Prefix-list Prefix and length range All protocols The default choice
Route-map Anything, and can set attributes All protocols Required where a tag is set
AS-path access-list AS_PATH regular expression BGP only Via filter-list or match as-path
Community list BGP communities BGP only Standard and expanded forms
Route tag A 32-bit tag on the route All IGPs Cross-protocol; survives redistribution
Decide whether the requirement is visibility or reachability"The branch should not see the core's subnets" and "the branch must not be able to reach the core's subnets" sound similar and need opposite tools. The first is a summarisation problem and a summary satisfies it while keeping connectivity. The second is a security requirement, and a routing filter is a weak way to enforce it — an access list on the forwarding path is what actually prevents reachability. Establishing which one is being asked for prevents building a routing filter that neither reduces detail cleanly nor secures anything.
Prefix-lists over access-lists, everywhereA standard ACL matches the network address and ignores the mask, so permit 10.1.0.0 0.0.255.255 matches 10.1.0.0/16 and also 10.1.0.0/24 and 10.1.0.0/30. That ambiguity is a source of filters that pass more than intended. A prefix-list expresses the length explicitly and is readable, and there is no situation in modern configuration where an ACL is the better tool for route filtering. The one exception worth knowing is an extended ACL used with a distribute-list, where the source and destination fields express prefix and mask together — a legacy idiom that still appears in older configurations and is worth recognising rather than writing.
Ask "does this stop propagation" before configuringFor EIGRP and BGP the answer is yes and the filter does what it looks like. For OSPF inside an area the answer is no, and a filter that only affects the local RIB is almost never what the requirement asked for. Establishing which case you are in first avoids configuring something that appears to work on the router you are logged into.
Sub claimThe filtering model follows from what the protocol advertises — routes can be withheld, topology cannot — which is why OSPF's filtering points are all at boundaries and EIGRP's are everywhere.

How Do I Filter in a Distance-Vector Protocol?

What are the options in EIGRP?

A distribute-list applied inbound or outbound, globally for the address family or scoped to one interface, referencing a prefix-list, an ACL, or a route-map. In named mode these live under topology base for the process-wide form and under af-interface for the per-interface form. Beyond that, summarisation on an interface replaces a set of specifics with one prefix, which is filtering with a replacement, and an offset-list raises a route's metric without removing it, which is filtering by discouragement. A route-map distribute-list additionally allows matching on tag, which is how cross-protocol filtering is expressed.

A Deeper Dive into Distance-Vector Filtering

The four forms

! ===== Named mode: process-wide, both directions =====
ip prefix-list NO-LAB seq 5 deny 10.99.0.0/16 le 32
ip prefix-list NO-LAB seq 10 permit 0.0.0.0/0 le 32
!
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  topology base
   distribute-list prefix NO-LAB in
   distribute-list prefix NO-LAB out
  exit-af-topology
 exit-address-family
!
! ===== Named mode: scoped to one interface =====
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  af-interface GigabitEthernet0/2
   distribute-list prefix BRANCH-ONLY out
  exit-af-interface
 exit-address-family
!
! ===== Classic mode =====
router eigrp 100
 distribute-list prefix NO-LAB in GigabitEthernet0/1
 distribute-list prefix BRANCH-ONLY out GigabitEthernet0/2

Filtering by tag, which crosses protocols

A distribute-list referencing a route-map can match on a route tag, which is what makes a filter portable across a redistribution boundary. A route tagged when it entered EIGRP from OSPF can be excluded from an outbound advertisement toward a particular branch without listing a single prefix, and the filter stays correct as prefixes are added.

! Do not advertise OSPF-sourced routes toward this branch
route-map NO-OSPF-ROUTES deny 10
 match tag 110
route-map NO-OSPF-ROUTES permit 20
!
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  af-interface GigabitEthernet0/2
   distribute-list route-map NO-OSPF-ROUTES out
  exit-af-interface
 exit-address-family
!
! Verify from the branch side
R-BRANCH# show ip route eigrp | count ^D EX
Number of lines which match regexp = 0

Summarisation as filtering

Replacing a set of specifics with a summary removes them from the downstream view as thoroughly as a filter does, and adds a route that maintains reachability. Where the requirement is "the branch does not need to see every core subnet", a summary is usually better than a distribute-list: it is one line, it maintains connectivity, and it does not need editing when a new subnet appears inside the summarised range.

! One summary replaces every specific inside it, on this interface
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  af-interface GigabitEthernet0/2
   summary-address 10.1.0.0 255.255.0.0
  exit-af-interface
 exit-address-family
!
! And a default, where even the summary is more than needed
  af-interface GigabitEthernet0/3
   summary-address 0.0.0.0 0.0.0.0
  exit-af-interface
!
! A local discard route appears, which is expected
R1# show ip route 10.1.0.0 255.255.0.0 | include Null0
  * directly connected, via Null0

passive-interface, which is filtering at the adjacency layer

Before filtering routes, consider whether the adjacency should exist at all. A passive-interface stops the protocol sending hellos on an interface while still advertising that interface's subnet, which is the correct configuration for every interface facing hosts rather than routers. It removes an entire class of exposure — a rogue device forming an adjacency, a misconfigured neighbour injecting routes — and it does so without any prefix list.

The opt-in form, passive-interface default with explicit exceptions, is stronger still: interfaces peer only where somebody decided they should, and show ip eigrp interfaces becomes an accurate list of intended adjacencies rather than an accident of which subnets a network statement happened to cover.

! Opt-in adjacencies: nothing peers unless named
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  af-interface default
   passive-interface
  exit-af-interface
  af-interface GigabitEthernet0/1
   no passive-interface
  exit-af-interface
  network 10.0.0.0
 exit-address-family
!
! The interface list is now a statement of intent
R1# show ip eigrp interfaces
EIGRP-IPv4 VR(CORP) Address-Family Interfaces for AS(100)
Interface     Peers  Xmit Queue  Mean SRTT
Gi0/1           1      0/0          4
! ^ One interface, one peer. Anything else would be a finding.

Offset-list, which discourages rather than removes

! Raise the metric of matched routes instead of dropping them
access-list 10 permit 10.5.0.0 0.0.255.255
!
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  topology base
   offset-list 10 in 5120 GigabitEthernet0/1
  exit-af-topology
 exit-address-family
! ^ Still reachable via this interface, but only if nothing better
!   exists. Useful where a filter would black-hole.
Pitfall: an outbound filter that removes the only path Symptom: after adding a distribute-list to reduce what a branch router receives, the branch loses reachability to a destination that was not in the filtered range and appears unrelated. Cause: the filtered prefix was the branch's path to a next hop that other routes recursively depended on, or the filter removed a summary that covered more than the specifics being targeted. Confirm: on the branch, show ip route for the unreachable destination returns nothing, and the missing prefix appears in the filter's deny range. Fix: use a summary or a default route instead of a deny, so reachability is preserved while the detail is removed. An outbound deny should be reserved for prefixes that genuinely must not be reachable, not for prefixes that are merely unwanted detail.
Sub claimIn a distance-vector protocol, filtering and summarising achieve the same reduction and only one of them preserves reachability — which makes the summary the default choice and the deny the exception.

Why Can't I Filter Inside an OSPF Area?

What can OSPF filter, and where?

Five places, all of them boundaries. At an ABR, area filter-list controls which Type 3 summaries cross into or out of an area, and area range not-advertise suppresses a range of them. At an ASBR, summary-address not-advertise suppresses Type 5 externals, and a route-map on the redistribute statement controls what becomes an external in the first place. And the area types — stub, totally stubby, NSSA, totally NSSA — block whole classes of LSA at the area boundary. Inside an area, between routers in the same area, there is nothing.

A Deeper Dive into OSPF's Filtering Points

Type 3 filtering at an ABR

! Control which summaries enter area 2 from elsewhere
ip prefix-list AREA2-IN seq 5 permit 10.0.0.0/8 le 24
ip prefix-list AREA2-IN seq 10 deny 0.0.0.0/0 le 32
!
router ospf 1
 area 2 filter-list prefix AREA2-IN in
 ! 'in' = into area 2. 'out' = out of area 2 into others.
!
! Verify on a router inside area 2
R6# show ip route ospf | count ^O IA
Number of lines which match regexp = 12
! ^ Down from the full inter-area set. This is real filtering:
!   the Type 3 LSAs are not generated into the area at all.

Suppressing a range with area range

! Summarise on the way out of area 1
router ospf 1
 area 1 range 10.1.0.0 255.255.0.0
!
! Or suppress it entirely
router ospf 1
 area 1 range 10.1.99.0 255.255.255.0 not-advertise
! ^ No Type 3 is generated for anything inside this range.
!
! Confirm the summary and the suppression
R1# show ip ospf | begin Area 1
    Area 1
        Area ranges are
           10.1.0.0/16 Active(2) Advertise
           10.1.99.0/24 Passive DoNotAdvertise

Suppressing externals at an ASBR

! Summarise redistributed externals
router ospf 1
 summary-address 172.16.0.0 255.255.0.0
!
! Or suppress a range of them completely
router ospf 1
 summary-address 172.16.99.0 255.255.255.0 not-advertise
!
! Better still, never create them - filter the redistribution
route-map INTO-OSPF permit 10
 match ip address prefix-list SHARE-THESE
 set tag 90
!
router ospf 1
 redistribute eigrp 100 subnets route-map INTO-OSPF
! ^ The cleanest option: the LSA is never generated.

The direction keyword on area filter-list

The in and out keywords are relative to the area named in the command, not to the router. area 2 filter-list prefix X in filters Type 3 LSAs being generated into area 2 from every other area; out filters those being generated out of area 2 into the rest of the domain. Getting this backwards produces a filter that is syntactically valid, applies to the opposite set of prefixes, and appears to do nothing because the prefixes it names do not travel in that direction.

Both directions can be configured on the same area, and on a router that is an ABR for several areas each area needs its own statement. A filter applied to one area does not affect what crosses at another ABR, so an area with two ABRs needs the identical filter on both — the same partial-deployment problem that affects redistribution tags.

Pitfall: area filter-list applied on only one of two ABRs Symptom: a filter intended to keep a set of prefixes out of an area works when traffic and LSAs flow through one ABR and stops working after a failure moves them to the other, so the prefixes appear intermittently and correlate with nothing obvious. Cause: the filter was configured on one ABR only; the second continues generating the Type 3 LSAs into the area normally. Confirm: show ip ospf database summary on a router inside the area shows the prefixes with the second ABR as advertising router; show running-config | include filter-list on both ABRs shows only one. Fix: apply the identical filter-list on every ABR serving the area, and audit for it whenever an ABR is added or rebuilt.

Area types, which block classes rather than prefixes

Area type Blocks Configured on Effect on the area's database
Stub Type 4 and Type 5 Every router in the area No externals; a default arrives instead
Totally stubby Type 3, 4 and 5 no-summary on the ABR Only intra-area plus a default
NSSA Type 4 and Type 5 Every router in the area No external imports; Type 7 permitted locally
Totally NSSA Type 3, 4 and 5 no-summary on the ABR Smallest database that still allows a local ASBR
! The largest database reduction available, in two commands
! On the ABR:
router ospf 1
 area 2 stub no-summary
!
! On every internal router in area 2:
router ospf 1
 area 2 stub
!
! Measure the effect
R6# show ip ospf database database-summary | include Total|Summary
  Summary Net   1        0        0
  Total         6        0        0
! ^ One Type 3, the default. Down from hundreds.

What distribute-list in actually does

It prevents routes from being installed in the local routing table. The LSAs are received, stored in the local LSDB, flooded onward normally, and used by SPF; only the resulting RIB entry is suppressed. There are legitimate uses — preventing a specific router from using a path while leaving the rest of the area unaffected — and they are narrow. Using it as a general filter produces a router with a routing table that disagrees with its own database and with every neighbour.

! Legitimate use: this router specifically must not use this path
ip prefix-list NOT-VIA-ME seq 5 deny 10.7.0.0/16
ip prefix-list NOT-VIA-ME seq 10 permit 0.0.0.0/0 le 32
!
router ospf 1
 distribute-list prefix NOT-VIA-ME in
!
! The consequence, stated plainly
R2# show ip route 10.7.0.0
% Network not in table
R2# show ip ospf database | include 10.7.0.0
10.7.0.0   3.3.3.3   412   0x80000004 0x00A2B1
! ^ R2 cannot reach it. Every other router in the area can.
!   If that is not what you wanted, this is the wrong command.
Pitfall: using distribute-list in to filter an OSPF area Symptom: a filter is applied to stop a set of prefixes propagating into part of the network; the router it was applied to no longer has them, and every other router in the area still does. Traffic that transits the filtered router is black-holed while traffic taking any other path works. Cause: under OSPF, distribute-list in filters RIB installation only. LSA flooding, and therefore every other router's view, is unaffected. Confirm: show ip route <prefix> is empty on the filtered router while show ip ospf database contains it there and everywhere. Fix: filter at a boundary instead — area filter-list at an ABR, a route-map on redistribution at an ASBR, or an area type that blocks the class. If the requirement genuinely is per-router, understand that you are creating a router whose forwarding disagrees with the area.
Sub claimOSPF gives you five filtering points and all of them are boundaries, because within an area the identical-database requirement is the loop prevention — which makes "filter inside an area" a request the protocol cannot grant.

How Do I Filter BGP and Redistributed Static Routes?

What is different about these two?

BGP is the most filterable of the protocols: four mechanisms per neighbour per direction per address family, plus ORF to push a filter to the peer, plus the structural fact that only the best path is ever advertised. Static routes have no protocol to filter at all — the filtering point is the redistribution that injects them into whatever protocol is going to carry them, which makes a route-map on the redistribute static statement the only control available and therefore the one that matters.

A Deeper Dive into BGP and Static Filtering

Why BGP is the easiest of the three

BGP was designed on the assumption that the operator does not trust the peer and the peer does not trust the operator, so every advertisement is subject to policy in both directions by default. That produces the richest filtering model of the three protocol families and one structural bonus: because BGP advertises only its best path, an inbound filter that rejects a path also removes it from consideration for everything downstream, and an outbound filter is the last word on what leaves.

The cost of that richness is that four mechanisms can apply in one direction and all of them must permit a prefix. A prefix rejected by a prefix-list never reaches the route-map, so reading the route-map alone will never explain its absence — which is why the recommendation elsewhere is one mechanism per direction, with everything else referenced from inside it.

BGP, briefly, in this context

! Four mechanisms, per neighbour, per direction, per family.
! All configured ones must permit a prefix for it to pass.
router bgp 65000
 address-family ipv4 unicast
  neighbor 192.0.2.2 prefix-list CUST-A-PFX in
  neighbor 192.0.2.2 filter-list 10 in
  neighbor 192.0.2.2 route-map CUST-A-IN in
  neighbor 192.0.2.6 route-map TRANSIT-OUT out
 exit-address-family
!
! And the change takes effect only after a refresh
R1# clear ip bgp 192.0.2.2 soft
!
! Verify by counting, on both sides of the policy
R1# show ip bgp neighbors 192.0.2.2 routes | include Total
R1# show ip bgp neighbors 192.0.2.6 advertised-routes | include Total

Static routes: tag at creation, filter at redistribution

A router accumulates static routes for several unrelated purposes — a Null0 discard supporting a summary, a management route, a temporary route added during an incident, a genuine reachability entry that should propagate. redistribute static with no filter carries all of them. Tagging each static at the moment it is created, with a value describing its purpose, turns the redistribution filter into a one-line match that stays correct as statics come and go.

! Tag statics by purpose, at creation
ip route 10.9.0.0 255.255.0.0 10.0.0.9 tag 500     ! propagate
ip route 172.16.0.0 255.240.0.0 Null0 tag 900       ! discard, never propagate
ip route 192.168.99.0 255.255.255.0 10.0.0.1 tag 800 ! management only
!
! One filter, correct for every static ever added
route-map STATIC-OUT permit 10
 match tag 500
 set tag 1
! implicit deny excludes 900 and 800 automatically
!
router ospf 1
 redistribute static subnets route-map STATIC-OUT
!
router eigrp CORP
 address-family ipv4 unicast autonomous-system 100
  topology base
   redistribute static metric 1000000 100 255 1 1500 route-map STATIC-OUT
  exit-af-topology
 exit-address-family

Filtering connected interfaces

redistribute connected has the same problem in a sharper form: every interface on the router, including management interfaces, out-of-band links, and loopbacks used for protocol identifiers, is carried unless filtered. A prefix-list naming the ranges that should propagate is the minimum, and matching on interface is available where the addressing does not partition cleanly.

! By prefix range - the usual approach
ip prefix-list SHARE-CONN seq 5 permit 10.1.0.0/16 le 30
!
route-map CONN-OUT permit 10
 match ip address prefix-list SHARE-CONN
!
! Or by interface, where addressing does not partition cleanly
route-map CONN-OUT-2 permit 10
 match interface GigabitEthernet0/1 GigabitEthernet0/2
!
router ospf 1
 redistribute connected subnets route-map CONN-OUT
!
! Verify the management interface did not propagate
R5# show ip route 192.168.99.0
% Network not in table

Choosing the filtering point

Requirement Best filtering point Why
A branch should not see core detail Summary or default on the branch-facing interface Reduces detail while preserving reachability
A prefix must not be reachable from a domain Deny at the redistribution or the area boundary Stops it existing there at all
Externals must not enter an area Stub or NSSA area type Blocks the class, not a list
A specific Type 3 must not cross area filter-list at the ABR The only Type 3 control point
Only some statics should propagate Tag at creation, match at redistribution Stays correct as statics change
A peer should stop sending prefixes BGP inbound filter, or ORF ORF also saves the transfer
Redistributed routes must not return Tag on export, deny on import Prefix-independent
Record the expected route count before applying a filterThe count of routes on the far side of the filter, taken before and after, is what distinguishes "the filter worked" from "the filter removed rather more than intended". It is two commands, it works identically for every protocol, and it catches the missing-trailing-permit case immediately — a count of zero is unambiguous in a way that a successful ping to one destination is not.
Filter as close to the source as possibleA prefix that is never created causes no problems anywhere. Filtering at the redistribution point stops the route existing in the destination protocol at all; filtering three routers later leaves it present, flooded, and consuming resources everywhere in between. Where both are possible, the earlier point is always the better one.
Sub claimStatic routes have no protocol-level filtering, so the redistribution route-map is the only control — which makes tagging statics at creation the difference between a filter that stays correct and one that needs editing every time somebody adds a route.

Which Filtering Mistakes Cause Black Holes?

What goes wrong?

Six things. An OSPF distribute-list in used as a propagation filter produces one router that disagrees with its area. An outbound deny that removes the only path to a destination black-holes it rather than merely hiding it. A prefix-list with an inverted ge or le matches nothing or everything. A filter applied without the implicit-deny in mind rejects far more than intended. A BGP filter applied without a soft reset governs only new prefixes. And a filter that removes a next hop breaks routes that recursively depended on it, which is invisible in the filter itself.

A Deeper Dive into the Failure Catalogue

Auditing filters that outlived their requirement

Filters accumulate. A prefix-list added for a migration that finished, a distribute-list from an incident three years ago, an area filter-list nobody can attribute — each was correct once and each now constrains the network for reasons nobody can state. The audit is mechanical: list every filter object, find where each is referenced, and for any with no reference remove it. For the ones that are referenced, the harder question is whether the requirement still exists, which only documentation can answer.

! Every filter object defined on the device
R1# show running-config | include ^ip prefix-list|^route-map|^ip as-path
!
! Which are actually referenced anywhere?
R1# show ip prefix-list detail | include ^ip prefix-list|refcount
ip prefix-list OLD-MIGRATION:
   count: 4, range entries: 0, sequences: 5 - 20, refcount: 0
! ^ refcount 0 = defined and used nowhere. Safe to remove.
!
! Where every filter is applied, by protocol
R1# show running-config | include distribute-list|filter-list|prefix-list .* in|out
R1# show running-config | include area .* filter-list|summary-address|area .* range

The recursive next-hop failure

A route whose next hop is not directly connected requires a second lookup to resolve. Filtering the prefix that provides that resolution removes the first route as well, even though it was never mentioned in the filter. This is most common with BGP next hops learned from an IGP, and with static routes pointing at addresses several hops away.

! The filter removes 10.0.0.0/24 - apparently unrelated
ip prefix-list TIDY seq 5 deny 10.0.0.0/24
ip prefix-list TIDY seq 10 permit 0.0.0.0/0 le 32
!
! But a BGP path's next hop lives in that range
R3# show ip bgp 203.0.113.0/24 | include from
    10.0.0.1 (inaccessible) from 10.0.0.9 (10.0.0.9)
! ^ The BGP prefix is now unusable because its next hop cannot
!   be resolved. Nothing in the filter mentions 203.0.113.0.
!
! Check what depends on a prefix before filtering it
R3# show ip bgp | include 10.0.0.1
R3# show ip route 10.0.0.1

The implicit deny, again

! WRONG - a prefix-list with only deny entries permits nothing
ip prefix-list BLOCK-LAB seq 5 deny 10.99.0.0/16 le 32
!
R2# show ip route eigrp | count ^D
Number of lines which match regexp = 0
! ^ Everything filtered. The implicit deny caught the rest.
!
! RIGHT
ip prefix-list BLOCK-LAB seq 5 deny 10.99.0.0/16 le 32
ip prefix-list BLOCK-LAB seq 10 permit 0.0.0.0/0 le 32
!
! Same rule for route-maps used as distribute-lists
route-map FILTER deny 10
 match tag 110
route-map FILTER permit 20
! ^ Without clause 20, nothing is advertised at all.

Writing a filter that can be reviewed

A filter's correctness is judged by somebody who was not there when it was written, usually during an incident. Three habits make that possible. Name the object after what it permits rather than where it is used, so CUSTOMER-BLOCKS survives being applied somewhere new while GI0-1-IN does not. Number entries in tens so an insertion does not require renumbering the whole list. And write the trailing permit or deny explicitly even where the implicit one would do the same thing, because an explicit final line is evidence that the author considered the case.

The fourth habit is a comment in configuration management naming the requirement the filter implements. A prefix-list with no stated purpose is a prefix-list nobody will remove even when the requirement has gone, which is how a network accumulates filters that nobody can justify and nobody dares delete.

! Named for content, numbered in tens, explicit final line
ip prefix-list CUSTOMER-BLOCKS seq 10 permit 203.0.113.0/24
ip prefix-list CUSTOMER-BLOCKS seq 20 permit 198.51.100.0/22 le 24
ip prefix-list CUSTOMER-BLOCKS seq 30 deny 0.0.0.0/0 le 32
! ^ The deny is redundant and states the intent anyway.
!
! Find every place an object is used, before changing it
R1# show running-config | include CUSTOMER-BLOCKS
 neighbor 192.0.2.2 prefix-list CUSTOMER-BLOCKS in
 match ip address prefix-list CUSTOMER-BLOCKS
!
! And read it back with its entry counts
R1# show ip prefix-list detail CUSTOMER-BLOCKS
ip prefix-list CUSTOMER-BLOCKS:
   count: 3, range entries: 1, sequences: 10 - 30, refcount: 3
   seq 10 permit 203.0.113.0/24 (hit count: 1, refcount: 1)
! ^ refcount 3 means three places reference this list. Changing it
!   affects all three.

Verification per protocol

! EIGRP: did the route stop being advertised?
R1# show ip eigrp topology 10.99.0.0/16
! (absent = the inbound filter worked)
R-NEIGH# show ip route 10.99.0.0
! (absent = the outbound filter worked)
!
! OSPF: is the LSA gone, or just the RIB entry?
R2# show ip route 10.7.0.0        ! RIB
R2# show ip ospf database | include 10.7.0.0   ! LSDB
! Absent from BOTH = a real boundary filter.
! Absent from the RIB only = distribute-list in. Probably wrong.
!
! BGP: compare pre-policy and post-policy
R1# show ip bgp neighbors 192.0.2.2 received-routes | include Total
R1# show ip bgp neighbors 192.0.2.2 routes | include Total
!
! Any protocol: did anything become unreachable that should not have?
R5# ping 10.5.0.1 source Loopback0
R5# traceroute 10.5.0.1
Mistake Symptom Confirming command Fix
OSPF distribute-list in as a filter One router disagrees with its area RIB empty, LSDB populated Filter at an ABR, ASBR, or by area type
Outbound deny removes the only path Black hole for that destination show ip route empty downstream Summary or default instead of deny
Missing trailing permit Everything filtered Route count drops to zero Add permit 0.0.0.0/0 le 32
Inverted ge/le Matches nothing or everything show ip prefix-list Both must exceed the stated length
Recursive next hop filtered Unrelated prefixes become unusable BGP path shows inaccessible Permit the next-hop range explicitly
BGP filter without a refresh Applies only to new prefixes Prefix count unchanged clear ip bgp X soft
Standard ACL instead of prefix-list Matches more than intended Compare against the mask Use a prefix-list
Filtering is not a security controlA prefix removed from a routing table is not unreachable — it is merely unrouted from that vantage point, and a host with a static route, a default route pointing the right way, or a path via another router reaches it anyway. Where the requirement is that traffic must not pass, the control belongs in the forwarding path as an access list or a firewall rule. Routing filters reduce what a router knows; they do not enforce what it will carry.
Exam contextRoute filtering is a P0 area of the CCIE Enterprise Infrastructure blueprint and is examined by outcome: a task states which prefixes must be visible where, and the expected answer uses the mechanism appropriate to the protocol involved. The reliably tested item is the OSPF case — a task that appears to want a distribute-list is usually testing whether you know it filters only the local RIB, and the intended answer is an area filter-list, an area type, or a redistribution route-map. ENARSI 300-410 covers the same material with more emphasis on prefix-list syntax and less on the OSPF architectural constraint.
Sub claimEvery black hole in this catalogue comes from removing a route rather than replacing it — which is why a summary or a default is the safer instrument wherever the requirement is to reduce detail rather than to deny reachability.

Conclusion

Filtering is three different problems because the protocols advertise three different things. A distance-vector protocol advertises routes, so withholding one removes it from the downstream view completely and filtering is available everywhere. A path-vector protocol advertises paths per neighbour and was designed around policy, so filtering is a first-class feature with four mechanisms and a way to push your filter to the peer. A link-state protocol advertises topology that every router in an area must hold identically, so there is no place inside an area to filter and all the control lives at boundaries.

The OSPF case deserves the emphasis because the command that looks like a filter is not one. distribute-list in stops the local router installing a route while the LSA continues to flood everywhere, including to that router's own database. Used deliberately, on one router, for a narrow reason, that is a legitimate tool. Used as a general filter, it produces a router whose forwarding disagrees with its area, which is a black hole for anything that transits it and is invisible from every other router.

The practical rule that covers most requirements is to reduce rather than remove. A branch that does not need core detail wants a summary or a default, not a deny — both remove the detail and only one preserves reachability. Where a deny is genuinely required, filter as close to the source as possible so the route never exists downstream, and check what depends on the prefix before removing it, because a recursive next hop is the dependency nobody looks for and the one that turns a tidy-up into an outage.

Reference Notes

  1. RFC 2328, Section 13 — the flooding procedure, which requires every router in an area to receive and store every LSA originated within it.
  2. RFC 2328, Section 16 — the SPF calculation operates on the link-state database, so a router with a different database computes a different tree.
  3. RFC 2328, Section 12.4.3 — summary-LSAs are originated by area border routers, which is why the ABR is the only Type 3 filtering point.
  4. RFC 2328, Section 3.6 — stub areas, in which Type 5 LSAs are not flooded, blocking a whole class rather than individual prefixes.
  5. RFC 3101 — the NSSA option and Type 7 LSAs, permitting a local ASBR within an otherwise stub-like area.
  6. RFC 7868, Section 4 — EIGRP's reliable update mechanism advertises routes rather than topology, which permits filtering at any interface.
  7. Cisco IOS-XE IP Routing Configuration Guide — distribute-list in under OSPF filters routes from installation in the routing table and does not affect LSA flooding.
  8. Cisco IOS-XE IP Routing Configuration Guide — area filter-list prefix filters Type 3 summary LSAs into or out of an area at an ABR.
  9. Cisco IOS-XE IP Routing Configuration Guide — area range not-advertise and summary-address not-advertise suppress Type 3 and Type 5 LSAs respectively.
  10. Cisco IOS-XE EIGRP Configuration Guide — distribute-list under topology base for process-wide filtering and under af-interface for per-interface filtering.
  11. Cisco IOS-XE IP Routing Configuration Guide — prefix-list ge and le values must both exceed the specified prefix length.
  12. Cisco IOS-XE IP Routing Configuration Guide — match interface and match tag as route-map conditions for filtering connected and static redistribution.