# RPKI & routing security

**A verified DNSSEC chain and a pinned TLSA key are worthless if someone can just steal the route.**

BGP has no built-in authentication — any network can announce "I originate `2a04:2a01::/32`," and if enough peers believe it, traffic to every Whisper agent is vacuumed into the hijacker's network before it reaches us. It has happened to real prefixes: YouTube's 2008 hijack by Pakistan Telecom, the 2018 Amazon Route 53 hijack that redirected `myetherwallet.com` traffic to a phishing site. DNSSEC and DANE prove the *answer* is authentic; RPKI proves the *path to the server* wasn't stolen. Skip it and you've locked the front door while leaving the delivery route unguarded.

Whisper's whole address block (`2a04:2a01::/32`, announced by **AS219419**) is RPKI-signed, and the resolver can enforce that every destination it hands an agent is running on a route nobody hijacked. This page covers the actual mechanism — ROAs, origin validation, the RFCs behind it — and how to check it yourself with nothing but stock tools.

## The mechanism: Route Origin Authorizations (RFC 6482)

RPKI (Resource Public Key Infrastructure, **RFC 6480**) is a PKI overlaid on the number resources themselves. A Regional Internet Registry (RIPE NCC, ARIN, APNIC…) holds the root certificate for the address space it allocated. It issues a certificate to the resource holder — Whisper Security / viaGraph B.V. holds the certificate for `2a04:2a01::/32` — and that holder signs a **Route Origin Authorization (ROA, RFC 6482)**, a small signed object asserting three fields:

| Field | Whisper's ROA |
|---|---|
| Prefix | `2a04:2a01::/32` |
| Origin ASN | `AS219419` |
| Max length | `32` |

The **max length** caps how specific a sub-announcement is allowed to be, and Whisper's ROA sets it to `32` — exactly the prefix length itself. That means **only the exact `/32` is authorized**: any more-specific announcement — a `/33`, a `/48`, a `/64` — from anywhere on earth, *including AS219419 itself*, is **RPKI-invalid**. It's the tightest ROA there is. There's no authorized more-specific for a hijacker to hide a bogus route behind and win longest-prefix-match, and no room for our own kit to leak one either. (A holder *can* permit more-specifics by setting `maxLength` longer than the prefix; Whisper deliberately doesn't — the per-agent `/128` identities all live *inside* that single `/32` announcement, so there's never a reason to announce anything narrower.)

ROAs are published in the RIR's **RPKI repository** as signed CMS objects and fetched by relying-party software (Routinator, rpki-client, OctoRPKI) that any network operator runs. That software builds a **VRP set** (Validated ROA Payload: prefix + max-length + ASN tuples) and hands it to the router.

## Route Origin Validation (RFC 6811)

**RFC 6811** defines how a BGP speaker uses that VRP set against every route it receives. For each announced `(prefix, origin-ASN)` pair, RPKI-to-router (RFC 8210) delivers the VRPs to the router in real time, and the outcome is one of three states:

- **Valid** — a VRP exists that covers this exact prefix (or a less-specific covering it, within max-length) with a matching origin ASN.
- **Invalid** — a covering VRP exists, but either the origin ASN doesn't match (hijack) or the announced prefix is more specific than the max-length allows (leak/overclaim).
- **NotFound (Unknown)** — no ROA covers this prefix at all — most of the internet's legacy space, still unsigned.

RFC 6811 recommends: prefer valid, never propagate invalid to customers, and deprioritize (or drop, per local policy) invalid routes in best-path selection. Whisper's edge routers apply **origin validation on every eBGP session** — invalid routes are marked and stripped from the RIB, so a hijacked more-specific of our own `/32`, or a bogus origin ASN claiming it, never wins a path even transiently.

### Dual-homed, not single-homed

AS219419 peers with more than one upstream and exchanges routes at public internet exchanges rather than depending on a single transit provider — the MANRS baseline for resilience. If one upstream flaps, has an outage, or itself propagates a bad route, the other path keeps `2a04:2a01::/32` reachable. Combined with RPKI-invalid dropping, this is what "an address on land we own" (see [Verifiable identity](/docs/verifiable-identity)) actually cashes out to operationally: a route that's both cryptographically authorized and not a single point of failure.

## MANRS: the operational commitment, not just the crypto

RPKI signs *what should be true*; **MANRS** (Mutually Agreed Norms for Routing Security, manrs.org) is the community's checklist that operators actually *do* something with it. AS219419 is MANRS-compliant against all four network-operator actions:

