BGP Prefix Origin AS Validation with RPKI

Resource Public Key Infrastructure (RPKI) is used to validate whether certain prefixes belong to the AS that advertises them. Before you continue with this lesson, make sure you have a good understanding of what BGP route leaking is and how RPKI can help.

In this lesson, we’ll configure an RPKI validator using Docker and make a Cisco IOS XE router validated prefixes. We’ll see how the router deals with valid, invalid, and not found prefixes. You’ll also learn how to forward this RPKI state to other routers.




Configuration

Let’s start with our topology:

Cisco Bgp Rpki Lab Topology

Let me explain what we have:

  • Routinator is open-source RPKI relying party software (RPKI validator) which downloads and verifies RPKI data.
  • R1 and R2 are in AS 12 and will use RPKI to validate routes.
  • R4 and R5 advertise prefixes to R1 through eBGP.
  • R3 is only needed so I can reach Routinator from R1.

I use CSR1000v routers running Cisco IOS Software [Amsterdam], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 17.3.6.

Configurations

Want to take a look for yourself? Here, you will find the startup configuration of each device.

R1

hostname R1
!
interface GigabitEthernet1
 ip address 192.168.1.1 255.255.255.0
!
interface GigabitEthernet2
 ip address 192.168.12.1 255.255.255.0
!
router bgp 12
 neighbor 192.168.1.4 remote-as 8075
 neighbor 192.168.1.5 remote-as 29256
 neighbor 192.168.12.2 remote-as 12
 neighbor 192.168.12.2 next-hop-self
 neighbor 192.168.12.2 send-community extended
 neighbor 192.168.12.2 announce rpki state
!
ip route 10.65.90.0 255.255.255.0 192.168.1.3
!
end

R2

hostname R2
!
interface GigabitEthernet1
 ip address 192.168.12.2 255.255.255.0
!
router bgp 12
 neighbor 192.168.12.1 remote-as 12
!
end

R4

hostname R4
!
interface Loopback0
 ip address 4.128.0.4 255.240.0.0
!
interface Loopback1
 ip address 5.0.0.5 255.255.224.0
!
interface Loopback2
 ip address 44.44.44.44 255.255.255.255
!
interface GigabitEthernet1
 ip address 192.168.1.4 255.255.255.0
!
router bgp 8075
 network 4.128.0.0 mask 255.240.0.0
 network 5.0.0.0 mask 255.255.224.0
 network 44.44.44.44 mask 255.255.255.255
 neighbor 192.168.1.1 remote-as 12
!
end

R5

hostname R5
!
interface Loopback0
 ip address 5.0.0.5 255.255.224.0
!
interface GigabitEthernet1
 ip address 192.168.1.5 255.255.255.0
!
router bgp 29256
 network 5.0.0.0 mask 255.255.224.0
 neighbor 192.168.1.1 remote-as 12
 neighbor 192.168.1.1 route-map AS_PATH_PREPEND out
!
route-map AS_PATH_PREPEND permit 10 
 set as-path prepend 29256 29256
!
end

docker-compose.yml

version: '3'

services:
  routinator:
    image: nlnetlabs/routinator
    container_name: routinator
    restart: unless-stopped
    ports:
      - "3323:3323"
      - "8323:8323"

Routinator

My docker container with Routinator is up and running.

If you don’t want to lab this up but try Routinator anyway, try RIPE’s hosted Routinator instance.

The GUI listens on HTTP TCP port 8323. Let’s have a look. Under Prefix Check, you can enter a prefix and AS number to see whether it’s valid, invalid, or not found:

Routinator Prefix Check Valid

This prefix checks out. Under Metrics, you can see how many Route Origin Authorizations (ROA) there are per Regional Internet Registry (RIR) and how many have been validated (VRPs):

Routinator Metrics

Under Repositories, you can see all the RPKI repositories from the different RIRs:

Routinator Repositories

Under Connections, you see how Routinator communicates with the repositories. This can be RPKI Repository Delta Protocol (RRDP) or Rsync:

Routinator Connections

Our Routinator docker instance is working well. There’s nothing we have to configure here.

Router

Let’s configure our router. Before I enable route validation, I’ll add this command on R1:

R1(config)#router bgp 12
R1(config-router)#bgp bestpath prefix-validate disable

This will ensure that once I connect to Routinator, R1 will check prefixes, but it won’t change the BGP table yet.

Next, I’ll connect to Routinator:

R1(config)#router bgp 12
R1(config-router)#bgp rpki server tcp 10.65.90.50 port 3323 refresh 300

Routinator uses TCP port 3323 for the RPKI-to-Router protocol (RTR).

