Building filters with bgpq4
The standard tool is bgpq4, the maintained successor to bgpq3. Give it a set (or an ASN) and it:
- expands the as-set to ASNs (with IRRd
!iqueries), - collects the route or route6 objects those ASNs originate (
!gand!6), - prints a ready-to-paste prefix-list or as-path filter for your platform.
It queries whois.radb.net by default, which mirrors most IRRs. Use -h to pick another server and -S to restrict which sources are trusted.
A filter pipeline
- Know each neighbour's set: from the contract, their aut-num export, or PeeringDB.
- Generate per-session filters on a schedule (daily or every few hours) with bgpq4 or a wrapper.
- Sanity-check before pushing. An empty result is a deny-all that would cut the customer off. A list that shrank by 90% overnight, or grew by 100,000 entries, should stop the pipeline and alert a human.
- Push and apply with your automation (Ansible, Salt, vendor APIs), and keep the generated file out of hand-edited config.
- Layer protections: the prefix-list says which prefixes; RPKI (next lesson) checks who may originate them;
maximum-prefixcaps how many.
# IPv4 prefix-list from everything AS64501's customer cone has registered
bgpq4 -4 -l AS64501-IN AS64501:AS-CUSTOMERS
# IPv6, also allowing more-specifics down to /48
bgpq4 -6 -R 48 -l AS64501-IN-V6 AS64501:AS-CUSTOMERS
# Only trust objects from these IRR sources
bgpq4 -S RIPE,ARIN,APNIC -4 -l AS64501-IN AS64501:AS-CUSTOMERS
# Output for other platforms: -J Junos, -b BIRD, -e Arista EOS
bgpq4 -J -4 -l AS64501-IN AS64501:AS-CUSTOMERS- Line 2:
-4IPv4,-lthe name of the generated list, then the set (or a single ASN) to expand. - Line 5:
-R 48also permits more-specifics of each registered prefix, down to /48. Use it for customers that deaggregate for traffic engineering. - Line 8:
-Slimits and orders the IRR sources. Leaving out non-authoritative ones such as RADB's own objects reduces the risk from proxy registrations. - Line 11: The default output is Cisco IOS syntax, which FRR also accepts. Other flags target Junos, BIRD, EOS and more.
$ bgpq4 -h irrd -4 -l AS64501-IN AS64501:AS-CUSTOMERS
no ip prefix-list AS64501-IN
ip prefix-list AS64501-IN permit 192.0.2.0/25
ip prefix-list AS64501-IN permit 192.0.2.128/25
ip prefix-list AS64501-IN permit 203.0.113.0/24
$ bgpq4 -h irrd -6 -R 48 -l AS64501-IN-V6 AS64501:AS-CUSTOMERS
no ipv6 prefix-list AS64501-IN-V6
ipv6 prefix-list AS64501-IN-V6 permit 2001:db8:501::/48
$ bgpq4 -h irrd -4 -l EMPTY-IN AS-DOES-NOT-EXIST
no ip prefix-list EMPTY-IN
! generated prefix-list EMPTY-IN is empty
ip prefix-list EMPTY-IN deny 0.0.0.0/0- Line 2: The list is deleted and rebuilt, so removed prefixes disappear. Apply it as one change, or the session briefly has no filter.
- Lines 3–5: One exact-match line per route object, sorted. AS64501's own /24 plus its two customers' /25s.
- Lines 7–8: The IPv6 list.
-R 48would addle 48to anything shorter than /48; this route6 is already a /48. - Lines 10–12: An empty expansion becomes deny-all. Correct for safety, but your automation must catch it before it cuts a customer off.
! Generated by bgpq4 on a schedule: never edit by hand
no ip prefix-list AS64501-IN
ip prefix-list AS64501-IN permit 192.0.2.0/25
ip prefix-list AS64501-IN permit 192.0.2.128/25
ip prefix-list AS64501-IN permit 203.0.113.0/24
!
route-map AS64501-IN permit 10
match ip address prefix-list AS64501-IN
set local-preference 200
exit
!
router bgp 64500
bgp router-id 10.255.0.1
neighbor 10.0.1.1 remote-as 64501
neighbor 10.0.1.1 description CUSTOMER-AS64501
!
address-family ipv4 unicast
neighbor 10.0.1.1 route-map AS64501-IN in
neighbor 10.0.1.1 maximum-prefix 20
exit-address-family
exit
!- Lines 1–5: Paste the generated list as-is, and keep it in its own file or template managed by automation.
- Lines 7–10: Permit only what's in the list, and mark customer routes with a high LOCAL_PREF. Everything else hits the route-map's implicit deny.
- Lines 14–15: The customer session, as in the BGP lesson.
- Line 18: Attach the filter inbound.
- Line 19: A backstop in case the filter is ever too permissive, e.g. after set bloat slips through.
$ bgpq4 -h irrd -4 -l AS64500-IN AS64500; echo "exit code $?"
ERROR:Invalid AS number: 64500
no ip prefix-list AS64500-IN
! generated prefix-list AS64500-IN is empty
ip prefix-list AS64500-IN deny 0.0.0.0/0
exit code 0- Line 2: bgpq4 rejects reserved and documentation ASNs given directly. (It expanded the as-sets above because members inside a set aren't checked the same way.)
- Lines 3–5: It still prints a complete, deny-all prefix list…
- Line 6: …and exits 0. Automation that only checks the exit code would push this and cut the customer off. Check for
ERRORand for empty lists.
Check your understanding
Your nightly job runs bgpq4 for a customer and gets the empty-list output (deny 0.0.0.0/0). What should the pipeline do?
- Push it: the IRR is the source of truth
- Keep the previous filter, alert a human, and contact the customer
- Replace the filter with permit-any until it's fixed
- Shut down the BGP session