RPKI ROA and Route Origin Validation: ISP Setup Guide
An RPKI ROA is a signed statement that says which AS may originate a prefix and how long the announced prefix may be. Route origin validation (ROV) is what your routers do with that data: they compare each received BGP route to the validated ROA payloads (VRPs) and mark it valid, invalid or not-found. This guide covers creating ROAs with a safe maxLength, checking validity states, enabling ROV on common edge platforms, and what to watch for when a DDoS scrubbing edge announces your prefixes.
How ROAs and validation states work
A ROA has three fields: a prefix, a maxLength and an origin ASN. Validators (Routinator, rpki-client, Fort and others) download ROAs from the RIR repositories and verify the signatures. They then feed the VRPs to your routers over the RTR protocol.
A route is classified like this:
| State | Meaning |
|---|---|
| Valid | A ROA covers the prefix, the origin ASN matches, and the prefix length is ≤ maxLength |
| Invalid | A ROA covers the prefix, but the origin ASN differs or the prefix is longer than maxLength |
| Not-found | No ROA covers the prefix |
Example with a single ROA: 192.0.2.0/24, maxLength 24, origin AS64496.
192.0.2.0/24from AS64496 is valid.192.0.2.0/24from AS64511 is invalid (wrong origin).192.0.2.0/25from AS64496 is invalid (longer than maxLength).198.51.100.0/24with no ROA is not-found.
The second and third cases are why ROAs matter for hijack and leak protection. The third is also the most common way operators break their own announcements.
Creating ROAs with the right maxLength
Create ROAs in your RIR portal (ARIN, RIPE NCC, APNIC, LACNIC or AFRINIC). Hosted RPKI is the simplest option for most ISPs and hosting networks.
Rules that work in practice:
- Default maxLength to the exact prefix length. If you announce
192.0.2.0/24, use maxLength 24. A loose maxLength lets an attacker announce a forged-origin more-specific that still validates. - Add maxLength only for more-specifics you really announce. If you announce a
/22and also deaggregate into/24s for traffic engineering, either use maxLength 24 on that ROA or create separate ROAs for each/24. Avoid maxLength 32 on IPv4 or 128 on IPv6. - Create a ROA for every origin ASN that may announce the prefix. Multiple ROAs for one prefix with different origin ASNs are valid. This matters for multihoming, migrations and scrubbing (see below).
- Cover IPv6 too. For
2001:db8::/32announced as a/32, use maxLength 32. If you announce/48s from it, plan those explicitly. - Create the ROA before you change anything. Publication and validator refresh can take from minutes to a few hours. Don't switch origins or start a new announcement until the VRP is visible in your own validator.
Checking validity before and after
Run your own validator. Routinator is a common choice:
routinator init
routinator server --rtr 10.0.0.10:3323 --http 127.0.0.1:9556
Bind RTR to an internal address only, and use firewall rules to allow just your routers. Then test a prefix and origin:
routinator validate --asn 64496 192.0.2.0/24
The output tells you the state and lists the matching VRPs. Also check from a router after the RTR session is up. Public looking glasses and RIR dashboards are a useful second opinion, but your own validator is what decides what your routers do.
Enabling ROV on edge routers
Point every router at two validators in different locations. If a router's only RTR session drops, it eventually has no VRPs and every route becomes not-found, so protection fails open silently. Alert on RTR session state.
Start by rejecting invalid routes from transit, IXes and peers. Customer sessions need more care (see the mistakes section).
Juniper (Junos)
set routing-options validation group RPKI session 10.0.0.10 port 3323
set routing-options validation group RPKI session 10.0.0.10 refresh-time 120
set routing-options validation group RPKI session 10.0.0.11 port 3323
set policy-options policy-statement ROV term invalid from protocol bgp
set policy-options policy-statement ROV term invalid from validation-database invalid
set policy-options policy-statement ROV term invalid then validation-state invalid
set policy-options policy-statement ROV term invalid then reject
Add ROV at the start of your eBGP import policy chain. Verify with show validation session and show validation database.
Cisco IOS XE
router bgp 64500
bgp rpki server tcp 10.0.0.10 port 3323 refresh 120
bgp rpki server tcp 10.0.0.11 port 3323 refresh 120
!
route-map ROV-IN deny 10
match rpki invalid
route-map ROV-IN permit 20
match rpki valid
route-map ROV-IN permit 30
match rpki not-found
Apply ROV-IN inbound on the eBGP neighbors, then check with show ip bgp rpki servers and show ip bgp rpki table.
MikroTik RouterOS v7
/routing/rpki add group=rpki address=10.0.0.10 port=3323
/routing/filter/rule add chain=ebgp-in rule="rpki-verify rpki; if (rpki invalid) { reject }"
Use the ebgp-in chain as the input filter on your eBGP connections. Exact filter syntax varies a bit between RouterOS 7 releases, so test it on a lab device or a low-impact session first.
Linux with BIRD 2
roa4 table r4;
roa6 table r6;
protocol rpki rpki1 {
roa4 { table r4; };
roa6 { table r6; };
remote 10.0.0.10 port 3323;
retry keep 90;
refresh keep 900;
expire keep 172800;
}
filter ebgp_in_v4 {
if roa_check(r4, net, bgp_path.last) = ROA_INVALID then reject;
accept;
}
Use r6 in an equivalent IPv6 filter.
How RPKI complements AS-SET and IRR filtering
IRR route objects and AS-SETs answer a different question than RPKI does. They tell you which prefixes a customer says they are allowed to announce. Tools like bgpq4 generate prefix lists from them. IRR data is not cryptographically authenticated in most registries, and stale or forged objects exist.
RPKI cryptographically ties a prefix to an origin ASN, but it only checks the origin. It says nothing about which customer is allowed to send you that prefix, and it doesn't validate the AS path. A forged-origin hijack with the legitimate ASN at the end of the path can still be valid.
Use both on customer sessions:
- Prefix-list from the customer AS-SET controls what you accept from that customer.
- ROV rejects routes whose origin or length is wrong.
- Max-prefix limits and bogon filters cover the rest.
RPKI and prefixes announced from a scrubbing edge
With a cloud scrubbing service, your prefixes are announced from the provider's edge during mitigation (or all the time, if always-on), and clean traffic returns over a GRE tunnel with a BGP session inside. From an RPKI perspective, this is a change in who announces your space, so check these items:
- Origin ASN. The ROA must authorize whichever ASN originates the route on the Internet. Confirm with your provider which origin ASN the announcements use, and create the matching ROA. If you move between origin ASNs for different modes, publish ROAs for both.
- Prefix length. If the edge announces your
/24s while you normally announce a/22, the ROA's maxLength must allow/24. Otherwise the scrubbing announcement is invalid and many networks will drop it, which defeats mitigation exactly when you need it. - On-demand mode. The announcement only appears during an attack, so nobody notices a missing ROA until then. Test with the provider during onboarding.
- Provider-side filtering. The provider can filter what you announce to it using your AS-SET. Keep the AS-SET and ROAs consistent, so a prefix is in both or neither.
With NixGuard Edge, customers need their own ASN and at least one /24, and the customer AS-SET can be used for prefix filtering. ROAs are the matching piece on the global-routing side.
RTBH and FlowSpec caveats
RTBH usually means announcing a /32 (or /128) with a blackhole community to your upstream. A ROA with maxLength 24 makes that /32 formally invalid. Many providers accept blackhole routes by community and exempt them from ROV, but not all do. Ask your upstream rather than raising maxLength to 32 across your whole space, which weakens protection for every normal announcement.
FlowSpec rules are validated differently. They are not subject to ROV on the NLRI prefix. Standard FlowSpec validation checks that the rule's destination matches the best-match unicast route and that the same neighbor originated both.
Common mistakes
- maxLength set too high. This invites forged-origin more-specifics.
- maxLength too low for your own deaggregation. Your
/24s turn invalid after you publish a/22ROA with maxLength 22. - No ROA for the scrubbing or backup origin. Mitigation fails when needed.
- A single validator. If it breaks, ROV stops silently.
- Rejecting invalid routes from customers without warning. Run a report of invalid customer routes first and have them fix their ROAs. Then enforce.
- Forgetting renewal and ownership changes. If you transfer or renumber space, update the ROAs the same day.
- Treating RPKI as DDoS protection. It protects routing integrity. Floods still need detection and mitigation.
Where NixMon fits
ROV protects the routes. NixMon detects attacks from NetFlow, IPFIX or sFlow and can trigger BGP blackhole, FlowSpec, on-prem NixGuard or NixGuard Edge. When mitigation relies on BGP announcements, a clean RPKI setup keeps those announcements accepted by the rest of the Internet. You can try it for 15 days without a credit card at mon.nixmon.com/register.
Frequently asked questions
What maxLength should I use in a ROA?
Use the exact prefix length you announce, for example 24 for a /24. Raise maxLength only if you actually announce more-specifics, such as /24s inside a /22. Avoid maxLength 32 on IPv4 or 128 on IPv6.
What is the difference between invalid and not-found?
Not-found means no ROA covers the prefix. Invalid means a ROA covers it, but the origin ASN does not match or the prefix is longer than maxLength. Networks that enforce ROV typically drop invalid routes and still accept not-found ones.
Does RPKI replace AS-SET and IRR filtering?
No. IRR and AS-SET filters define which prefixes a customer may announce to you. RPKI validates the origin ASN and prefix length. Use both, plus max-prefix limits.
Will ROV drop my RTBH /32 announcements?
It can. If your ROA maxLength is 24, a /32 is invalid. Many providers exempt blackhole-community routes from ROV, but you should confirm this with your upstream rather than loosening maxLength broadly.