DEV Community

Young Gao
Young Gao

Posted on

RPKI in Practice: Securing Your BGP Routes Against Hijacking in 2026

RPKI in Practice: Securing Your BGP Routes Against Hijacking

BGP was designed in 1989 with an implicit assumption: every network operator is trustworthy. That assumption hasn't aged well. Route hijacking — where someone announces your prefixes as their own — remains one of the Internet's most persistent security problems.

RPKI (Resource Public Key Infrastructure) fixes this by cryptographically binding IP prefixes to the ASNs authorized to originate them. If you operate your own AS, deploying RPKI is no longer optional — it's table stakes.

How RPKI Works

The chain of trust starts at the five Regional Internet Registries (RIRs): ARIN, RIPE NCC, APNIC, AFRINIC, and LACNIC. Each RIR operates a Certificate Authority (CA) that issues certificates to resource holders.

RIR (Trust Anchor)
  └── LIR / Resource Holder (Certificate)
        └── ROA (Route Origin Authorization)
              └── "AS215000 is authorized to announce 2001:db8:abcd::/48"
Enter fullscreen mode Exit fullscreen mode

When you create a ROA, you're signing a statement: "This ASN is allowed to announce this prefix with this maximum prefix length." Validators fetch these ROAs, verify the signatures, and provide the validation results to your BGP router.

Your router then classifies every received BGP route as:

State Meaning Action
Valid A ROA exists and matches Accept
Invalid A ROA exists but doesn't match (wrong ASN or too specific) Reject
NotFound No ROA exists for this prefix Accept (but flag)

The critical part: Invalid routes get dropped. This is what prevents hijacking.

Step 1: Create Your ROAs

RIPE NCC

If your resources are in the RIPE region, log into the RIPE NCC portal and navigate to RPKIROAs.

Create a ROA for each prefix you announce:

Prefix:     2001:db8:abcd::/48
Origin AS:  AS215000
Max Length:  48
Enter fullscreen mode Exit fullscreen mode

Max Length matters: Setting max length to /48 means only a /48 announcement is valid. If you sometimes announce more specifics (like /64s for traffic engineering), set max length accordingly. But be conservative — a wider max length increases your attack surface.

For IPv4:

Prefix:     203.0.113.0/24
Origin AS:  AS215000
Max Length:  24
Enter fullscreen mode Exit fullscreen mode

ARIN

ARIN uses their RPKI Dashboard. The process is similar but requires you to first create a Resource Certificate, then create ROAs under it.

Hosted vs Delegated

  • Hosted RPKI (recommended for most): The RIR hosts your certificates and ROAs. You manage them through a web portal. Simpler, no infrastructure to maintain.
  • Delegated RPKI: You run your own CA. More control, but you're responsible for uptime and key management. Only worth it if you're a large LIR.

Step 2: Run an RPKI Validator

Your BGP router needs a local source of validated ROA data. This is provided by an RPKI validator — software that fetches ROAs from all five RIRs, validates the cryptographic chain, and serves the results via the RTR (RPKI-to-Router) protocol.

Routinator (Recommended)

Routinator by NLnet Labs is the most widely deployed validator.

# Install on Debian/Ubuntu
sudo apt install routinator

# Or via cargo
cargo install routinator

# Initialize (downloads Trust Anchor Locators)
routinator init --accept-arin-rpa

# Run with RTR server on port 3323 and HTTP API on 8323
routinator server --rtr 0.0.0.0:3323 --http 0.0.0.0:8323
Enter fullscreen mode Exit fullscreen mode

Set up as a systemd service:

# /etc/systemd/system/routinator.service
[Unit]
Description=Routinator RPKI Validator
After=network.target

[Service]
Type=simple
User=routinator
ExecStart=/usr/bin/routinator server --rtr 0.0.0.0:3323 --http 0.0.0.0:8323
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
sudo useradd -r -s /usr/sbin/nologin routinator
sudo systemctl enable --now routinator
Enter fullscreen mode Exit fullscreen mode

Verify It's Working

# Check HTTP status
curl http://localhost:8323/api/v1/status

# Count validated ROAs
curl -s http://localhost:8323/api/v1/validity/AS215000/2001:db8:abcd::/48
Enter fullscreen mode Exit fullscreen mode

Other Validators

  • Fort: Lightweight alternative by LACNIC
  • OctoRPKI: By Cloudflare, used in their production infrastructure
  • rpki-client: OpenBSD-native, also runs on Linux

For redundancy, consider running two different validator implementations.

Step 3: Configure BIRD 2 for RPKI

Add the RPKI protocol and ROA tables to your BIRD configuration:

# /etc/bird/bird.conf

# ROA tables
roa4 table roa_v4;
roa6 table roa_v6;

# RPKI connection to Routinator
protocol rpki rpki1 {
    roa4 { table roa_v4; };
    roa6 { table roa_v6; };

    remote "127.0.0.1" port 3323;

