RTBH placeholder-next-hop check predates c49e31b's community-based fix, rejects valid community-only configs #273

Closed
opened 2026-08-04 04:00:19 +00:00 by vxfemboy · 0 comments
Owner

Symptom

`blackwalld flow` refuses to arm (exits 1, forces shadow-only) with:

```
error: refusing to arm: RTBH next-hop [192.0.2.1, 100::1] is a documentation/discard placeholder
(RFC 5737/3849/6666) that never resolves to a real blackhole route -- BIRD would leave the blackhole
`unreachable` and never export it. Set next-hop-v4/next-hop-v6 to a real discard route, or run in
`shadow`.
```

...even when the RTBH community (65535,666) is correctly configured and BIRD's import filter converts
it directly to `dest = RTD_BLACKHOLE` on import, making the next-hop's resolvability irrelevant.

Root cause

The check (`68eb669`, "feat(instance): per-instance kernel-resource identity + reject placeholder
RTBH next-hop", 2026-07-31) predates `c49e31b` ("fix(rtbh): convert community-tagged host routes to
real discards on import (RFC 7999)", 2026-08-01) by 12 commits. `68eb669`'s check encodes the
pre-c49e31b assumption -- that a real, resolvable next-hop is required for BIRD's recursive
next-hop resolution to turn the route into a genuine blackhole. `c49e31b` made that assumption
obsolete: the generated import filter now sets `dest = RTD_BLACKHOLE` directly from the community,
regardless of whether the next-hop resolves. The placeholder check was never updated to account for
this and still treats a documentation-range next-hop as a hard arm-blocking error.

Impact

Confirmed live on AS214806: after picking up commits #265/#266/#270 (unrelated fixes), the container's
`blackwalld-flow` failed to restart with this error and downgraded from ARMED (M1) to a forced
shadow-only crash-loop -- config unchanged, only the binary was updated. The config's
`next-hop-v4=192.0.2.1 next-hop-v6=100::1` was deliberately set to placeholder values because
c49e31b made a real discard address unnecessary (see that commit's own message: "This makes RTBH work
with NO reserved next-hop address"). The daemon's own validation logic disagrees with its own recent
fix.

Fix

The check in `bin/blackwalld/src/main.rs` (around the `placeholder_next_hops()` call in the `Flow`
command handler) should be relaxed or removed when the configured `community` is the RTBG-blackhole
one AND the generated BIRD import filter is known to do the community-to-`RTD_BLACKHOLE` conversion
(i.e., whenever c49e31b's behavior applies). At minimum, the error message should mention that a real
next-hop is no longer required as of c49e31b, so an operator hitting this doesn't have to trace the
history to find out the check itself is stale.

Workaround in place

Set `next-hop-v4`/`next-hop-v6` to a real-but-unused address within our own managed space
(`94.156.238.67`/`2a12:9b00:b00b::67`) instead of an RFC 5737/3849/6666 placeholder -- passes the
check, no functional difference since c49e31b makes the value irrelevant either way.

## Symptom \`blackwalld flow\` refuses to arm (exits 1, forces shadow-only) with: \`\`\` error: refusing to arm: RTBH next-hop [192.0.2.1, 100::1] is a documentation/discard placeholder (RFC 5737/3849/6666) that never resolves to a real blackhole route -- BIRD would leave the blackhole \`unreachable\` and never export it. Set next-hop-v4/next-hop-v6 to a real discard route, or run in \`shadow\`. \`\`\` ...even when the RTBH community (65535,666) is correctly configured and BIRD's import filter converts it directly to \`dest = RTD_BLACKHOLE\` on import, making the next-hop's resolvability irrelevant. ## Root cause The check (\`68eb669\`, \"feat(instance): per-instance kernel-resource identity + reject placeholder RTBH next-hop\", 2026-07-31) predates \`c49e31b\` (\"fix(rtbh): convert community-tagged host routes to real discards on import (RFC 7999)\", 2026-08-01) by 12 commits. \`68eb669\`'s check encodes the *pre-c49e31b* assumption -- that a real, resolvable next-hop is required for BIRD's recursive next-hop resolution to turn the route into a genuine blackhole. \`c49e31b\` made that assumption obsolete: the generated import filter now sets \`dest = RTD_BLACKHOLE\` directly from the community, regardless of whether the next-hop resolves. The placeholder check was never updated to account for this and still treats a documentation-range next-hop as a hard arm-blocking error. ## Impact Confirmed live on AS214806: after picking up commits #265/#266/#270 (unrelated fixes), the container's \`blackwalld-flow\` failed to restart with this error and downgraded from ARMED (M1) to a forced shadow-only crash-loop -- config unchanged, only the binary was updated. The config's \`next-hop-v4=192.0.2.1 next-hop-v6=100::1\` was deliberately set to placeholder values *because* c49e31b made a real discard address unnecessary (see that commit's own message: \"This makes RTBH work with NO reserved next-hop address\"). The daemon's own validation logic disagrees with its own recent fix. ## Fix The check in \`bin/blackwalld/src/main.rs\` (around the \`placeholder_next_hops()\` call in the \`Flow\` command handler) should be relaxed or removed when the configured \`community\` is the RTBG-blackhole one AND the generated BIRD import filter is known to do the community-to-\`RTD_BLACKHOLE\` conversion (i.e., whenever c49e31b's behavior applies). At minimum, the error message should mention that a real next-hop is no longer required as of c49e31b, so an operator hitting this doesn't have to trace the history to find out the check itself is stale. ## Workaround in place Set \`next-hop-v4\`/\`next-hop-v6\` to a real-but-unused address within our own managed space (\`94.156.238.67\`/\`2a12:9b00:b00b::67\`) instead of an RFC 5737/3849/6666 placeholder -- passes the check, no functional difference since c49e31b makes the value irrelevant either way.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
femboy/blackwall#273
No description provided.