Remotely triggered blackholing
A Distributed Denial of Service (DDoS) attack against one address can fill your transit links, taking everything else down with it. Remotely triggered blackhole (RTBH) asks your providers to drop traffic to that one address at their edge, before it reaches you. The attacked host goes offline, but the rest of your network survives. It's a blunt tool, but often the only one that works fast.
The mechanism is a well-known community, BLACKHOLE (65535:666, RFC 7999):
- You announce the attacked address as a /32, tagged BLACKHOLE.
- Your provider accepts host routes only when they carry BLACKHOLE (and only inside your registered space), sets their next hop to a discard address that routes to nowhere (Null0), and adds NO_EXPORT so it never leaves their network.
- Their routers now forward that /32 into the void. Everything else in your /24 is unaffected.
On R1 that takes three pieces: a route-map that tags the /32, a network statement for it, and an extra rule in the export map that allows /32s from our space only if they carry the BLACKHOLE community. The lab's first attempt got two things wrong, and both are worth seeing.
Mistake 1: adding NO_EXPORT yourself
The first RTBH map added both blackhole and no-export. The result: Not advertised to any peer. NO_EXPORT means "don't send this to any eBGP neighbor", and your upstream is an eBGP neighbor. RFC 7999 has the receiving network add NO_EXPORT; the customer sends only BLACKHOLE.
Mistake 2: a community-list that never matches
With NO_EXPORT removed, the /32 still wasn't advertised. The export rule matched a community-list with the regex 65535:666, and VyOS community-lists are expanded lists: FRR matches the regex against the community's text form. For 65535:666, that text is the word blackhole. The regex never matched, so the route fell through to the export map's final deny. Matching blackhole fixed it. When a community-list seems to match nothing, show bgp ipv4 community-list NAME tells you immediately.
Working
R1 now advertises the /32 alongside the /24. upstream1 receives it, sets the next hop to its discard address 192.0.2.1, adds NO_EXPORT, and installs it as a blackhole. The internet never even sees the /32. From the internet, the attacked host stops answering, the rest of R1's network still does, and traceroute dies at the very first hop, inside the provider.
(One lab detail on the provider side: FRR wouldn't install an eBGP route whose next hop had been rewritten to a non-connected discard address, the same connected-check rule as in the BGP on loopbacks lesson. The lab's upstreams therefore use disable-connected-check on the customer session. Real providers typically do RTBH on internal trigger routers or with platform features, so this is their problem, not yours.)
To end the blackhole, remove the network statement. Do it as soon as the attack stops: RTBH completes the attacker's job for that one address.
frr defaults traditional
hostname upstream1
!
interface eth0
ip address 203.0.113.0/31
!
interface eth1
ip address 203.0.113.4/31
!
! RTBH: anything tagged BLACKHOLE is sent to this discard next hop
ip route 192.0.2.1/32 Null0
!
ip prefix-list CUSTOMER-PREFIXES seq 10 permit 198.51.100.0/24
ip prefix-list CUSTOMER-BLACKHOLES seq 10 permit 198.51.100.0/24 ge 32
!
bgp community-list standard BLACKHOLE seq 10 permit blackhole
!
route-map CUSTOMER-IN permit 10
match ip address prefix-list CUSTOMER-BLACKHOLES
match community BLACKHOLE
set ip next-hop 192.0.2.1
set community no-export additive
exit
!
route-map CUSTOMER-IN permit 20
match ip address prefix-list CUSTOMER-PREFIXES
set local-preference 200
exit
!
router bgp 64496
bgp router-id 203.0.113.0
no bgp ebgp-requires-policy
neighbor 203.0.113.1 remote-as 64500
neighbor 203.0.113.1 description CUSTOMER-R1
neighbor 203.0.113.1 disable-connected-check
neighbor 203.0.113.5 remote-as 64511
neighbor 203.0.113.5 description PEER-INTERNET
!
address-family ipv4 unicast
neighbor 203.0.113.1 route-map CUSTOMER-IN in
neighbor 203.0.113.1 default-originate
exit-address-family
exit
!- Line 11: The discard address: routed to nowhere.
- Line 13: Customer's aggregate, exact…
- Line 14: …and host routes inside it, only for blackholing.
- Lines 18–23: A tagged /32 gets the discard next hop and NO_EXPORT.
- Lines 25–28: The normal customer route, with the customer local preference.
- Line 35: Lab-specific: lets the rewritten, non-connected next hop be installed.
set policy community-list BLACKHOLE rule 10 action 'permit'
set policy community-list BLACKHOLE rule 10 regex '65535:666'
set policy prefix-list OUR-HOSTS rule 10 action 'permit'
set policy prefix-list OUR-HOSTS rule 10 prefix '198.51.100.0/24'
set policy prefix-list OUR-HOSTS rule 10 ge '32'
set policy route-map TRANSIT-OUT rule 20 action 'permit'
set policy route-map TRANSIT-OUT rule 20 match ip address prefix-list 'OUR-HOSTS'
set policy route-map TRANSIT-OUT rule 20 match community community-list 'BLACKHOLE'
set policy route-map RTBH rule 10 action 'permit'
set policy route-map RTBH rule 10 set community add '65535:666'
set policy route-map RTBH rule 10 set community add 'no-export'
set protocols bgp address-family ipv4-unicast network 198.51.100.10/32 route-map 'RTBH'- Lines 1–2: Mistake 2: a regex on the number, but FRR matches the text form.
- Lines 3–5: Our space, /32s only.
- Lines 6–8: Export /32s only when tagged BLACKHOLE.
- Line 10: BLACKHOLE (65535:666).
- Line 11: Mistake 1: NO_EXPORT stops it reaching the upstream.
- Line 12: Announce the attacked host.
vyos@R1:~$ show ip bgp neighbors 203.0.113.0 advertised-routes
BGP table version is 12, local router ID is 198.51.100.1, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/24 0.0.0.0 0 0 i
Total number of prefixes 1, total number of paths 1
vyos@R1:~$ show bgp ipv4 198.51.100.10/32
BGP routing table entry for 198.51.100.10/32, version 12
Paths: (1 available, best #1, table default, inform peer to blackhole prefix)
Not advertised to any peer
Local
0.0.0.0 from 0.0.0.0 (198.51.100.1)
Origin IGP, metric 0, weight 32768, valid, sourced, local, best (First path received)
Community: blackhole no-export
Last update: Sat Oct 17 13:38:29 2026
Characteristics:
BGPID: 198.51.100.1- Line 11: Only the /24 goes to the upstream.
- Line 17: Not advertised to any eBGP neighbour…
- Line 21: …because of no-export.
delete policy route-map RTBH rule 10 set community add 'no-export'- Line 1: The provider adds NO_EXPORT itself.
vyos@R1:~$ show bgp ipv4 community-list BLACKHOLE
vyos@R1:~$ vtysh -c 'show bgp community-list'
Named Community expanded list BLACKHOLE
permit 65535:666- Line 1: Nothing matches.
- Lines 3–4: An expanded list, regex 65535:666.
set policy community-list BLACKHOLE rule 10 regex 'blackhole'- Line 1: FRR writes 65535:666 as
blackhole.
vyos@R1:~$ show bgp ipv4 community-list BLACKHOLE
BGP table version is 13, local router ID is 198.51.100.1, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.10/32 0.0.0.0 0 32768 i
Displayed 1 routes and 6 total paths
vyos@R1:~$ show ip bgp neighbors 203.0.113.0 advertised-routes
BGP table version is 13, local router ID is 198.51.100.1, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/24 0.0.0.0 0 0 i
*> 198.51.100.10/32 0.0.0.0 0 0 i
Total number of prefixes 2, total number of paths 2- Line 11: The list matches.
- Line 25: And the export map lets it through.
upstream1# show ip bgp 198.51.100.10/32
BGP routing table entry for 198.51.100.10/32, version 3
Paths: (1 available, best #1, table default, inform peer to blackhole prefix)
Not advertised to any peer
64500
192.0.2.1 from 203.0.113.1 (198.51.100.1)
Origin IGP, metric 0, valid, external, best (First path received)
Community: blackhole no-export
Last update: Sat Oct 17 13:40:55 2026
upstream1# show ip route 198.51.100.10/32
Routing entry for 198.51.100.10/32
Known via "bgp", distance 20, metric 0, best
Last update 00:00:20 ago
192.0.2.1 (recursive), weight 1
* unreachable (blackhole), weight 1
upstream1# ip route get 198.51.100.10
RTNETLINK answers: Invalid argument- Line 6: Next hop rewritten to the discard address.
- Line 8: BLACKHOLE, plus the NO_EXPORT the provider added.
- Line 15: Installed as a blackhole.
- Line 18: The kernel won't even route it.
internet# show ip bgp 198.51.100.10/32
% Network not in table
internet:/# ping -c 2 -W 2 -I 203.0.113.130 198.51.100.10
PING 198.51.100.10 (198.51.100.10) from 203.0.113.130: 56 data bytes
--- 198.51.100.10 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
internet:/# ping -c 2 -W 2 -I 203.0.113.130 198.51.100.1
PING 198.51.100.1 (198.51.100.1) from 203.0.113.130: 56 data bytes
64 bytes from 198.51.100.1: seq=0 ttl=63 time=1.461 ms
64 bytes from 198.51.100.1: seq=1 ttl=63 time=2.072 ms
--- 198.51.100.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.461/1.766/2.072 ms
internet:/# traceroute -n -q 1 -m 4 -s 203.0.113.130 198.51.100.10
traceroute to 198.51.100.10 (198.51.100.10) from 203.0.113.130, 4 hops max, 46 byte packets
1 *
2 *
3 *
4 *- Line 2: NO_EXPORT kept the /32 inside upstream1.
- Lines 3–7: The attacked host is gone…
- Lines 8–11: …the rest of the /24 isn't.
- Lines 18–21: Traceroute dies at the first hop: dropped inside upstream1.
Check your understanding
Your RTBH /32 shows 'Not advertised to any peer' with communities blackhole and no-export. What's wrong?
- You added NO_EXPORT; it stops the route reaching your eBGP upstream
- The upstream rejected it
- BLACKHOLE routes can't be advertised
- The /32 needs a static route