    retry keep 5;
    refresh keep 30;
    expire 600;
}

# Optional: redundant validator
protocol rpki rpki2 {
    roa4 { table roa_v4; };
    roa6 { table roa_v6; };

    remote "10.0.0.2" port 3323;

    retry keep 5;
    refresh keep 30;
    expire 600;
}
Enter fullscreen mode Exit fullscreen mode

Update Your Import Filters

filter import_rpki {
    # Reject bogons first
    if net ~ [ ::/8+, fe80::/10+, fc00::/7+, 2001:db8::/32+ ] then reject;
    if net.len > 48 then reject;

    # RPKI validation
    if (roa_check(roa_v6, net, bgp_path.last) = ROA_INVALID) then {
        print "RPKI INVALID: ", net, " via AS", bgp_path.last;
        reject;
    }

    # Optionally tag valid/unknown for monitoring
    if (roa_check(roa_v6, net, bgp_path.last) = ROA_VALID) then {
        bgp_large_community.add((MY_ASN, 1000, 1));  # Mark as RPKI valid
    }

    accept;
}
Enter fullscreen mode Exit fullscreen mode

Apply to your BGP sessions:

protocol bgp upstream_a from upstream {
    neighbor 2001:db8:1::1 as 64500;
    ipv6 {
        import filter import_rpki;
        export filter export_upstream;
    };
}
Enter fullscreen mode Exit fullscreen mode

Reload Without Disruption

sudo birdc configure
# BIRD reloads config without dropping BGP sessions
Enter fullscreen mode Exit fullscreen mode

Step 4: Monitor Your RPKI Status

Check Your Own ROAs

# Via Routinator HTTP API
curl -s http://localhost:8323/api/v1/validity/AS215000/2001:db8:abcd::/48 | jq

# Via external services
# https://rpki-validator.ripe.net/
# https://bgp.tools/prefix/2001:db8:abcd::/48#rpki
Enter fullscreen mode Exit fullscreen mode

Monitor for Invalid Routes

Set up alerting for RPKI invalid routes in your network:

#!/bin/bash
# /usr/local/bin/rpki-monitor.sh
INVALID_COUNT=$(birdc 'show route where roa_check(roa_v6, net, bgp_path.last) = ROA_INVALID' | grep -c "via")
if [ "$INVALID_COUNT" -gt 0 ]; then
    echo "$INVALID_COUNT RPKI-invalid routes detected" | \
        mail -s "RPKI Alert: Invalid Routes" noc@example.com
fi
Enter fullscreen mode Exit fullscreen mode

ROA Expiry Monitoring

ROAs have an expiry date. If your ROAs expire, your routes become "NotFound" — which is less secure than "Valid."

# Check ROA expiry via RIPE NCC portal
# Or use the Routinator API:
curl -s http://localhost:8323/api/v1/status | jq '.roas'
Enter fullscreen mode Exit fullscreen mode

RPKI Adoption in 2026

As of 2026, RPKI adoption has reached critical mass:

  • 70%+ of IPv4 routes and 60%+ of IPv6 routes have ROAs
  • Major networks (Cloudflare, Google, Amazon, Microsoft) reject RPKI-invalid routes
  • RIPE NCC, APNIC, and ARIN all support hosted RPKI
  • Most IX route servers perform RPKI validation by default

If you don't have ROAs, your routes are increasingly at a disadvantage — some networks may deprioritize "NotFound" routes, and you have zero protection against hijacking.

Common RPKI Mistakes

  1. Creating ROAs with wrong max length: A /24 ROA with max length /28 means anyone who hijacks a /28 of your space will have a "Valid" route. Keep max length tight.

  2. Forgetting to update ROAs when changing providers: If you move your prefix to a new ASN, update the ROA before the BGP change. Otherwise you'll create an invalid route for yourself.

  3. Not monitoring ROA expiry: Expired ROAs = no protection. Set calendar reminders or automated alerts.

  4. Running only one validator: If your single validator goes down, BIRD's ROA table expires and all routes become "NotFound." Run at least two validators for redundancy.

  5. Not deploying on all border routers: RPKI validation on one router but not another creates inconsistent behavior. Deploy everywhere.

Beyond Origin Validation: BGPsec and ASPA

RPKI origin validation (what we've covered here) prevents prefix hijacking — someone announcing your prefix from their ASN. It doesn't prevent path manipulation — someone inserting your ASN into a fabricated path.

Two emerging standards address this:

  • ASPA (Autonomous System Provider Authorization): Validates the AS path by checking that each AS-to-AS hop is authorized. Draft standard, gaining support.
  • BGPsec: Cryptographic path validation. More complete but higher overhead. Limited deployment.

For now, RPKI origin validation with ROAs covers the most common attack scenarios and is straightforward to deploy.


Already running RPKI? What validator are you using, and have you caught any invalid routes? Share your experience in the comments.

Top comments (0)