Once connected, the router will now download a list of prefixes and the ASes they belong to. The server will send incremental updates, but the router can query the server for a refresh as well. I set the refresh time to 300 seconds, but on a production network, once every hour is probably more than enough.

You can configure multiple servers. The router will download records from both servers and stores a copy for each server. This is recommended so you have redundancy.

Let’s check if R1 is connected to Routinator:

R1#show ip bgp rpki servers 
BGP SOVC neighbor is 10.65.90.50/3323 connected to port 3323
Flags 64, Refresh time is 300, Serial number is 135, Session ID is 11494
InQ has 0 messages, OutQ has 0 messages, formatted msg 2
Session IO flags 3, Session flags 4008
 Neighbor Statistics:
  Prefixes 500539
  Connection attempts: 20
  Connection failures: 18
  Errors sent: 0
  Errors received: 0
          
Connection state is ESTAB, I/O status: 1, unread input bytes: 0            
Connection is ECN Disabled, Mininum incoming TTL 0, Outgoing TTL 255
Local host: 192.168.1.1, Local port: 53929
Foreign host: 10.65.90.50, Foreign port: 3323
Connection tableid (VRF): 0
Maximum output segment queue size: 50

Enqueued packets for retransmit: 0, input: 0  mis-ordered: 0 (0 bytes)

Event Timers (current time is 0x3F80132):
Timer          Starts    Wakeups            Next
Retrans             4          1             0x0
TimeWait            0          0             0x0
AckHold          7068          4             0x0
SendWnd             0          0             0x0
KeepAlive        8171          0       0x3F80628
GiveUp              0          0             0x0
PmtuAger            1          0       0x3FAACF2
DeadWait            0          0             0x0
Linger              0          0             0x0
ProcessQ            0          0             0x0

iss:  341721583  snduna:  341721604  sndnxt:  341721604
irs: 2065660931  rcvnxt: 2076787572

sndwnd:  64220  scale:      0  maxrcvwnd:  16384
rcvwnd:  15652  scale:      0  delrcvwnd:    732

SRTT: 234 ms, RTTO: 2984 ms, RTV: 2750 ms, KRTT: 0 ms
minRTT: 1 ms, maxRTT: 1000 ms, ACK hold: 200 ms
uptime: 427282 ms, Sent idletime: 14052 ms, Receive idletime: 14050 ms 
Status Flags: active open
Option Flags: keepalive running, nagle, path mtu capable
IP Precedence value : 6

Datagrams (max data segment is 1460 bytes):
Rcvd: 8151 (out of order: 0), with data: 8124, total data bytes: 11126640
Sent: 8215 (retransmit: 1, fastretransmit: 0, partialack: 0, Second Congestion: 0), with data: 2, total data bytes: 20

 Packets received in fast path: 0, fast processed: 0, slow path: 0
 fast lock acquisition failures: 0, slow path: 0
TCP Semaphore      0x7F272B14F018  FREE

We are connected. The number of prefixes (500539) is something to keep an eye on. It can take a few minutes for the router to download everything. We can see a list of all prefixes and AS numbers using this command:

R1#show ip bgp rpki table 
367569 BGP sovc network entries using 58811040 bytes of memory
407525 BGP sovc record entries using 13040800 bytes of memory

Network              Maxlen  Origin-AS  Source  Neighbor
1.0.0.0/24           24      13335      0       10.65.90.50/3323
1.0.4.0/24           24      38803      0       10.65.90.50/3323
1.0.4.0/22           22      38803      0       10.65.90.50/3323
1.0.5.0/24           24      38803      0       10.65.90.50/3323
1.0.6.0/24           24      38803      0       10.65.90.50/3323
1.0.7.0/24           24      38803      0       10.65.90.50/3323
1.0.64.0/18          18      18144      0       10.65.90.50/3323
1.1.1.0/24           24      13335      0       10.65.90.50/3323
1.1.4.0/22           22      4134       0       10.65.90.50/3323
1.1.16.0/20          20      4134       0       10.65.90.50/3323
1.2.9.0/24           24      4134       0       10.65.90.50/3323
1.2.10.0/24          24      4134       0       10.65.90.50/3323
1.2.11.0/24          24      4134       0       10.65.90.50/3323
1.2.12.0/22          22      4134       0       10.65.90.50/3323
1.3.0.0/16           16      4134       0       10.65.90.50/3323
1.6.0.0/22           24      9583       0       10.65.90.50/3323

This is looking good. Let’s find out how R1 uses this information by checking the BGP table:

