Chapter: 2 (Routing II: BGP)
Duration: 90 minutes
Tools: Containerlab, FRRouting, vtysh, Wireshark, Routinator
Points: 10
Objectives
- Configure eBGP and iBGP sessions in a 3-AS topology
- Observe BGP path selection using LOCAL_PREF and AS_PATH manipulation
- Simulate a BGP prefix hijack and observe the impact on the RIB
- Validate RPKI ROA lookup against a live prefix
Topology
AS 65001 (your network) AS 65002 (upstream ISP) AS 65003 (peer/attacker)
R1 ----10.1.1.0/30---- R2 ----10.2.2.0/30---- R3
192.168.10.0/24 owned by AS 65001
AS 65001 internal:
R1 (RR client) ---- R5 (Route Reflector) ---- R4 (RR client)
Setup
# topo-bgp3as.clab.yml
name: bgp3as
topology:
nodes:
r1:
kind: linux
image: frrouting/frr:latest
r2:
kind: linux
image: frrouting/frr:latest
r3:
kind: linux
image: frrouting/frr:latest
links:
- endpoints: ["r1:eth1", "r2:eth1"] # eBGP AS65001 <-> AS65002
- endpoints: ["r2:eth2", "r3:eth1"] # eBGP AS65002 <-> AS65003
Configure FRR on each router:
# R1 (AS 65001)
docker exec -it clab-bgp3as-r1 vtysh
configure terminal
interface lo
ip address 192.168.10.1/32
interface eth1
ip address 10.1.1.1/30
router bgp 65001
bgp router-id 10.1.1.1
network 192.168.10.0/24
neighbor 10.1.1.2 remote-as 65002
# R2 (AS 65002 - transit AS)
configure terminal
interface eth1
ip address 10.1.1.2/30
interface eth2
ip address 10.2.2.1/30
router bgp 65002
bgp router-id 10.1.1.2
neighbor 10.1.1.1 remote-as 65001
neighbor 10.2.2.2 remote-as 65003
# R3 (AS 65003)
configure terminal
interface eth1
ip address 10.2.2.2/30
router bgp 65003
bgp router-id 10.2.2.2
neighbor 10.2.2.1 remote-as 65002
Exercises
Exercise 1: Verify eBGP Peering (10 min)
docker exec clab-bgp3as-r1 vtysh -c "show ip bgp summary"
docker exec clab-bgp3as-r3 vtysh -c "show ip bgp"
Record:
- What is the state of each BGP session (Established)?
- Does R3 see 192.168.10.0/24 in its RIB? What AS_PATH does it show?
- How many prefixes has R1 advertised to R2?
Exercise 2: LOCAL_PREF Manipulation (20 min)
Add a second path: add a direct eBGP link between R1 (AS 65001) and R3 (AS 65003).
# Add to links section:
- endpoints: ["r1:eth2", "r3:eth2"]
Reconfigure:
# R1: add second eBGP neighbor (AS 65003)
router bgp 65001
neighbor 10.3.3.2 remote-as 65003
neighbor 10.3.3.2 route-map PREFER_65002 in
!
route-map PREFER_65002 permit 10
set local-preference 200
# Verify path selection on R1
docker exec clab-bgp3as-r1 vtysh -c "show ip bgp"
Record:
- How many paths does R1 have to R3's prefix (if any)?
- Which path is selected as best? What LOCAL_PREF value determines this?
- Change the LOCAL_PREF to 50 on one path; which path is now best?
Exercise 3: AS_PATH Prepending (15 min)
Configure R1 to prepend its own AS on outbound advertisements to AS 65003:
route-map PREPEND_TO_65003 permit 10
set as-path prepend 65001 65001 65001
!
router bgp 65001
neighbor 10.3.3.2 route-map PREPEND_TO_65003 out
# Check what AS_PATH R3 now sees for 192.168.10.0/24 via R1
docker exec clab-bgp3as-r3 vtysh -c "show ip bgp 192.168.10.0/24"
Record:
- What is the AS_PATH length R3 sees via R1 now?
- Does R3 prefer the path via R2 or via R1? Why?
Exercise 4: Sandboxed Prefix Hijack (20 min)
Instructor demo / supervised exercise. This exercise should be run only in the isolated Containerlab sandbox.
Configure AS 65003 to originate (hijack) AS 65001's prefix 192.168.10.0/24:
docker exec -it clab-bgp3as-r3 vtysh
configure terminal
router bgp 65003
network 192.168.10.0/24
Observe the result:
# Check R2's RIB: which AS_PATH does it prefer for 192.168.10.0/24?
docker exec clab-bgp3as-r2 vtysh -c "show ip bgp 192.168.10.0/24"
Record:
- Does R2 now have two paths to 192.168.10.0/24? Which one does it prefer?
- If R3 is one hop closer to R2 than R1, which path wins based on AS_PATH length?
- How would RPKI prevent this hijack? (What would the ROA for 192.168.10.0/24 specify?)
Remove the hijack before proceeding:
docker exec -it clab-bgp3as-r3 vtysh -c "configure terminal" <<EOF
router bgp 65003
no network 192.168.10.0/24
EOF
Exercise 5: RPKI ROA Lookup (15 min)
Using Routinator (pre-installed per SETUP.md):
# Start Routinator if not already running
routinator server --rtr 127.0.0.1:3323 --http 127.0.0.1:9556 &
sleep 10 # allow initial sync
# Look up Cloudflare's prefix: should be Valid
curl -s "http://127.0.0.1:9556/api/v1/validity/AS13335/1.1.1.0%2F24" | jq .
# Look up Google's prefix
curl -s "http://127.0.0.1:9556/api/v1/validity/AS15169/8.8.8.0%2F24" | jq .
# Simulate a hijack lookup: Rostelecom announcing Cloudflare's space
curl -s "http://127.0.0.1:9556/api/v1/validity/AS12389/1.1.1.0%2F24" | jq .
Record:
- What validity state does Routinator return for each query (valid/invalid/not-found)?
- What JSON fields describe the matched VRP (Validated ROA Payload)?
- Why does the AS12389 / 1.1.1.0/24 query return "invalid"?
Lab Report
Answer the following (1-2 pages):
- In BGP's decision process, why is LOCAL_PREF evaluated before AS_PATH? What does this imply for traffic engineering?
- Explain how the sandboxed prefix hijack would affect real Internet traffic if executed on a global BGP router (not in a sandbox). Who would be affected?
- RPKI prevents origin hijacks. What does it NOT prevent? (Hint: consider AS_PATH prepending.)
Cleanup
containerlab destroy -t topo-bgp3as.clab.yml
Grading (10 points)
| Item | Points |
|---|---|
| All BGP sessions Established; R3 receives 192.168.10.0/24 via correct AS_PATH | 2 |
| LOCAL_PREF manipulation: correct path selected; explanation is accurate | 2 |
| AS_PATH prepending: correct; explanation of effect on R3's path preference | 2 |
| Prefix hijack exercise completed; correctly explains RPKI mitigation | 2 |
| RPKI lookups correct; valid/invalid/not-found explained with VRP fields | 2 |