what it’s all about?
as part of efforts to protect BGP routes from “hijacking”, which means unauthorized announcement to redirect traffic, IETF came up with idea of running resource certification for some of BGP attributes. RPKI, which stands for Resource Public Key Infrastructure is a specialized framework that enables doing just that - by cryptologically signing information about BGP prefix (and allowed mask length) and BGP route origin AS.
in ideal world, you should run your own RPKI server that you control, and then feed your routers with current state of validation tables. for most part this is easy and quick, but people often complain that they need additional VMs or even hardware appliances to do that. here’s the solution to that problem.
RPKI route server
I’m running community route server, that’s available to everyone, just like [some](BGP blackholing) of my [other](AS 112) [projects](BGP Feeder).
if you want to start RPKI journey, first of all you should make sure to sign your own prefixes. there is a couple of good tutorials out there on how to do this.
then, you should make your own mind how you want to treat prefixes if they are invalid. when router receives BGP prefixes from neighbor and then RPKI table, it can perform validation process by tryign to compare those two.
prefix in BGP will contain prefix itself (let’s say 1.1.0.0/16) as well as some BGP attributes, like AS_PATH (AS path that as used to announce it to this point). RPKI table will contain ROA records, that will specify prefix along with allowed mask variation (let’s say 1.1.0.0/16-24) and origin AS (let’s say 1024).
after validation, prefix will end up in one of three states:
- VALID - prefix in BGP table matches RPKI definition;
- INVALID - prefix in BGP table doesn’t match RPKI/ROA definition, which means somebody is playing dirty tricks, or simply made an error while signing the prefix (it still happens)
- NOT FOUND - prefix in BGP table can’t be matched to any RPKI/ROA entry, and likely was not yet signed; that’s unfortunately still the case, with about 65% of prefixes not yet signed by owners
if you’re running stub network (non-transit), connected to one upstream provider, even if you decide not to forward traffic towards INVALID prefixes, you’ll likely still send it as it matches default route (you can also choose to drop such traffic, but effectivness of such action will be likely limited).
if you have two upstreams, here where play begins. it may be, that INVALID prefix is received only via one neighbor, while the other is advertising proper prefix. then, decision is simple - you should ignore and never forward based on INVALID data.
config, show me the configuration
before you start, make a decision - do you want to drop traffic based on validation status, or just lower it’s preference vs others. it’s important, as with some topologies/traffic scenarios, dropping “INVALID” prefixes may lead to routing loops!
- sessions are established over TCP with RTR protocol (not SSH!)
- session IP addresses of RPKI route servers - remember RPKI records are sent for both IPv4 and IPv6 over any possible transport, so you don’t need to establish separate IPv4 and IPv6 sessions like you would typically do for normal BGP sessions:
- IPv4 -
85.232.240.141
or/and195.136.71.52
- IPv6 -
2001:1a68:2c:2::141
or/and2a00:4120:8000:a::10
- IPv4 -
- timers - 3600 for refresh
some example configurations for Your routers:
Cisco IOS-XE configuration
for Cisco IOS XE, in releases 17+, the BGP path validation is already active and should be dropping INVALID paths from being selected as bestpaths; if therefore you want to configure the community BGP RPKI route server, just configure that:
router bgp X
bgp rpki server tcp 85.232.240.141 port 3323 refresh 3600
bgp rpki server tcp 195.136.71.52 port 3323 refresh 3600
bgp rpki server tcp 2A00:4120:8000:A::10 port 3323 refresh 3600
bgp rpki server tcp 2001:1A68:2C:2::141 port 3323 refresh 3600
once this is done, RPKI servers should feed you with data (amount of prefixes will equalize with time, once all sessions are synchronized):
ios-xe-rtr#sh bgp ipv4 unicast rpki servers | i SOVC|Prefixes
BGP SOVC neighbor is 195.136.71.52/3323 connected to port 3323
Prefixes 316421
BGP SOVC neighbor is 2A00:4120:8000:A::10/3323 connected to port 3323
Prefixes 316422
BGP SOVC neighbor is 2001:1A68:2C:2::141/3323 connected to port 3323
Prefixes 316427
BGP SOVC neighbor is 85.232.240.141/3323 connected to port 3323
Prefixes 316410
if for some reason you want to stop that and control prefixes based on policies, you could allow INVALID state prefixes into BGP:
router bgp X
address family ipv4 unicast
bgp bestpath prefix-validate allow-invalid
address family ipv6 unicast
bgp bestpath prefix-validate allow-invalid
You can then manipulate route attributes, and invalid routes can become bestpaths - but that would be less optimal in bigger scheme of things.
Cisco IOS XR configuration
for Cisco IOS XR, the same configuration would be:
router bgp X
rpki server 195.136.71.52
transport tcp port 3323
refresh-time 3600
!
rpki server 85.232.240.141
transport tcp port 3323
refresh-time 3600
!
rpki server 2001:1a68:2c:2::141
transport tcp port 3323
refresh-time 3600
!
rpki server 2a00:4120:8000:a::10
transport tcp port 3323
refresh-time 3600
!
address-family ipv4 unicast
bgp origin-as validation enable
bgp bestpath origin-as use validity
!
address-family ipv6 unicast
bgp origin-as validation enable
bgp bestpath origin-as use validity
!
once you established connections properly, you should see something like that:
RP/0/RP0/CPU0:xr-router#sh bgp rpki server summary
Hostname/Address Transport State Time ROAs (IPv4/IPv6)
195.136.71.52 TCP:3323 ESTAB 00:00:14 263152/53269
2001:1a68:2c:2::141 TCP:3323 ESTAB 00:00:14 263156/53271
2a00:4120:8000:a::10 TCP:3323 ESTAB 00:00:14 263152/53269
85.232.240.141 TCP:3323 ESTAB 00:04:14 263197/53285
and:
RP/0/RP0/CPU0:xr-router#sh bgp rpki summary
RPKI cache-servers configured: 4
RPKI database
Total IPv4 net/path: 238761/263197
Table Version: 4100272
Scanner Version: 4100272
Total IPv6 net/path: 49812/53286
Table Version: 804305
Scanner Version: 804305
Juniper JunOS configuration
basic configuration (again, you need two of those, don’t need to configure separate IPv4 and IPv6 unless you’re really crazy about redundancy):
set routing-options validation group LUKE-RPKI-SERVERS session 85.232.240.141 port 3323
set routing-options validation group LUKE-RPKI-SERVERS session 195.136.71.52 port 3323
set routing-options validation group LUKE-RPKI-SERVERS session 2001:1a68:2c:2::141 port 3323
set routing-options validation group LUKE-RPKI-SERVERS session 2a00:4120:8000:a::10 port 3323
which should give you:
root@vmx1> show validation session
Session State Flaps Uptime #IPv4/IPv6 records
85.232.240.141 Up 0 00:00:43 263156/53271
195.136.71.52 Up 0 00:00:43 263156/53271
2001:1a68:2c:2::141 Up 0 00:00:43 263156/53271
2a00:4120:8000:a::10 Up 0 00:00:43 263156/53271
then you need to attach RPKI validation policy into your BGP peers, and put it somewhere in your BGP import policies to execute before you accept anything:
set policy-options community origin-validation-state-invalid members 0x4300:0.0.0.0:2
set policy-options community origin-validation-state-unknown members 0x4300:0.0.0.0:1
set policy-options community origin-validation-state-valid members 0x4300:0.0.0.0:0
set policy-options policy-statement RPKI-POLICY term valid from protocol bgp
set policy-options policy-statement RPKI-POLICY term valid from validation-database valid
set policy-options policy-statement RPKI-POLICY term valid then validation-state valid
set policy-options policy-statement RPKI-POLICY term valid then community add origin-validation-state-valid
set policy-options policy-statement RPKI-POLICY term valid then next policy
set policy-options policy-statement RPKI-POLICY term unknown from protocol bgp
set policy-options policy-statement RPKI-POLICY term unknown from validation-database unknown
set policy-options policy-statement RPKI-POLICY term unknown then validation-state unknown
set policy-options policy-statement RPKI-POLICY term unknown then community add origin-validation-state-unknown
set policy-options policy-statement RPKI-POLICY term unknown then next policy
set policy-options policy-statement RPKI-POLICY term invalid from protocol bgp
set policy-options policy-statement RPKI-POLICY term invalid from validation-database invalid
set policy-options policy-statement RPKI-POLICY term invalid then validation-state invalid
set policy-options policy-statement RPKI-POLICY term invalid then community add origin-validation-state-invalid
set policy-options policy-statement RPKI-POLICY term invalid then reject
and your example BGP import policy should be looking like this:
root@mx> show configuration protocols bgp
group FULL-v4 {
[...]
import [ RPKI-POLICY ACCEPT-ALL ];
export DROP-ALL;
FAQ
can I pass the data from your route server?
Yes, iBGP peers can exchange prefix validation using extended communities. it’s up to you to configure your devices if you want to take advantage of that, as it will cause additional churn in BGP due to validation updates and may increase your CPU and memory load.
can you make the RPKI server using SSH transport instead of TCP RTR?
Not right now, but if enough people will ask for that, I can consider doing just that.
what’s next?
have a good time validating!