R1#show ip bgp
BGP table version is 10, local router ID is 192.168.12.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
              t secondary path, L long-lived-stale,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>   4.128.0.0/12     192.168.1.4              0             0 8075 i
 *>   5.0.0.0/19       192.168.1.4              0             0 8075 i
 *                     192.168.1.5              0             0 29256 29256 29256 i
 *>   44.44.44.44/32   192.168.1.4              0             0 8075 i

Three prefixes have been selected as the best path. Take a closer look at 5.0.0.0/19. I advertise this prefix from R4 and R5, but I used AS path prepending on R5 so that R4 becomes the best path.

This is what the routing table looks like:

R1#show ip route bgp

      4.0.0.0/12 is subnetted, 1 subnets
B        4.128.0.0 [20/0] via 192.168.1.4, 00:07:29
      5.0.0.0/19 is subnetted, 1 subnets
B        5.0.0.0 [20/0] via 192.168.1.4, 00:03:03
      44.0.0.0/32 is subnetted, 1 subnets
B        44.44.44.44 [20/0] via 192.168.1.4, 00:14:35

Nothing new here. This is because of the bgp bestpath prefix-validate disable command we added earlier. Let’s get rid of it so you can see the difference:

R1(config)#router bgp 12
R1(config-router)#no bgp bestpath prefix-validate disable

This changes the BGP table:

R1#show ip bgp 
BGP table version is 11, local router ID is 192.168.12.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
              t secondary path, L long-lived-stale,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
V*>   4.128.0.0/12     192.168.1.4              0             0 8075 i
I*    5.0.0.0/19       192.168.1.4              0             0 8075 i
V*>                    192.168.1.5              0             0 29256 29256 29256 i
N*>   44.44.44.44/32   192.168.1.4              0             0 8075 i

This time, we see something different:

  • 4.128.0.0/12 from AS 8075 is a valid prefix.
  • 5.0.0.0/19 from AS 8075 is an invalid prefix.
  • 5.0.0.0/19 from AS 29256 is a valid prefix.
  • 44.44.44.44/32 from AS 8075 is a prefix that is not found.

This influences the BGP best path selection. R1 selects the longer path through R5 as the best path to get to 5.0.0.0/19. Here’s the routing table:

R1#show ip route bgp

      4.0.0.0/12 is subnetted, 1 subnets
B        4.128.0.0 [20/0] via 192.168.1.4, 00:08:50
      5.0.0.0/19 is subnetted, 1 subnets
B        5.0.0.0 [20/0] via 192.168.1.5, 00:00:32
      44.0.0.0/32 is subnetted, 1 subnets
B        44.44.44.44 [20/0] via 192.168.1.4, 00:15:56

Let’s check all prefixes in the RPKI table. Here’s the first one:

R1#show ip bgp 4.128.0.0/12 | include RPKI
      path 7F2732260020 RPKI State valid

The 4.128.0.0/12 from AS 8075 is a valid prefix. We have two entries for 5.0.0.0/19:

