Classroom Glossary Public page

Lab 3: RPKI Deployment -- ROA States and Reject-Invalid Policy

336 words

Week: 3 -- Internet-Scale BGP
Points: 20
Time estimate: 90 min lab + 3 hr independent
Deliverable: lab-3-report.md


Objectives

  1. Deploy Routinator and sync against live RIR RPKI repositories.
  2. Query the Routinator REST API for ROA validity across a set of prefixes.
  3. Configure FRR to reject BGP routes with Invalid RPKI state via RTR.
  4. Simulate a prefix hijack and verify FRR rejects it as Invalid.

Part A: Routinator Deployment and ROA Sync (20 min)

# Start Routinator
docker run -d \
  --name routinator \
  -p 3323:3323 \
  -p 8323:8323 \
  nlnetlabs/routinator

# Watch sync progress
docker logs -f routinator 2>&1 | grep -E "valid|invalid|Updating"

# Wait ~5 minutes for initial sync; verify
curl http://localhost:8323/api/v1/status | python3 -m json.tool

Verify ROA database is populated:

# Query total valid ROAs
curl "http://localhost:8323/api/v1/status" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); print('Valid ROAs:', d.get('valid_roas', 'N/A'))"

Part B: ROA Validity Queries (30 min)

Query the Routinator REST API for the validity state of specific prefixes. Use these test cases:

# Test each prefix -- record the validity state
PREFIXES=(
  "8.8.8.0/24/15169"          # Google DNS -- should be Valid
  "1.1.1.0/24/13335"          # Cloudflare DNS -- should be Valid
  "192.0.2.0/24/64512"        # Documentation prefix -- should be NotFound
  "8.8.8.0/24/64512"          # Google prefix, wrong AS -- should be Invalid
  "8.8.8.0/25/15169"          # Google /24 more-specific, same AS -- depends on maxLength
)

for pao in "${PREFIXES[@]}"; do
    IFS='/' read -r prefix len asn <<< "$pao"
    result=$(curl -s "http://localhost:8323/api/v1/validity/AS${asn}/${prefix}/${len}")
    state=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('validated_route',{}).get('validity',{}).get('state','ERROR'))" 2>/dev/null)
    echo "${prefix}/${len} AS${asn}: ${state}"
done

Record the validity state for each entry. Pay particular attention to the more-specific query: does the /25 announcement with the correct AS receive Valid or Invalid state? Why?


Part C: FRR RTR Integration and Reject-Invalid Policy (40 min)

Configure an FRR router to connect to Routinator via RTR and apply a route-map that rejects Invalid routes:

# Add FRR container to lab network (reuse Lab 1 infrastructure or deploy new)
docker run -d --name bgp-rtr \
  --cap-add NET_ADMIN \
  frrouting/frr:v9.1.0

FRR configuration with RPKI:

! FRR config for bgp-rtr
!
rpki
 rpki polling_period 3600
 rpki cache 172.17.0.2 3323 preference 1
 exit
!
router bgp 65100
 bgp router-id 10.99.0.1
 !
 neighbor 10.99.0.2 remote-as 65200
 !
 address-family ipv4 unicast
  neighbor 10.99.0.2 activate
  neighbor 10.99.0.2 route-map rm-rpki-filter in
 exit-address-family
!
route-map rm-rpki-filter deny 5
 match rpki invalid
!
route-map rm-rpki-filter permit 10
!

Verify RPKI session is established:

docker exec bgp-rtr vtysh -c "show rpki prefix-table"
docker exec bgp-rtr vtysh -c "show rpki cache-connection"

Simulate a prefix hijack: configure a second FRR container (bgp-hijacker) that announces a prefix with an invalid origin AS. Verify the bgp-rtr router rejects it:

# bgp-hijacker announces 8.8.8.0/24 from AS 64512 (not the rightful owner AS15169)
# bgp-rtr should reject this as Invalid per the route-map

docker exec bgp-rtr vtysh -c "show bgp ipv4 unicast 8.8.8.0/24"
# Expected: "Route has been filtered by route-map rm-rpki-filter" or not in RIB

Lab Report

Create lab-3-report.md with:

  1. Routinator status output: total valid ROAs, sync time
  2. ROA validity table (all 5 test cases; validity state for each)
  3. Explanation of the /25 more-specific result: is it Valid or Invalid, and why?
  4. show rpki prefix-table output (snippet showing 8.8.8.0/24 entry)
  5. Evidence that the hijacked prefix is rejected (show bgp output or RIB state)
  6. One-paragraph analysis: "Pakistan Telecom's 2008 YouTube hijack -- would RPKI have prevented it? What would the ROA state have been for 208.65.153.0/24 announced from AS17557?"

Grading

Component Points
ROA validity table: all 5 entries correct 6
/25 more-specific explanation: maxLength correctly explained 3
RTR session: show rpki prefix-table populates correctly 5
Hijack simulation: Invalid route rejected from RIB 4
Pakistan Telecom paragraph: historically accurate and technically specific 2
Total 20