How-to – Implement RPKI in 3 simple steps

What’s RPKI?

Although sounding complicated, Resource Public Key Infrastructure is just a way to secure the internet against IPv4/v6 prefix hijacks and leaks. To achieve that, RPKI will serve your router the trusted information so it can check if eBGP learned prefixes are originating from where they are allowed to (first AS in path) and in the format they are allowed to (subnetmask or subnetmask range). It’s first described in RFC6480.

An ROA (Route Origin Authorization) is kind of a signed IRR and basically has following structure:

ASN |  IPv4/v6 Prefix  |  Mask  | (Optional)  Max. Mask  | signature

These are usually stored on specific servers managed by your responsible IRR org.

2-way implementation

There are 2 independent aspects when you implement RPKI:

  • generate ROAs to protect your prefixes. This is usually made on your RIR platform who will act like a “Certification Authority” for it’s managed prefixes.
  • implement RPKI Validation to protect your routing-table. Setup your own Validator server who will download and verify the ROAs from the RIRs. A RTR Server (RPKI-to-Router protocol) is needed to send the ROA lists to your  routers.

You can run RPKI on your routers and take routing decisions based on it without having ROAs. You can also create ROAs for your prefixes without having RPKI implemented in your routing logic or network. Implement both is best.

While the title may refer to a very simple and quick process to implement RPKI, you might want to plan this carefully and study the impact on your routing. Best is to go trough the whole process with a /24 that isn’t used for prod.

Here you can see the Cloudflare RPKI diagram neatly describing the whole setup:

RPKI-diagram

Source: https://blog.cloudflare.com/rpki/

Before we start

Well, yes, deploying it could be relatively quick & easy in a small AS but  make sure you take time to fully understand the implications before taking any productive steps. Read through the tutorial and make your own opinion about how you will benefit from it and what risks it involves for your network.

Step 1: Generate your ROAs

Note: We start with generating ROAs because they are only pushed to update every 8 hours, which means others may see your prefix as Valid (or invalid) only by then. In the meantime it will stay Unkown/NotFound.

Our AS is administrated by RIPE so we’ll generate our ROAs on their infrastructure. This is mostly quick and painless as RIPE is already hosting your IRRs (ASN:IPADDR entries) and monitoring what prefixes/CIDR your AS announces. In the RIPE RPKI dash, you can click on the little magic stick and auto-generate ROAs equal to the actual announcements, also don’t forget to “review & publish” the changes or nothing will happen (ask me how I know that):

createroaripe2

Note: Full procedure is best described here: https://www.ripe.net/manage-ips-and-asns/resource-management/certification/resource-certification-roa-management

You can check your ROAs from different tools. Here some:

Step 2: Deploy Validator3 & RTR-Server

To get the signed ROA Entries from the RIRs you need to install a specific Service. RIPE develops their own tool called Validator Server, which is the one we are using here. There are approx. half a dozen other tools and while I’m sure they’re just as good I am going to stick with what worked painlessly for me.

Install

We got ourselves the 3.1 version on Ubuntu 20.04 LTS. We tried to run the Docker files from toomscj7 in version 3.0 but it was not running smoothly and a bit slow. As the setup is a no-brainer you can just install the Deb packages:

https://github.com/RIPE-NCC/rpki-validator-3/wiki/RIPE-NCC-RPKI-Validator-3-Production

wget https://ftp.ripe.net/tools/rpki/validator3/prod/deb/rpki-validator-3-latest.deb
wget https://ftp.ripe.net/tools/rpki/validator3/prod/deb/rpki-rtr-server-latest.deb

dpkg -i rpki-validator-3-latest.deb
dpkg -i rpki-rtr-server-latest.deb

sudo systemctl enable rpki-validator-3 
sudo systemctl start rpki-validator-3

sudo systemctl enable rpki-rtr-server 
sudo systemctl start rpki-rtr-server

journalctl -f -u rpki-validator-3
journalctl -f -u rpki-rtr-server

Change the Listening IPaddr to 0.0.0.0 from localhost so your routers can access the RTR-service on port 8323:

vim /etc/rpki-rtr-server/application.properties

If you’re not running the service as “rpki” user you’ll have to change it to your current user in:

vim /etc/systemd/system/multi-user.target.wants/rpki-validator-3.service
vim /etc/systemd/system/multi-user.target.wants/rpki-rtr-server.service

systemctl daemon-reload

Add the ARIN database

The ARIN RPKI data is not shipped with the Validators default install. We can include that pretty simply.

Download the ARIN file preformatted for the RIPE Validator:

cd /var/lib/rpki-validator/preconfigured-tals/
wget https://www.arin.net/resources/manage/rpki/arin-ripevalidator.tal

The Validator should add the ARIN repo in the list and download files for it.

Check services

Last quickly check if both are listening to the correct ports/IPs:

