Policy & Filters
Policy & Filters
Routing without policy is a demo; routing with policy is operations. This chapter covers prefix filters, distribute ideas, route-maps as a pattern, and loop-prevention instincts using FRR—still free and vendor-agnostic.
Learning goals
By the end of this chapter you can:
- Write prefix-lists that match intended space only
- Apply import/export filters on BGP neighbors
- Use route-map style logic (match → set → permit/deny)
- Predict leaks and loops from redistribution mistakes
- Build a lab that rejects unauthorized prefixes
Why policy exists
| Goal | Mechanism ideas |
|---|---|
| Do not accept bogons / your own space from customers | Inbound prefix filter |
| Do not advertise internal-only nets to Internet | Outbound filter |
| Prefer one uplink | local-pref on import |
| De-prefer backup path | AS-path prepend on export |
| Redistribute without feedback loops | Tags, filters, distance |
Prefix lists (FRR)
ip prefix-list OWN-NETS seq 10 permit 192.168.1.0/24
ip prefix-list OWN-NETS seq 20 permit 1.1.1.1/32
ip prefix-list OWN-NETS seq 30 deny any
ip prefix-list CUST-ALLOW seq 10 permit 198.51.100.0/24
ip prefix-list CUST-ALLOW seq 20 deny any
Order matters: first match wins. Always know your implicit/default at the end.
Route-maps as idea
Regardless of vendor syntax, the pattern is:
if match prefix-list X:
set local-preference 200
permit
else deny
FRR example:
route-map FROM-CUST permit 10
match ip address prefix-list CUST-ALLOW
set local-preference 200
route-map FROM-CUST deny 99
!
route-map TO-CUST permit 10
match ip address prefix-list OWN-NETS
Attach:
router bgp 65002
neighbor 10.0.0.1 route-map FROM-CUST in
neighbor 10.0.0.1 route-map TO-CUST out
Local-pref steer drill
Two ISPs: isp1 and isp2; customer prefers isp1 for inbound to customer… actually:
- Local pref (on customer) influences outbound exit from customer AS
- AS prepend / MED / communities influence how others send inbound
Outbound preference (customer)
route-map PREFER-ISP1 permit 10
set local-preference 300
route-map PREFER-ISP2 permit 10
set local-preference 100
!
neighbor <isp1> route-map PREFER-ISP1 in
neighbor <isp2> route-map PREFER-ISP2 in
Predict: traffic leaves via isp1 when both paths exist.
vtysh -c 'show ip route 0.0.0.0'
vtysh -c 'show bgp ipv4 unicast'Redistribution loop awareness
Redistributing OSPF ↔︎ BGP (or static ↔︎ OSPF) without filters can:
- Re-inject prefixes with changed metrics
- Create loops or suboptimal paths
- Explode tables
Rules of thumb:
- Redistribute on purpose, on as few points as possible
- Tag routes; filter on tags
- Never blindly mutual redistribute two IGPs
- Prefer BGP for policy domains, IGP for underlay topology
Example static→OSPF with filter (sketch)
ip prefix-list STATICS seq 5 permit 192.168.9.0/24
route-map REDIST-STATIC permit 10
match ip address prefix-list STATICS
!
router ospf
redistribute static route-map REDIST-STATIC
ACL-style packet filters vs routing policy
Do not confuse:
| Routing policy | Packet filter |
|---|---|
| Which routes enter RIB | Which packets pass |
| BGP/OSPF route-maps | nftables/iptables/ACLs |
| Control plane | Data plane |
Both appear in hardening. A permit route does not mean packets are allowed through a firewall mid-path.
Distribute-list / filter-list ideas
Older or alternate forms filter by ACL or AS-path lists:
bgp as-path access-list 1 permit _65001$
neighbor x filter-list 1 in
Same intent: accept only what policy allows.
Failure drills
Drill 1 — over-broad permit any
Export permit any to a lab “ISP.”
Observe: internal lab nets leave the AS.
Fix: prefix-list OWN only.
Harden: default-deny export mindset.
Drill 2 — accidental deny all
Route-map deny first line matches everything.
Symptom: Established but zero prefixes.
Debug: show bgp neighbors ... routes / policy counters if available; simplify map.
Drill 3 — next-hop-self missing (iBGP)
Learned eBGP route reflected iBGP with remote next hop unreachable.
Symptom: BGP has path; FIB lacks usable route.
Fix: next-hop-self or IGP reachability to next hop.
verify.sh policy checks
#!/usr/bin/env bash
set -euo pipefail
fail() { echo "FAIL: $*" >&2; exit 1; }
docker exec clab-bgp-ebgp-r2 vtysh -c 'show bgp ipv4 unicast' | grep -q '192.168.1.0/24' \
|| fail "missing customer prefix"
if docker exec clab-bgp-ebgp-r2 vtysh -c 'show bgp ipv4 unicast' | grep -q '203.0.113.0/24'; then
fail "hijack prefix should be filtered"
fi
echo OKPolicy design worksheet
Before applying:
## Neighbor: r1-r2 eBGP
Import accept: ...
Import deny: ...
Export advertise: ...
Export never: ...
Preference intent: ...
Failure mode if map wrong: ...Summary
- Policy decides which routes and with which attributes
- Prefix-lists + route-maps are the portable pattern
- Default-deny posture on Internet edges
- Redistribution needs filters/tags or it will bite
- Verify with BGP table and negative tests for rejected prefixes
Next part: ops & automation—observability, lab-as-code automation, and a capstone outline that pulls the book together.