R1#show ip bgp 5.0.0.0/19
BGP routing table entry for 5.0.0.0/19, version 11
Paths: (2 available, best #2, table default)
  Advertised to update-groups:
     5          6         
  Refresh Epoch 1
  8075
    192.168.1.4 from 192.168.1.4 (44.44.44.44)
      Origin IGP, metric 0, localpref 100, valid, external
      path 7F27322601D0 RPKI State invalid
      rx pathid: 0, tx pathid: 0
      Updated on Jan 16 2024 10:08:41 UTC
  Refresh Epoch 1
  29256 29256 29256
    192.168.1.5 from 192.168.1.5 (5.0.0.5)
      Origin IGP, metric 0, localpref 100, valid, external, best
      path 7F2732260140 RPKI State valid
      rx pathid: 0, tx pathid: 0x0
      Updated on Jan 16 2024 10:08:40 UTC

Above, you can see that prefix 5.0.0.0/19 from AS 8075 is invalid and the one from AS 29256 is valid.

Let’s check the last prefix:

R1#show ip bgp 44.44.44.44/32 | include RPKI
      path 7F27322600B0 RPKI State not found

This prefix is not found because there is no ROA for it.

Invalid Prefixes

Let’s take a closer look at that invalid prefix. By default, a router refuses to use invalid prefixes. We can test this by shutting down R5 for now:

R5(config)#interface GigabitEthernet 1
R5(config-if)#shutdown

R1 now only has the invalid prefix 5.0.0.0/19 from AS 8075:

R1#show ip bgp 5.0.0.0/19
BGP routing table entry for 5.0.0.0/19, version 0
Paths: (1 available, no best path)
  Flag: 0x4100
  Not advertised to any peer
  Refresh Epoch 2
  8075
    192.168.1.4 from 192.168.1.4 (44.44.44.44)
      Origin IGP, metric 0, localpref 100, valid, external
      path 7F2732260140 RPKI State invalid
      rx pathid: 0, tx pathid: 0
      Updated on Jan 16 2024 10:47:03 UTC

R1 refuses to use this prefix:

R1#show ip route 5.0.0.0
% Network not in table

However, it is possible to tell R1 that you do want to use invalid prefixes. Here’s how:

R1(config)#router bgp 12
R1(config-router)#bgp bestpath prefix-validate allow-invalid

Because it’s the only option, R1 now uses this as the best path:

R1#show ip bgp 5.0.0.0/19
BGP routing table entry for 5.0.0.0/19, version 4
Paths: (1 available, best #1, table default)
  Advertised to update-groups:
     10        
  Refresh Epoch 2
  8075
    192.168.1.4 from 192.168.1.4 (44.44.44.44)
      Origin IGP, metric 0, localpref 100, valid, external, best
      path 7F2732260140 RPKI State invalid
      rx pathid: 0, tx pathid: 0x0
      Updated on Jan 16 2024 10:47:03 UTC

And installs it in the routing table:

R1#show ip route 5.0.0.0
Routing entry for 5.0.0.0/19, 1 known subnets
B        5.0.0.0 [20/0] via 192.168.1.4, 00:00:33

Let’s enable R5 again:

R5(config)#interface GigabitEthernet 1
R5(config-if)#no shutdown

Route-map

We can also use a route-map to match the different RPKI states and change one of the BGP attributes. For example, local preference. Here’s how to do it:

R1(config)#route-map RPKI permit 10
R1(config-route-map)#match rpki valid
R1(config-route-map)#set local-preference 200

R1(config)#route-map RPKI permit 20
R1(config-route-map)#match rpki not-found
R1(config-route-map)#set local-preference 100

R1(config)#route-map RPKI permit 30
R1(config-route-map)#match rpki invalid
R1(config-route-map)#set local-preference 50

R1(config)#route-map RPKI permit 40

We’ll give valid prefixes the highest local preference (200), not found the second best (100), and invalid prefixes the worst (50). Don’t forget to add an empty statement or your router will deny everything else. Let’s attach this route-map to R4 and R5:

R1(config)#router bgp 12
R1(config-router)#neighbor 192.168.1.4 route-map RPKI in
R1(config-router)#neighbor 192.168.1.5 route-map RPKI in

Let’s speed things up and reset the BGP neighbor adjacencies:

We're Sorry, Full Content Access is for Members Only...

If you like to keep on reading, Become a Member Now!

  • Learn any CCNA, CCNP and CCIE R&S Topic. Explained As Simple As Possible.
  • Try for Just $1. The Best Dollar You’ve Ever Spent on Your Cisco Career!
  • Full Access to our 800 Lessons. More Lessons Added Every Week!
  • Content created by Rene Molenaar (CCIE #41726)
527 Sign Ups in the last 30 days
satisfaction-guaranteed

  • 100% Satisfaction Guaranteed!
  • You may cancel your monthly membership at any time.
  • No Questions Asked!

Forum Replies

  1. Hello Dears,

    Usually when it comes to RPKI, we just check the online tools such as Routinator as you mentioned to check if the route is valid or not,

    Now could you please explain why we need to configure it up in the routers? does it going to help and not advertise those routes when is not valid or not found to the peer routers?

    also this shouldn’t be router bgp 12 or it is okay ?

    https://cdn-forum.networklessons.com/uploads/default/original/2X/0/0eb3524390197451ba31ebe8e8ae817eeb228047.png

    And please why prefix 44.44.44.44/32 is not found route?

  2. Hello Ahmedlmad

    The validity of routes is something that is dynamic, and it can change. Checking the validity of routes on an online tool without any additional action is useful, but information can become out of date. For this reason, by configuring the routers to dynamically chec

    ... Continue reading in our forum

  3. Hello Sepideh

    Port 3323 is the port used by the RPKI-to-Router protocol (RTR). This is the protocol used to allow BGP routers to communicate with the Routinator server. So for communication between the BGP routers and Routinator, 3323 is the correct TCP port.

    The 8323 port is used to connect to the GUI of the Routinator. So from your PC, on a web browser you would include the port number to be used. For example, in this lesson, Rene used: docker1.nwl.ai:8323.

    These port numbers are reaffirmed at this related Routinator documentation:
    https://routinator.docs

    ... Continue reading in our forum

1 more reply! Ask a question or join the discussion by visiting our Community Forum