apt install net-tools
netstat -tulpen
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 101 20444 877/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 23156 1075/sshd: /usr/sbi
tcp 0 0 127.0.0.1:39843 0.0.0.0:* LISTEN 0 24688 924/containerd
tcp6 0 0 :::22 :::* LISTEN 0 23167 1075/sshd: /usr/sbi
tcp6 0 0 :::8323 :::* LISTEN 0 4129723 579092/java
tcp6 0 0 :::80 :::* LISTEN 0 4120270 578326/apache2
tcp6 0 0 127.0.0.1:8080 :::* LISTEN 0 4116673 577266/java
tcp6 0 0 :::8081 :::* LISTEN 0 4129735 579092/java
udp 0 0 127.0.0.53:53 0.0.0.0:* 101 20443 877/systemd-resolve

Security

Apache http_proxy

To secure the Validator3 webinterface running on port 8080, instead of changing listening interface from localhost to any, it’s probably smarter to just deploy an apache2 proxy.

apt install apache2

Create a new file (you might have to ‘a2dissite 000-default’):

vim /etc/apache2/sites-available/rproxy-rpki-validator.conf
<VirtualHost _default_:*>

<Location "/">
AllowOverride AuthConfig

AuthType Basic
AuthBasicProvider file
AuthUserFile "/etc/httpd/passwd/passwords"
AuthName "Only known users are allowed to make updates"

<LimitExcept GET>
Require valid-user
</LimitExcept>

ProxyPass "http://localhost:8080/"
ProxyPassReverse "http://localhost:8080/"
</Location>

</VirtualHost>

Add a htpasswd file to add authentification when a POST request gets sent to the webserver:

htpasswd -c /etc/httpd/passwd/passwords rpkiadmin

Restart apache and check http://serveripaddress/

systemctl restart apache2

Firewall

Also don’t forget adequate Firewall rules (you might want to restrict that further down):

ufw allow from 192.168.0.0/24 to any port 8323
ufw allow from 10.10.10.0/24 to any port 80
ufw enable
ufw status

Validator3 GUI

Give the server a bit of time to start up, then get to http://IPADDRESS

Now that you are running your own Validator Server you can check the Trust Anchors status and manipulate (validate/invalidate/ignore) all the ROAs. You see that the ARIN anchor you added earlier manually is also in the list:

validator-trustanchors

Last but not least you can browse all the existing ROAs and check their state thanks to an up to date routing table dump so you know what data your routers will get:

validator-announcementpreview

Step 3: configure routers

Configure RPKI

Let’s assume following IP addressing:

  • rpki/rtr server IP: 10.10.10.1 – RTR port 8323
  • RT1 IP: 192.168.0.255 – is an iBGP router
  • RT2 IP: 192.168.0.254 – is connected to an eBGP Upstream and sends those routes to RT1 via iBGP

Huawei VRP

Configure the router to get ROAs from your RTR-server:

system-view
  rpki
    session 10.10.10.1
    tcp port 8323

Configure the BGP process to import RPKI information into the BGP routing table:

bgp 65000
  prefix origin-validation enable
  bestroute origin-as-validation allow-invalid

Commit, then check the session is established:

display rpki session 10.10.10.1 verbose
RPKI server is 10.10.10.1, port 8323
RPKI current state: Established, Age: 04m08s
VPN-instance name: _public_
Local host: 192.168.0.255, Local port: 49616
Remote host: 10.10.10.1, Remote port: 8323
Refresh time : 1800
Aging time : 3600
Session ID : 4686
Serial number : 7
Session Statistics:
IPv4 record : 150836
IPv6 record : 24919

Finally check the database:

display rpki table
Total number of RPKI record entry : 150845
Network Maxlen OriginAS Session VPN
1.0.0.0/24 24 13335 10.10.10.1 _public_
1.1.1.0/24 24 13335 10.10.10.1 _public_
1.6.0.0/22 24 9583 10.10.10.1 _public_
1.6.100.0/22 24 9583 10.10.10.1 _public_

...

You can see the routes getting a RPKI status now:

disp bgp routing-table
BGP Local router ID is 192.168.0.255
Status codes: * - valid, > - best, d - damped, x - best external, a - add path,
h - history, i - internal, s - suppressed, S - Stale
Origin : i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V - valid, I - invalid, N - not-found


Total Number of Routes: 2470702
Network NextHop MED LocPrf PrefVal Path/Ogn

*>i V 1.0.0.0/24 192.168.0.254 0 60 0 13335i
* i V 192.168.0.254 0 60 0 13335i
* i V 192.168.0.254 0 29 0 13335i
* i V 192.168.0.254 0 29 0 13335i
*>i V 1.0.4.0/22 192.168.0.254 0 60 0 15412 4826 38803 56203i
...

https://support.huawei.com/enterprise/en/doc/EDOC1100055018/36627f51/improving-bgp-security#dc_vrp_bgp_cfg_3099

Cisco IOS

Configure the router to get ROAs from your RTR-server:

router bgp 65000
  bgp rpki server tcp 10.10.10.1 port 8323 refresh 180

Configure the BGP process to import RPKI information into the BGP routing table:

