Add all 8 course modules with converted markdown links
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
144
modules/01-isis.md
Normal file
144
modules/01-isis.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Module 1: The Underlay — IS-IS
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Next**: [Module 2: MPLS](02-mpls.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*IS-IS Level 2 domain — all P and PE routers with NET addresses and link subnets*
|
||||
|
||||
---
|
||||
|
||||
## Why IS-IS and Not OSPF?
|
||||
|
||||
Every major ISP on the planet runs IS-IS as their IGP (Interior Gateway Protocol). Here's why:
|
||||
|
||||
1. **IS-IS runs on Layer 2** — it doesn't need IP to function. OSPF runs on top of IP. This means IS-IS is more resilient; if your IP config is broken, IS-IS still forms adjacencies.
|
||||
2. **Protocol-agnostic** — IS-IS carried IPv4, IPv6, and MPLS labels long before OSPF could. It was designed to carry *any* protocol (it originally carried CLNS).
|
||||
3. **Scales better** — IS-IS uses a flat TLV (Type-Length-Value) structure, making it trivially extensible. Adding Segment Routing support to IS-IS was easy. Adding it to OSPF required new LSA types and was messy.
|
||||
4. **Faster convergence** — IS-IS partial route calculations (PRC) are more efficient than OSPF's.
|
||||
5. **Convention** — When everyone uses IS-IS, interop is easier. It's the industry standard for SP networks.
|
||||
|
||||
## IS-IS Key Concepts
|
||||
|
||||
**Levels:**
|
||||
- **Level 1 (L1)** = Intra-area routing (like OSPF's intra-area routes)
|
||||
- **Level 2 (L2)** = Inter-area / backbone routing (like OSPF Area 0)
|
||||
- **Level 1-2** = A router that participates in both (most PE routers)
|
||||
|
||||
For our ISP: **Everything runs Level 2 only.** This is standard practice in SP networks. We're one big backbone — no need for L1 areas. Keeps it simple and fast.
|
||||
|
||||
**NET (Network Entity Title):**
|
||||
This is IS-IS's address format. It looks weird but it's simple:
|
||||
|
||||
```
|
||||
49.0001.0000.0000.0001.00
|
||||
│ │ │ │
|
||||
│ │ └──────────────┘── System ID (unique per router, often based on loopback IP)
|
||||
│ └── Area ID
|
||||
└── AFI (49 = private, always use this in labs)
|
||||
```
|
||||
|
||||
**Metric:**
|
||||
IS-IS uses a flat metric (default: 10 on every link). We'll use **wide metrics** (mandatory for Segment Routing) and set costs based on link speed to influence traffic paths.
|
||||
|
||||
## Lab 1 Config: IS-IS on the Core
|
||||
|
||||
**Goal:** Full IS-IS adjacency across all P and PE routers. Every router can ping every other router's loopback.
|
||||
|
||||
**Addressing Plan:**
|
||||
|
||||
| Router | Loopback0 | IS-IS NET | Role |
|
||||
|--------|-----------|-----------|------|
|
||||
| P1 | 10.0.0.1/32 | 49.0001.0000.0000.0001.00 | Core P |
|
||||
| P2 | 10.0.0.2/32 | 49.0001.0000.0000.0002.00 | Core P |
|
||||
| P3 | 10.0.0.3/32 | 49.0001.0000.0000.0003.00 | Core P |
|
||||
| P4 | 10.0.0.4/32 | 49.0001.0000.0000.0004.00 | Core P |
|
||||
| P-CORE | 10.0.0.5/32 | 49.0001.0000.0000.0005.00 | Core P / RR |
|
||||
| PE-EDGE1 | 10.0.0.11/32 | 49.0001.0000.0000.0011.00 | PE (AS65000 border) |
|
||||
| PE-EDGE2 | 10.0.0.12/32 | 49.0001.0000.0000.0012.00 | PE (AS65000 cust) |
|
||||
| PE-EDGE3 | 10.0.0.13/32 | 49.0001.0000.0000.0013.00 | PE (AS65100 border) |
|
||||
| PE-EDGE4 | 10.0.0.14/32 | 49.0001.0000.0000.0014.00 | PE (AS65100 cust) |
|
||||
|
||||
**Link Addressing (point-to-point, /30s):**
|
||||
|
||||
| Link | Subnet | Router A IP | Router B IP |
|
||||
|------|--------|-------------|-------------|
|
||||
| P1 — PE-EDGE1 | 10.1.1.0/30 | .1 | .2 |
|
||||
| P1 — P-CORE | 10.1.1.4/30 | .5 | .6 |
|
||||
| P1 — P2 | 10.1.1.8/30 | .9 | .10 |
|
||||
| P2 — PE-EDGE2 | 10.1.1.12/30 | .13 | .14 |
|
||||
| P2 — P-CORE | 10.1.1.16/30 | .17 | .18 |
|
||||
| P3 — PE-EDGE3 | 10.1.1.20/30 | .21 | .22 |
|
||||
| P3 — P-CORE | 10.1.1.24/30 | .25 | .26 |
|
||||
| P3 — P4 | 10.1.1.28/30 | .29 | .30 |
|
||||
| P4 — PE-EDGE4 | 10.1.1.32/30 | .33 | .34 |
|
||||
| P4 — P-CORE | 10.1.1.36/30 | .37 | .38 |
|
||||
| PE-EDGE1 — IXP | 172.16.0.0/24 | .1 | — |
|
||||
| PE-EDGE3 — IXP | 172.16.0.0/24 | .3 | — |
|
||||
|
||||
**Sample Config — P1 (IOS-XE / IOSv):**
|
||||
|
||||
```
|
||||
hostname P1
|
||||
!
|
||||
interface Loopback0
|
||||
ip address 10.0.0.1 255.255.255.255
|
||||
ip router isis YOURSP
|
||||
!
|
||||
interface GigabitEthernet0/1
|
||||
description TO PE-EDGE1
|
||||
ip address 10.1.1.1 255.255.255.252
|
||||
ip router isis YOURSP
|
||||
isis network point-to-point
|
||||
isis metric 10
|
||||
no shutdown
|
||||
!
|
||||
interface GigabitEthernet0/2
|
||||
description TO P-CORE
|
||||
ip address 10.1.1.5 255.255.255.252
|
||||
ip router isis YOURSP
|
||||
isis network point-to-point
|
||||
isis metric 10
|
||||
no shutdown
|
||||
!
|
||||
interface GigabitEthernet0/3
|
||||
description TO P2
|
||||
ip address 10.1.1.9 255.255.255.252
|
||||
ip router isis YOURSP
|
||||
isis network point-to-point
|
||||
isis metric 10
|
||||
no shutdown
|
||||
!
|
||||
router isis YOURSP
|
||||
net 49.0001.0000.0000.0001.00
|
||||
is-type level-2-only
|
||||
metric-style wide
|
||||
log-adjacency-changes
|
||||
passive-interface Loopback0
|
||||
```
|
||||
|
||||
## Verification Commands
|
||||
|
||||
```
|
||||
show isis neighbors ! Are adjacencies UP?
|
||||
show isis database detail ! What LSPs do we have?
|
||||
show ip route isis ! Are all loopbacks in the table?
|
||||
ping 10.0.0.5 source 10.0.0.1 ! Can P1 reach P-CORE?
|
||||
show isis topology ! Visual of the IS-IS graph
|
||||
```
|
||||
|
||||
## Understanding Check
|
||||
|
||||
Before moving on, you should be able to answer:
|
||||
1. Why does the ISP use Level 2 only?
|
||||
2. What's the System ID in the NET, and why do we derive it from the loopback?
|
||||
3. Why `isis network point-to-point` on every link?
|
||||
4. What happens if you forget `metric-style wide`? (Hint: Segment Routing won't work)
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 2: MPLS — Labeling the Backbone →](02-mpls.md)
|
||||
81
modules/02-mpls.md
Normal file
81
modules/02-mpls.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Module 2: MPLS — Labeling the Backbone
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 1: IS-IS](01-isis.md)
|
||||
> **Next**: [Module 3: iBGP](03-ibgp.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*MPLS label switched path showing Push → Swap → Swap → PHP Pop → IP Lookup*
|
||||
|
||||
---
|
||||
|
||||
## What Is MPLS and Why Do ISPs Use It?
|
||||
|
||||
MPLS (Multi-Protocol Label Switching) is the **heart of every modern ISP backbone**. Here's the key insight:
|
||||
|
||||
> **Core routers (P routers) don't need to know about customer routes.**
|
||||
|
||||
Without MPLS, every P router would need a full routing table — millions of routes. That's slow, expensive, and a security risk. Instead:
|
||||
|
||||
1. PE routers push an **MPLS label** onto packets entering the core
|
||||
2. P routers only look at the label — a simple number — and swap/forward it
|
||||
3. The PE on the other side pops the label and delivers to the customer
|
||||
|
||||
Think of it like shipping containers. The cargo ship (P router) doesn't care what's inside the container. It just reads the shipping label and moves it to the right port.
|
||||
|
||||
## LDP (Label Distribution Protocol)
|
||||
|
||||
LDP is how routers agree on which labels to use. It's simple:
|
||||
|
||||
1. Router A tells Router B: "If you want to reach my loopback 10.0.0.1, use label 24"
|
||||
2. Router B remembers this and tells its own neighbors: "To reach 10.0.0.1, send it to me with label 30" (its own locally assigned label)
|
||||
3. This builds a **Label Switched Path (LSP)** across the network
|
||||
|
||||
## Lab 2 Config: Enable MPLS/LDP
|
||||
|
||||
**On every P and PE router (add to existing config):**
|
||||
|
||||
```
|
||||
mpls ip
|
||||
mpls ldp router-id Loopback0 force
|
||||
!
|
||||
interface GigabitEthernet0/1
|
||||
mpls ip
|
||||
!
|
||||
interface GigabitEthernet0/2
|
||||
mpls ip
|
||||
!
|
||||
interface GigabitEthernet0/3
|
||||
mpls ip
|
||||
```
|
||||
|
||||
**That's it.** MPLS is beautifully simple to enable. The magic is in what it *enables* (VPNs, TE, etc.)
|
||||
|
||||
## Key Concept: PHP (Penultimate Hop Popping)
|
||||
|
||||
When a packet is one hop away from its destination, the second-to-last router **pops the label** instead of swapping it. Why? So the destination router only has to do one lookup (IP) instead of two (label + IP). This is called PHP and you'll see it as `implicit-null` or label `3` in the LFIB.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
```
|
||||
show mpls interfaces ! Which interfaces have MPLS enabled?
|
||||
show mpls ldp neighbor ! LDP sessions established?
|
||||
show mpls ldp bindings ! What labels are assigned to what prefixes?
|
||||
show mpls forwarding-table ! The LFIB — the actual label switching table
|
||||
traceroute 10.0.0.14 source 10.0.0.11 ! Should show MPLS labels in the path!
|
||||
```
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. Why don't P routers need customer routes?
|
||||
2. What is the LFIB and how is it different from the RIB/FIB?
|
||||
3. Explain PHP — why does the second-to-last hop pop the label?
|
||||
4. What would break if you forgot `mpls ldp router-id Loopback0 force`?
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 3: iBGP — The Brain of the ISP →](03-ibgp.md)
|
||||
120
modules/03-ibgp.md
Normal file
120
modules/03-ibgp.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Module 3: iBGP — The Brain of the ISP
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 2: MPLS](02-mpls.md)
|
||||
> **Next**: [Module 4: L3VPN](04-l3vpn.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*iBGP Route Reflector design — P-CORE reflects routes to all PE clients, eliminating full mesh*
|
||||
|
||||
---
|
||||
|
||||
## Why BGP Inside the ISP?
|
||||
|
||||
IS-IS carries infrastructure routes (loopbacks, point-to-point links). But customer routes, internet routes, VPN routes — all of that rides on **BGP**. Specifically, **iBGP** (Internal BGP — same AS number on both sides).
|
||||
|
||||
## The Full Mesh Problem
|
||||
|
||||
iBGP has a rule: **A route learned via iBGP cannot be advertised to another iBGP peer.** This prevents loops but creates a problem — you need a full mesh of iBGP sessions. With 9 routers, that's 36 sessions. With 100 routers, that's 4,950 sessions. That doesn't scale.
|
||||
|
||||
## Route Reflectors to the Rescue
|
||||
|
||||
A **Route Reflector (RR)** breaks the full-mesh requirement. RR rules:
|
||||
- **Client → RR**: Reflects to all other clients and non-clients
|
||||
- **Non-client → RR**: Reflects to clients only
|
||||
- **RR → RR**: Reflects to clients
|
||||
|
||||
We'll make **P-CORE** our Route Reflector. Every PE peers with P-CORE only. P-CORE reflects routes between them. Simple, scalable, elegant.
|
||||
|
||||
## Why Peer Using Loopbacks?
|
||||
|
||||
iBGP sessions use **loopback addresses** (not physical interfaces) because:
|
||||
1. If a physical link goes down but an alternate path exists, the BGP session survives
|
||||
2. Loopbacks never go down unless the router itself is dead
|
||||
3. This is why IS-IS (Module 1) was so important — it provides reachability to loopbacks
|
||||
|
||||
## Lab 3 Config: iBGP with Route Reflector
|
||||
|
||||
**P-CORE (Route Reflector):**
|
||||
|
||||
```
|
||||
router bgp 65000
|
||||
bgp router-id 10.0.0.5
|
||||
bgp log-neighbor-changes
|
||||
no bgp default ipv4-unicast
|
||||
!
|
||||
neighbor PEERS peer-group
|
||||
neighbor PEERS remote-as 65000
|
||||
neighbor PEERS update-source Loopback0
|
||||
neighbor PEERS route-reflector-client
|
||||
!
|
||||
neighbor 10.0.0.11 peer-group PEERS
|
||||
neighbor 10.0.0.12 peer-group PEERS
|
||||
neighbor 10.0.0.13 peer-group PEERS
|
||||
neighbor 10.0.0.14 peer-group PEERS
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor PEERS activate
|
||||
neighbor PEERS send-community both
|
||||
neighbor PEERS next-hop-self
|
||||
exit-address-family
|
||||
!
|
||||
address-family vpnv4 unicast
|
||||
neighbor PEERS activate
|
||||
neighbor PEERS send-community both
|
||||
exit-address-family
|
||||
```
|
||||
|
||||
**PE-EDGE1 (and similar for all PE routers):**
|
||||
|
||||
```
|
||||
router bgp 65000
|
||||
bgp router-id 10.0.0.11
|
||||
bgp log-neighbor-changes
|
||||
no bgp default ipv4-unicast
|
||||
!
|
||||
neighbor 10.0.0.5 remote-as 65000
|
||||
neighbor 10.0.0.5 update-source Loopback0
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 10.0.0.5 activate
|
||||
neighbor 10.0.0.5 send-community both
|
||||
exit-address-family
|
||||
!
|
||||
address-family vpnv4 unicast
|
||||
neighbor 10.0.0.5 activate
|
||||
neighbor 10.0.0.5 send-community both
|
||||
exit-address-family
|
||||
```
|
||||
|
||||
## Key Design Notes
|
||||
|
||||
- `no bgp default ipv4-unicast` — Best practice. Forces you to explicitly activate neighbors per address family. Prevents accidental route leaking.
|
||||
- `send-community both` — Critical for MPLS VPNs. Route targets are carried as BGP communities.
|
||||
- `address-family vpnv4` — This carries VPN routes (Module 4). We enable it now so it's ready.
|
||||
- `next-hop-self` on the RR — Ensures PE routers don't need to resolve each other's next-hops through the core (the RR rewrites it to itself).
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
show bgp summary ! All neighbors Established?
|
||||
show bgp ipv4 unicast summary ! IPv4 session status
|
||||
show bgp vpnv4 unicast summary ! VPNv4 session status (should be empty for now)
|
||||
show bgp ipv4 unicast ! What routes are in BGP?
|
||||
show ip bgp neighbors 10.0.0.5 ! Detailed neighbor info
|
||||
```
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. Why can't iBGP routes be re-advertised to other iBGP peers (without a RR)?
|
||||
2. What's the difference between `address-family ipv4` and `address-family vpnv4`?
|
||||
3. Why `update-source Loopback0`?
|
||||
4. What would happen if P-CORE went down? (Single point of failure — how would you fix this in production?)
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 4: L3VPN — Customer Isolation with VRFs →](04-l3vpn.md)
|
||||
129
modules/04-l3vpn.md
Normal file
129
modules/04-l3vpn.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Module 4: L3VPN — Customer Isolation with VRFs
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 3: iBGP](03-ibgp.md)
|
||||
> **Next**: [Module 5: eBGP](05-ebgp.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*L3VPN end-to-end flow — CE→PE→MPLS Core→PE→CE with VRF isolation and dual label stack*
|
||||
|
||||
---
|
||||
|
||||
## The Business Problem
|
||||
|
||||
You're an ISP. Customer A and Customer B both use `10.0.0.0/8` internally (because of course they do). If you put both their routes in your global routing table, they collide. **VRFs solve this.**
|
||||
|
||||
## What Is a VRF?
|
||||
|
||||
A **VRF (Virtual Routing and Forwarding)** instance is a completely separate routing table on the same physical router. Think of it as running multiple virtual routers on one box.
|
||||
|
||||
Each VRF has:
|
||||
- **Name** — just a label (e.g., "CUST_A")
|
||||
- **Route Distinguisher (RD)** — Makes routes globally unique. 65000:100 + 10.0.0.0/8 becomes a unique VPNv4 route
|
||||
- **Route Targets (RT)** — Controls which VRFs import/export routes. This is the magic that connects customer sites across the MPLS core
|
||||
|
||||
## How L3VPN Works End-to-End
|
||||
|
||||
1. **CE-CUST1** advertises `192.168.100.0/24` via eBGP to **PE-EDGE2**
|
||||
2. **PE-EDGE2** puts this route into VRF `CUST_A`, adds RD `65000:100`, and exports with RT `65000:100`
|
||||
3. The route is carried via **MP-BGP (VPNv4 address family)** to the Route Reflector
|
||||
4. **P-CORE (RR)** reflects it to **PE-EDGE4**
|
||||
5. **PE-EDGE4** sees RT `65000:100`, checks its VRF import policy, and imports it into VRF `CUST_A`
|
||||
6. **CE-CUST2** now sees `192.168.100.0/24` and can reach Customer A's other site
|
||||
7. **All transit through the core is MPLS-labeled** — P routers never see customer routes
|
||||
|
||||
## Lab 4 Config: L3VPN
|
||||
|
||||
**PE-EDGE2 (Customer A facing):**
|
||||
|
||||
```
|
||||
! Create VRF
|
||||
vrf definition CUST_A
|
||||
rd 65000:100
|
||||
address-family ipv4
|
||||
route-target export 65000:100
|
||||
route-target import 65000:100
|
||||
exit-address-family
|
||||
!
|
||||
! Assign customer-facing interface to VRF
|
||||
interface GigabitEthernet0/4
|
||||
description TO CE-CUST1
|
||||
vrf forwarding CUST_A
|
||||
ip address 10.100.0.1 255.255.255.252
|
||||
no shutdown
|
||||
!
|
||||
! BGP config for VRF
|
||||
router bgp 65000
|
||||
address-family ipv4 vrf CUST_A
|
||||
neighbor 10.100.0.2 remote-as 65001
|
||||
neighbor 10.100.0.2 activate
|
||||
exit-address-family
|
||||
```
|
||||
|
||||
**CE-CUST1 (Customer A):**
|
||||
|
||||
```
|
||||
hostname CE-CUST1
|
||||
!
|
||||
interface Loopback0
|
||||
ip address 192.168.100.1 255.255.255.255
|
||||
!
|
||||
interface GigabitEthernet0/0
|
||||
description TO PE-EDGE2
|
||||
ip address 10.100.0.2 255.255.255.252
|
||||
no shutdown
|
||||
!
|
||||
router bgp 65001
|
||||
bgp router-id 192.168.100.1
|
||||
network 192.168.100.0 mask 255.255.255.0
|
||||
neighbor 10.100.0.1 remote-as 65000
|
||||
```
|
||||
|
||||
**PE-EDGE4 (Customer B / also imports CUST_A routes):**
|
||||
|
||||
```
|
||||
vrf definition CUST_A
|
||||
rd 65000:100
|
||||
address-family ipv4
|
||||
route-target export 65000:100
|
||||
route-target import 65000:100
|
||||
exit-address-family
|
||||
!
|
||||
interface GigabitEthernet0/4
|
||||
description TO CE-CUST2
|
||||
vrf forwarding CUST_A
|
||||
ip address 10.100.1.1 255.255.255.252
|
||||
no shutdown
|
||||
!
|
||||
router bgp 65000
|
||||
address-family ipv4 vrf CUST_A
|
||||
neighbor 10.100.1.2 remote-as 65002
|
||||
neighbor 10.100.1.2 activate
|
||||
exit-address-family
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
show vrf ! VRFs configured
|
||||
show ip route vrf CUST_A ! Customer A's routing table
|
||||
show bgp vpnv4 unicast all ! All VPN routes across the core
|
||||
show bgp vpnv4 unicast vrf CUST_A ! VPN routes for this specific customer
|
||||
ping vrf CUST_A 192.168.100.1 source 10.100.1.1 ! Cross-core VPN connectivity
|
||||
traceroute vrf CUST_A 192.168.100.1 ! Should show MPLS labels through core
|
||||
```
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. What's the difference between RD and RT? (Common interview question!)
|
||||
2. If Customer B also uses `192.168.100.0/24`, why doesn't it conflict?
|
||||
3. What MPLS labels are used for VPN forwarding? (Hint: there are TWO labels — why?)
|
||||
4. How would you give Customer A internet access in addition to their VPN?
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 5: eBGP — Peering with the World →](05-ebgp.md)
|
||||
106
modules/05-ebgp.md
Normal file
106
modules/05-ebgp.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Module 5: eBGP — Peering with the World
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 4: L3VPN](04-l3vpn.md)
|
||||
> **Next**: [Module 6: Segment Routing](06-segment-routing.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*eBGP peering at the IXP — route filtering, local-pref tiers, and the Big 9 best path selection*
|
||||
|
||||
---
|
||||
|
||||
## Peering Types at an ISP
|
||||
|
||||
| Type | What It Is | Relationship | Money |
|
||||
|------|-----------|-------------|-------|
|
||||
| **Transit** | You pay a bigger ISP to reach the full internet | Customer → Provider | You pay them |
|
||||
| **Peering** | Two ISPs agree to exchange traffic for free | Peer ↔ Peer | Free (settlement-free) |
|
||||
| **Customer** | Someone pays YOU for connectivity | Provider → Customer | They pay you |
|
||||
| **IXP (Internet Exchange)** | A shared switch where many ISPs peer at once | Many ↔ Many | Small port fee |
|
||||
|
||||
## Our Lab Setup
|
||||
|
||||
PE-EDGE1 (AS 65000) and PE-EDGE3 (AS 65100) peer at the IXP. This simulates **settlement-free peering** between two ISPs.
|
||||
|
||||
## Lab 5 Config: eBGP at the IXP
|
||||
|
||||
**PE-EDGE1:**
|
||||
|
||||
```
|
||||
! IXP-facing interface
|
||||
interface GigabitEthernet0/5
|
||||
description TO IXP-SWITCH
|
||||
ip address 172.16.0.1 255.255.255.0
|
||||
no shutdown
|
||||
!
|
||||
router bgp 65000
|
||||
neighbor 172.16.0.3 remote-as 65100
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 172.16.0.3 activate
|
||||
neighbor 172.16.0.3 route-map PEERING-IN in
|
||||
neighbor 172.16.0.3 route-map PEERING-OUT out
|
||||
neighbor 172.16.0.3 prefix-list PEER-IN-FILTER in
|
||||
exit-address-family
|
||||
!
|
||||
! Only accept their customer prefixes, not the full internet
|
||||
ip prefix-list PEER-IN-FILTER seq 10 permit 10.200.0.0/16 le 24
|
||||
ip prefix-list PEER-IN-FILTER seq 999 deny 0.0.0.0/0 le 32
|
||||
!
|
||||
! Set local-pref lower for peering routes (prefer transit/customer)
|
||||
route-map PEERING-IN permit 10
|
||||
set local-preference 100
|
||||
!
|
||||
route-map PEERING-OUT permit 10
|
||||
! Only advertise your customer routes, not routes learned from other peers
|
||||
match community CUSTOMER-ROUTES
|
||||
```
|
||||
|
||||
**PE-EDGE3:**
|
||||
|
||||
```
|
||||
interface GigabitEthernet0/5
|
||||
description TO IXP-SWITCH
|
||||
ip address 172.16.0.3 255.255.255.0
|
||||
no shutdown
|
||||
!
|
||||
router bgp 65100
|
||||
neighbor 172.16.0.1 remote-as 65000
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 172.16.0.1 activate
|
||||
neighbor 172.16.0.1 route-map PEERING-IN in
|
||||
neighbor 172.16.0.1 route-map PEERING-OUT out
|
||||
exit-address-family
|
||||
```
|
||||
|
||||
## BGP Best Path Selection (The Big 9)
|
||||
|
||||
This is **THE** most important BGP concept. When a router has multiple paths to the same prefix, it picks the best one using this order:
|
||||
|
||||
| Priority | Attribute | Higher or Lower Wins? | Who Controls It? |
|
||||
|----------|-----------|----------------------|-----------------|
|
||||
| 1 | Weight (Cisco-proprietary) | Higher | Local router only |
|
||||
| 2 | Local Preference | Higher | Entire AS (via iBGP) |
|
||||
| 3 | Locally originated | — | Prefer routes this router originated |
|
||||
| 4 | AS Path length | Shorter | Neighbors (can be prepended) |
|
||||
| 5 | Origin code | IGP > EGP > ? | Route origin |
|
||||
| 6 | MED (Multi-Exit Discriminator) | Lower | Neighbor (suggestion only) |
|
||||
| 7 | eBGP over iBGP | — | Prefer external routes |
|
||||
| 8 | Lowest IGP metric to next-hop | Lower | Interior routing |
|
||||
| 9 | Oldest route / Router ID | Varies | Tiebreakers |
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. Why do ISPs filter inbound routes with prefix lists? What could go wrong?
|
||||
2. What is AS-path prepending and when would you use it?
|
||||
3. Why set a lower local-preference on peering routes?
|
||||
4. What is a BGP community and how do ISPs use them for traffic engineering?
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 6: Segment Routing →](06-segment-routing.md)
|
||||
86
modules/06-segment-routing.md
Normal file
86
modules/06-segment-routing.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Module 6: Segment Routing
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 5: eBGP](05-ebgp.md)
|
||||
> **Next**: [Module 7: Traffic Engineering](07-traffic-engineering.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*Segment Routing SID assignments (SRGB 16000+) with Prefix SIDs and Adjacency SIDs on all nodes*
|
||||
|
||||
---
|
||||
|
||||
## The Evolution: LDP → SR
|
||||
|
||||
Remember how LDP assigns labels? It works, but it has problems:
|
||||
- LDP creates a **full mesh of label bindings** — every router gets a label for every prefix
|
||||
- LDP is a **separate protocol** that must stay in sync with IS-IS (if they disagree, traffic blackholes)
|
||||
- No built-in traffic engineering
|
||||
|
||||
**Segment Routing (SR)** fixes all of this by embedding labels directly into IS-IS (or OSPF). No more LDP. No more synchronization issues.
|
||||
|
||||
## How SR Works
|
||||
|
||||
Instead of LDP negotiating labels between neighbors, each router advertises a **Segment ID (SID)** via IS-IS:
|
||||
|
||||
- **Prefix SID** = A label for reaching a specific router's loopback (replaces what LDP does)
|
||||
- **Adjacency SID** = A label for a specific link (used for traffic engineering)
|
||||
|
||||
The SID is an **index** added to a globally configured **SRGB (Segment Routing Global Block)**. Default SRGB: 16000–23999.
|
||||
|
||||
Example: If P1's Prefix SID index is 1, its label is **16001** everywhere in the network. No negotiation needed.
|
||||
|
||||
## Lab 6 Config: Enable Segment Routing
|
||||
|
||||
**On every router (replace LDP):**
|
||||
|
||||
```
|
||||
! Remove LDP (optional — SR and LDP can coexist, but pure SR is cleaner)
|
||||
no mpls ldp router-id Loopback0 force
|
||||
!
|
||||
! Enable SR in IS-IS
|
||||
router isis YOURSP
|
||||
segment-routing mpls
|
||||
segment-routing prefix-sid-map advertise-local
|
||||
!
|
||||
interface Loopback0
|
||||
ip router isis YOURSP
|
||||
isis prefix-sid index <UNIQUE_NUMBER>
|
||||
```
|
||||
|
||||
**SID Index Assignments:**
|
||||
|
||||
| Router | Loopback | Prefix SID Index | Resulting Label |
|
||||
|--------|----------|-----------------|----------------|
|
||||
| P1 | 10.0.0.1 | 1 | 16001 |
|
||||
| P2 | 10.0.0.2 | 2 | 16002 |
|
||||
| P3 | 10.0.0.3 | 3 | 16003 |
|
||||
| P4 | 10.0.0.4 | 4 | 16004 |
|
||||
| P-CORE | 10.0.0.5 | 5 | 16005 |
|
||||
| PE-EDGE1 | 10.0.0.11 | 11 | 16011 |
|
||||
| PE-EDGE2 | 10.0.0.12 | 12 | 16012 |
|
||||
| PE-EDGE3 | 10.0.0.13 | 13 | 16013 |
|
||||
| PE-EDGE4 | 10.0.0.14 | 14 | 16014 |
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
show isis segment-routing prefix-sid-map
|
||||
show mpls forwarding-table ! Labels should now be 16xxx
|
||||
show isis database detail ! Look for SR TLVs in the LSPs
|
||||
show segment-routing mpls state
|
||||
```
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. Why is SR simpler than LDP? What failure mode does it eliminate?
|
||||
2. What's the SRGB and why does it need to be the same on every router?
|
||||
3. What's the difference between a Prefix SID and an Adjacency SID?
|
||||
4. Can SR and LDP coexist? When would you want that?
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 7: Traffic Engineering →](07-traffic-engineering.md)
|
||||
64
modules/07-traffic-engineering.md
Normal file
64
modules/07-traffic-engineering.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Module 7: Traffic Engineering
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 6: Segment Routing](06-segment-routing.md)
|
||||
> **Next**: [Module 8: Attack & Defense](08-attack-defense.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*SR-TE explicit path steering — default shortest path vs policy-driven SID stack path with Flex-Algo*
|
||||
|
||||
---
|
||||
|
||||
## Why TE?
|
||||
|
||||
By default, IS-IS picks the shortest path. But what if:
|
||||
- The shortest path is congested?
|
||||
- You want to send VoIP traffic on a low-latency path and bulk data on a high-bandwidth path?
|
||||
- A fiber cut takes out the shortest path and you need a pre-computed backup?
|
||||
|
||||
**Traffic Engineering** lets you define explicit paths through the network.
|
||||
|
||||
## SR-TE (Segment Routing Traffic Engineering)
|
||||
|
||||
With SR, TE is just a **stack of SIDs**. Want traffic to go P1 → P2 → P-CORE → P4 instead of the direct path? Push labels `[16002, 16005, 16004]` onto the packet. Done. No RSVP tunnels, no signaling protocol, no state in the core.
|
||||
|
||||
## Lab 7 Config: SR-TE Policy
|
||||
|
||||
**PE-EDGE1 (force traffic to PE-EDGE4 via a specific path):**
|
||||
|
||||
```
|
||||
segment-routing traffic-eng
|
||||
segment-list PATH-VIA-P2-PCORE
|
||||
index 10 mpls label 16002 ! P2
|
||||
index 20 mpls label 16005 ! P-CORE
|
||||
index 30 mpls label 16014 ! PE-EDGE4
|
||||
!
|
||||
policy STEER-TO-PE4
|
||||
color 100 end-point 10.0.0.14
|
||||
candidate-paths
|
||||
preference 200
|
||||
explicit segment-list PATH-VIA-P2-PCORE
|
||||
```
|
||||
|
||||
## Flex-Algo (Advanced)
|
||||
|
||||
Flex-Algo lets you define **multiple topologies** on the same physical network. For example:
|
||||
- **Algorithm 0** (default): Shortest path by metric
|
||||
- **Algorithm 128**: Low-latency path (uses delay metric)
|
||||
- **Algorithm 129**: High-bandwidth path (avoids congested links)
|
||||
|
||||
Each algorithm creates a separate set of SIDs, so you can steer traffic into different topologies without explicit path lists.
|
||||
|
||||
## Understanding Check
|
||||
|
||||
1. How does SR-TE compare to RSVP-TE? What makes it simpler?
|
||||
2. What is a SID stack and how does it define a path?
|
||||
3. What is Flex-Algo and when would you use it over explicit SR-TE?
|
||||
|
||||
---
|
||||
|
||||
> **Next Module**: [Module 8: Attack & Defense Labs →](08-attack-defense.md)
|
||||
137
modules/08-attack-defense.md
Normal file
137
modules/08-attack-defense.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Module 8: Attack & Defense Labs
|
||||
|
||||
> **Course**: [ISP Backbone Lab Course](../README.md)
|
||||
> **Previous**: [Module 7: Traffic Engineering](07-traffic-engineering.md)
|
||||
|
||||
---
|
||||
|
||||
## Network Diagram
|
||||
|
||||

|
||||
*Attack surface map — 5 attack vectors from Kali box with corresponding 5-layer defense strategy*
|
||||
|
||||
---
|
||||
|
||||
## Red Team / Blue Team on Your Own ISP
|
||||
|
||||
This is where it gets fun. You built this ISP — now **break it**.
|
||||
|
||||
---
|
||||
|
||||
## Attack 1: BGP Hijacking
|
||||
|
||||
**Scenario:** Kali box (connected to PE-EDGE2's network) sends BGP updates pretending to own Customer A's prefixes.
|
||||
|
||||
**The Attack:**
|
||||
On Kali, run a BGP speaker (ExaBGP or FRRouting):
|
||||
```
|
||||
# ExaBGP config — advertise someone else's prefix
|
||||
neighbor 10.100.0.1 {
|
||||
router-id 6.6.6.6;
|
||||
local-as 65001;
|
||||
peer-as 65000;
|
||||
static {
|
||||
route 192.168.100.0/24 next-hop 10.100.0.2;
|
||||
route 192.168.100.0/25 next-hop 10.100.0.2; # More specific = wins!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**The Defense:**
|
||||
```
|
||||
! On PE-EDGE2 — filter what CE-CUST1 can advertise
|
||||
ip prefix-list CUST-A-ALLOWED seq 10 permit 192.168.100.0/24
|
||||
ip prefix-list CUST-A-ALLOWED seq 999 deny 0.0.0.0/0 le 32
|
||||
!
|
||||
router bgp 65000
|
||||
address-family ipv4 vrf CUST_A
|
||||
neighbor 10.100.0.2 prefix-list CUST-A-ALLOWED in
|
||||
neighbor 10.100.0.2 maximum-prefix 10 80 ! Alert at 80%, tear down at 100%
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attack 2: IS-IS Adjacency Flooding
|
||||
|
||||
**Scenario:** Inject a rogue router into the IS-IS domain to poison the SPF tree.
|
||||
|
||||
**The Defense:**
|
||||
```
|
||||
! IS-IS authentication on ALL links
|
||||
router isis YOURSP
|
||||
authentication mode md5 level-2
|
||||
authentication key-chain ISIS-AUTH level-2
|
||||
!
|
||||
key chain ISIS-AUTH
|
||||
key 1
|
||||
key-string S3cur3ISISk3y!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attack 3: MPLS Label Manipulation
|
||||
|
||||
**Scenario:** Craft packets with forged MPLS labels to reach VRFs you shouldn't have access to.
|
||||
|
||||
**The Defense:**
|
||||
- **CoPP (Control Plane Policing)** — Rate-limit protocol traffic to the CPU
|
||||
- **iACL (Infrastructure ACL)** — Only allow known sources to send labeled traffic
|
||||
- **TTL propagation disabled** — Hides internal topology from traceroute
|
||||
|
||||
```
|
||||
no mpls ip propagate-ttl
|
||||
!
|
||||
ip access-list extended INFRASTRUCTURE-PROTECTION
|
||||
permit tcp 10.0.0.0 0.0.0.255 any eq bgp
|
||||
permit udp 10.0.0.0 0.0.0.255 any eq 646 ! LDP
|
||||
deny ip any any log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attack 4: OSPF/IS-IS Route Injection
|
||||
|
||||
**Scenario:** A compromised CE router attempts to inject routes into the ISP's IGP.
|
||||
|
||||
**The Defense:** This is why IS-IS runs on **P and PE routers only**, never on CE links. CE routers speak BGP, which is filtered. The IGP is completely isolated from customer influence. Architecture *is* the defense.
|
||||
|
||||
---
|
||||
|
||||
## Attack 5: DDoS Against the Control Plane
|
||||
|
||||
**Scenario:** Flood a PE router with spoofed packets targeting BGP (TCP 179).
|
||||
|
||||
**The Defense:**
|
||||
```
|
||||
! CoPP — protect the control plane
|
||||
ip access-list extended COPP-BGP
|
||||
permit tcp 10.0.0.0 0.0.0.255 any eq bgp
|
||||
permit tcp any any eq bgp established
|
||||
deny tcp any any eq bgp
|
||||
!
|
||||
class-map COPP-BGP-CLASS
|
||||
match access-group name COPP-BGP
|
||||
!
|
||||
policy-map COPP-POLICY
|
||||
class COPP-BGP-CLASS
|
||||
police rate 500 pps burst 100 packets
|
||||
conform-action transmit
|
||||
exceed-action drop
|
||||
class class-default
|
||||
police rate 1000 pps
|
||||
!
|
||||
control-plane
|
||||
service-policy input COPP-POLICY
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- **Offense informs defense** — You can't protect what you don't understand how to attack
|
||||
- **Layered security** — No single defense is enough; combine prefix filtering, authentication, CoPP, and architectural isolation
|
||||
- **Architecture IS security** — The IS-IS/BGP separation, MPLS label isolation, and VRF design are all security features by nature
|
||||
|
||||
---
|
||||
|
||||
> **Back to Course**: [ISP Backbone Lab Course ←](../README.md)
|
||||
Reference in New Issue
Block a user