bgp_rtbh — BGP Remote Triggered Black Hole

Blocks by announcing each banned IP to the network as a host route (/32 IPv4, /128 IPv6) carrying the RFC 7999 BLACKHOLE community — or, with announce_type = "flowspec", as a BGP FlowSpec rule discarding traffic from the source. Routers that honor the announcement drop the traffic — at your edge, or with a transit provider that accepts them, before it ever reaches your link. The linux_ip_route backend scaled from one host to the whole network.

[kur.ddos]
backend  = "bgp_rtbh"
ban_time = 3600

[kur.ddos.options]
driver = "exabgp"

How the network side works — required first

This kur only announces and withdraws; everything else is BGP engineering that must already exist:

Requirements

Settings

Options

| option | default | what | |-----------------|--------------|--------------------------------------------------------| | driver | exabgp | exabgp, gobgp, or frr | | announce_type | rtbh | rtbh or flowspec (flowspec: exabgp/gobgp only) | | community | 65535:666 | community on every announcement (RFC 7999 BLACKHOLE) | | next_hop | 192.0.2.1 | next hop for IPv4 announcements | | next_hop6 | 100::1 | next hop for IPv6 announcements | | mask4 | 32 | IPv4 prefix length | | mask6 | 128 | IPv6 prefix length | | extra | (unset) | extra attributes appended verbatim, driver syntax | | exabgpcli_cmd | exabgpcli | exabgpcli binary (driver exabgp) | | gobgp_cmd | gobgp | gobgp binary (driver gobgp) | | vtysh_cmd | vtysh | vtysh binary (driver frr) |

community, next_hop/next_hop6, and extra apply to the exabgp/gobgp rtbh announcements; the frr driver's blackhole static route carries none of them (your redistribute route-map adds the community), and flowspec rules encode match-and-discard instead.

extra is driver-specific syntax passed through untouched — exabgp local-preference 50 vs gobgp local-pref 50; switching drivers means rewriting it. Widening mask4/mask6 announces more than the banned IP — deliberate collateral only.

What each operation runs

| operation | exabgp driver | gobgp driver | |------------|-------------------------------------------------------------------|-----------------------------------------------------------| | init | nothing | nothing | | ban | exabgpcli 'announce route <ip>/<mask> next-hop <nh> community [<community>]' | gobgp global rib add <ip>/<mask> nexthop <nh> community <community> -a ipv4\|ipv6 | | unban | exabgpcli 'withdraw route <ip>/<mask> next-hop <nh> community [<community>]' | gobgp global rib del <ip>/<mask> -a ipv4\|ipv6 | | check | exabgpcli 'show neighbor summary' exits 0 | gobgp neighbor exits 0 | | flush | the withdraw per banned IP | same | | re_init | teardown (best effort), init, re-announce every banned IP | same | | teardown | the withdraw per banned IP (ban book kept) | same |

With announce_type = "flowspec" the ban/unban commands become FlowSpec discard rules instead:

The frr driver injects and removes blackhole statics via vtysh -c 'configure terminal' -c '[no] ip[v6] route <ip>/<mask> blackhole', and its check is vtysh -c 'show ip bgp summary'.

list is the kur's own ban book; there is no init-time setup.

self_heal

check confirms the daemon answers — not that sessions are Established, not that any specific route is still announced, and certainly not that routers are dropping. An ExaBGP restart loses its announcements, yet check goes green again as soon as the daemon is back: pair daemon restarts with a re_init (which re-announces the whole book), and watch session state with your normal BGP monitoring, not this kur.

Gotchas