address-family ipv4 unicast
bgp bestpath prefix-validate allow-invalid

If you want to get the information without altering the usual route-selection process:

bgp bestpath prefix-validate disable

Finally check the database:

show ip bgp rpki table

Juniper JUNOS

Juniper supports RPKI. I couldn’t test the configuration by myself so I’ll refer to the Juniper RPKI config guide here, it’s pretty detailed and should answer all settings we also covered in this how-to: https://www.juniper.net/documentation/en_US/junos/topics/topic-map/bgp-origin-as-validation.html#jd0e658

Extreme SLX-OS

Unfortunatly, Extreme doesn’t support RPKI –  for now. I would add the configuration part in this tutorial once this has changed (because it has to be in the pipeline). UPDATE: it has been confirmed under development and will be available in a SLX-OS 20.2.x version, which I reckon could be next month or in 2 years).

Configure route-maps

Best pratice is not the implemented default behavior of dropping all RPKI invalid marked routes but to accept all of them, even invalids but prioritize the Valid routes, then the Unknown and as a last resort, the Invalid routes.

Huawei VRP

Set the route-map to allow all routes but to implement that logic:

route-policy RPKI-IN permit node 10
  if-match rpki origin-as-validation invalid
  apply local-preference 50
!
route-policy RPKI-IN permit node 20
 if-match rpki origin-as-validation not-found
 apply local-preference 100
!
route-policy RPKI-IN permit node 30
 if-match rpki origin-as-validation valid
 apply local-preference 200
!
route-policy RPKI-IN permit node 40
!

Apply the route-map to your incoming eBGP sessions:

peer 1.2.3.4 route-policy RPKI-IN import

Cisco IOS

Set the route-map to allow all routes but to implement that logic:

route-map RPKI-IN permit 10
  match rpki invalid
  set local-preference 50
!
route-map RPKI-IN permit 20
  match rpki not-found
  set local-preference 100
!
route-map RPKI-IN permit 30
  match rpki valid
  set local-preference 200
!
route-map RPKI-IN permit 40
!

Apply the route-map to your incoming eBGP sessions:

neighbor 1.2.3.4 route-map RPKI-IN in

Sending the validation-state to iBGP peers

Depending on your network stucture you may want to share the validation-state along with the eBGP learned routes to your iBGP peers. This has been implemented through well known communities (extended) that are sent with the route.

Huawei VRP

bgp 65000
  peer 192.168.0.254 as-number 65000
  peer 192.168.0.254 description "iBGP peering to RouterX"
  ipv4-family unicast
  peer 192.168.0.254 advertise-ext-community
  peer 192.168.0.254 advertise origin-as-validation

Cisco IOS

router bgp 65000
 neighbor 192.168.0.254 remote-as 65000
 neighbor 192.168.0.254 description "iBGP peering to RouterX"
 address-family ipv4 unicast
 neighbor 192.168.0.254 send-community extended
 neighbor 192.168.0.254 announce rpki state

Consolidating your RPKI infrastructure

Restrict Validator3 WebGUI access

While it’s obvious firewall rules are important to protect access to the Validator, the proxy + .htaccess login  on the Validator’s webinterface is a first step. Ideally upgrade that access via HTTPS 443 instead of plain HTTP 80, even if the certificates are self-signed.

NGINX Proxy: https://github.com/RIPE-NCC/rpki-validator-3/wiki/Run-the-RPKI-Validator-UI-and-API-behind-an-nginx-proxy

Apache2 Proxy: https://github.com/RIPE-NCC/rpki-validator-3/wiki/Running-the-RPKI-Validator-UI-and-API-behind-an-apache-proxy

Self-signed Apache2 SSL config: https://www.linux.com/training-tutorials/creating-self-signed-ssl-certificates-apache-linux/

Run multiple instances of Validator3+RTR-Server

Connecting your routers to multiple geo-spreaded RTR-servers seems like a wise thing to do to enforce redondancy and avoid altered RPKI table which might lead to at least suboptimal iBGP routing, depending on how strict your routing policy is about invalid and NotFound/Unkown routes.

RTR-Protocol security

You might have already noted that this way of transfering roa’s doesn’t come with any kind of native secure data transmission mecanism. There is an MD5 encrypting mecanism but my guess is it’s been implemented to give some network engineer a year spare for ISO 27001. I’ll explore this subject in another post as I didn’t went through all the options available in 2020.

Links:

Thanks RIPE for the tools & well documented Validator: https://github.com/RIPE-NCC/rpki-validator-3

https://github.com/RIPE-NCC/rpki-validator-3/wiki/RIPE-NCC-RPKI-Validator-3-Production

Cisco RPKI Config document: https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/iproute_bgp/configuration/15-s/irg-15-s-book/irg-origin-as.html

Huawei Improve BGP security: https://support.huawei.com/enterprise/en/doc/EDOC1100028526?section=j062&topicName=improving-bgp-security#dc_vrp_bgp_cfg_3099

2 thoughts on “How-to – Implement RPKI in 3 simple steps

Leave a comment