1. **Filtering** — reject announcements (from customers/peers) that fail origin validation or don't match agreed prefixes.
2. **Anti-spoofing** — enforce source-address validation so packets can't leave the network with a forged source.
3. **Coordination** — publish current contact info (peeringdb, IRR/RPKI metadata) so abuse and routing incidents get resolved fast.
4. **Global validation** — publish accurate route-object/ROA information so *other* networks can validate against AS219419's own routes.

That last one is the point where RPKI and MANRS meet: it's not enough for Whisper to validate what it receives — the ROA for `2a04:2a01::/32` has to be correct and current so the *rest of the internet's* routers validate Whisper's own announcements as valid, not invalid or unknown.

## Checking it yourself — stock tools

No Whisper software required — RPKI state is public data, published for exactly this purpose.

```bash
# 1. Ask a public RPKI validator (RIPEstat) for the ROA and origin-validation verdict
curl -s "https://stat.ripe.net/data/rpki-validation/data.json?resource=AS219419&prefix=2a04:2a01::/32" | jq '.data'
# → { "status": "valid", "validator": "routinator", "validating_roas": [
#       { "origin": "219419", "prefix": "2a04:2a01::/32", "max_length": 32, "validity": "valid" } ] }

# 2. Cross-check the ASN's name, peers and announced prefixes with bgpview.io (or bgp.tools)
curl -s "https://api.bgpview.io/asn/219419" | jq '.data | {name, description_short, rir_allocation}'
curl -s "https://api.bgpview.io/asn/219419/prefixes" | jq '.data.ipv6_prefixes[].prefix'
whois -h whois.radb.net '!6as219419'           # IPv6 IRR route objects for the origin AS

# 3. Grep the ROA out of a public, current VRP export (Cloudflare's rpki-client feed)
curl -s "https://rpki.cloudflare.com/rpki.json" \
  | jq '.roas[] | select(.asn=="AS219419")'
#   → { "prefix": "2a04:2a01::/32", "maxLength": 32, "asn": "AS219419", "ta": "ripe" }
```

`stat.ripe.net`'s `rpki-validation` endpoint runs the exact RFC 6811 algorithm against the live VRP set and gives you the same valid/invalid/unknown verdict a router would compute — no BGP session of your own required.

## With Whisper: enforcing it on the resolver, not just the wire

Checking the *route to Whisper* is public and stock-tools-only, as above. But Whisper's control plane goes one step further: it can make the **resolver itself** refuse to hand an agent a destination whose *own* route is RPKI-invalid — protecting the agent from resolving straight into a hijack of somebody else's prefix.

```bash
# Turn on hijack-aware routing policy for one agent — the resolver refuses to
# hand it any destination currently announced via an RPKI-invalid route.
whisper policy shipping-bot --routing drop-hijacked
```

Under the hood this is one call to the control verb — the same `whisper.agents` verb that provisions identity, sets geo/category policy, and streams logs (see [Control plane](/docs/control-plane)):

```
CALL whisper.agents({op:'policy', args:{
  agent:   'shipping-bot',
  routing: 'drop-hijacked'
}})
```

With this set, any candidate answer the resolver would otherwise return is checked against current route-origin validation state before it's handed to the agent; an RPKI-invalid destination is treated the same as a graph-flagged malicious one — it doesn't resolve. Every policy field is additive and revocable: re-run `whisper policy shipping-bot …` with a different set of levers at any time and the *next* query the agent makes is evaluated under it — nothing to redeploy.

```bash
whisper policy shipping-bot --routing drop-hijacked --geo-allow EU --block tor-exit
# routing + geofence + category block, one call, evaluated fresh per query
```

This is opt-in, not a hidden filter — Postel's Law cuts both ways: liberal in what the resolver accepts as a query, conservative (and honest about it) in what it's willing to hand back as an answer once you've asked it to be.

> RPKI only signs the origin ASN, not the AS path — it stops "wrong network claims this prefix" hijacks (the overwhelming majority of real incidents) but not a path-manipulation attack from a transit AS already on a legitimate path. Full path security is what BGPsec (RFC 8205) targets; it isn't yet deployed at internet scale, and Whisper doesn't claim it does more than RFC 6811 origin validation.

---

**Next:** [Verifiable identity](/docs/verifiable-identity) — how the address itself, not just the route to it, is provable · [Trustless verification](/docs/verify) — chain-of-custody checks (DANE, DNSSEC, transparency) that compose with RPKI for an end-to-end trust story.
