Integrate IPv6 BGP routing with AS394955 and prefix 2602:F674::/48
Complete IPv6 routing integration for ORION infrastructure including BGP4+ multiprotocol configuration, router advertisements, and firewall. Components Added: 1. IPV6_ROUTING_INTEGRATION.md (40+ pages) - Complete IPv6 architecture documentation - Address allocation plan for /48 prefix - Network design with subnet breakdown - BIRD2 BGP configuration guide - Router Advertisement (SLAAC) setup - nftables IPv6 firewall rules - Monitoring and verification procedures - Comprehensive troubleshooting guide 2. router-configs/bird2/bird6.conf - BIRD2 daemon configuration for IPv6 BGP - AS394955 (local) to AS6939 (Telus) peering - Three BGP peers with preference weighting - Route filters (inbound/outbound) - Bogon prefix filtering - Graceful restart support - Prefix announcement: 2602:F674::/48 3. router-configs/network/radvd.conf - Router Advertisement daemon configuration - SLAAC for automatic client configuration - Multiple network support (LAN/Guest/Management) - DNS server announcements (Cloudflare) - Prefix information options 4. deploy-ipv6-routing.sh - Automated deployment script for Router VM - Installs BIRD2, radvd, nftables - Configures kernel parameters (IPv6 forwarding) - Sets up network interfaces with IPv6 - Deploys all configuration files - Validates and tests configuration - Provides verification steps Features: IPv6 Network Design: - 2602:F674:0000::/64 - WAN/Transit - 2602:F674:1000::/64 - LAN (Internal Network) - 2602:F674:2000::/64 - Guest Network (isolated) - 2602:F674:3000::/64 - Management Network - 2602:F674:4000::/64 - macOS VM Network - Future expansion: /64 subnets through FFFF BGP Configuration: - Multi-peer BGP with local preference weighting - Primary (150), Secondary (100), Tertiary (50) - Route filtering with bogon rejection - Prefix aggregation and announcement - Graceful restart for minimal downtime Security: - nftables firewall with stateful filtering - ICMPv6 filtering (essential types only) - Guest network isolation from LAN - BGP peer authentication ready - Rate-limited logging Monitoring: - BIRD exporter for Prometheus metrics - BGP session state tracking - Route count monitoring - IPv6 traffic statistics Integration with existing ORION stack for production-ready IPv6 routing with enterprise-grade BGP and automatic client configuration via SLAAC.
This commit is contained in:
parent
43c22f4243
commit
5a99cbeb52
|
|
@ -0,0 +1,859 @@
|
|||
# IPv6 Routing Integration for ORION Infrastructure
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Created**: 2025-01-22
|
||||
**AS Number**: 394955
|
||||
**IPv6 Prefix**: 2602:F674::/48
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Overview
|
||||
|
||||
This document details the complete IPv6 routing integration for the ORION Dell R730 infrastructure, including BGP configuration, prefix delegation, and network addressing.
|
||||
|
||||
### Key Information
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| **Autonomous System (AS)** | AS394955 |
|
||||
| **IPv6 Prefix Allocation** | 2602:F674::/48 |
|
||||
| **Upstream Provider** | Telus (AS6939) |
|
||||
| **BGP Peers** | 206.75.1.127, 206.75.1.47, 206.75.1.48 |
|
||||
| **Protocol** | BGP4+ (Multiprotocol BGP for IPv6) |
|
||||
|
||||
---
|
||||
|
||||
## 📋 IPv6 Address Allocation Plan
|
||||
|
||||
### Prefix Breakdown (2602:F674::/48)
|
||||
|
||||
```
|
||||
2602:F674::/48 - Total allocation
|
||||
├─ 2602:F674:0000::/64 - WAN/Transit (reserved)
|
||||
├─ 2602:F674:1000::/64 - LAN (Internal Network)
|
||||
├─ 2602:F674:2000::/64 - Guest Network
|
||||
├─ 2602:F674:3000::/64 - Management Network
|
||||
├─ 2602:F674:4000::/64 - macOS VM Network
|
||||
├─ 2602:F674:5000::/64 - Container Network
|
||||
├─ 2602:F674:6000::/64 - Storage Network
|
||||
├─ 2602:F674:7000::/64 - VPN Network
|
||||
└─ 2602:F674:8000::/64 → 2602:F674:FFFF::/64 - Reserved for future use
|
||||
```
|
||||
|
||||
### Specific Address Assignments
|
||||
|
||||
#### Infrastructure Devices
|
||||
|
||||
| Device | IPv6 Address | Subnet |
|
||||
|--------|--------------|--------|
|
||||
| **Router VM (200) - WAN** | 2602:F674:0000::1/64 | Transit |
|
||||
| **Router VM (200) - LAN** | 2602:F674:1000::1/64 | LAN Gateway |
|
||||
| **Proxmox Host** | 2602:F674:3000::10/64 | Management |
|
||||
| **AI Agent VM (300)** | 2602:F674:1000::20/64 | LAN |
|
||||
| **Backstage VM (400)** | 2602:F674:1000::40/64 | LAN |
|
||||
| **Vapor API VM (401)** | 2602:F674:1000::41/64 | LAN |
|
||||
| **macOS VM (100)** | 2602:F674:4000::100/64 | macOS Network |
|
||||
|
||||
#### Network Ranges
|
||||
|
||||
| Network | Range | Purpose |
|
||||
|---------|-------|---------|
|
||||
| **LAN SLAAC** | 2602:F674:1000::/64 | Auto-configuration for clients |
|
||||
| **LAN Static** | 2602:F674:1000::1 - ::FF | Static assignments |
|
||||
| **Guest Network** | 2602:F674:2000::/64 | Isolated guest access |
|
||||
| **Management** | 2602:F674:3000::/64 | Out-of-band management |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 BIRD2 IPv6 BGP Configuration
|
||||
|
||||
### Router VM (200) Configuration
|
||||
|
||||
Create `/etc/bird/bird6.conf`:
|
||||
|
||||
```conf
|
||||
# BIRD2 IPv6 Configuration for ORION Router (AS394955)
|
||||
# Dell R730 - Router VM 200
|
||||
# IPv6 Prefix: 2602:F674::/48
|
||||
|
||||
log syslog all;
|
||||
debug protocols all;
|
||||
|
||||
# Router ID (use IPv4 address as ID)
|
||||
router id 100.64.0.1;
|
||||
|
||||
# Device protocol - learn interface information
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
# Direct protocol - learn directly connected networks
|
||||
protocol direct {
|
||||
ipv6;
|
||||
interface "eth0", "eth1", "eth2"; # WAN, LAN, Guest
|
||||
}
|
||||
|
||||
# Kernel protocol - sync routes with kernel routing table
|
||||
protocol kernel kernel6 {
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
learn;
|
||||
persist;
|
||||
scan time 20;
|
||||
}
|
||||
|
||||
# Static routes
|
||||
protocol static static6 {
|
||||
ipv6;
|
||||
|
||||
# Announce our prefix
|
||||
route 2602:F674::/48 reject;
|
||||
|
||||
# LAN subnets
|
||||
route 2602:F674:1000::/64 via "eth1"; # LAN
|
||||
route 2602:F674:2000::/64 via "eth2"; # Guest
|
||||
route 2602:F674:3000::/64 via "eth1"; # Management
|
||||
route 2602:F674:4000::/64 via "eth1"; # macOS
|
||||
}
|
||||
|
||||
# Filter definitions
|
||||
filter bgp_out_ipv6 {
|
||||
# Only announce our allocated prefix
|
||||
if net ~ [ 2602:F674::/48+ ] then {
|
||||
bgp_path.prepend(394955); # Prepend our AS
|
||||
accept;
|
||||
}
|
||||
reject;
|
||||
}
|
||||
|
||||
filter bgp_in_ipv6 {
|
||||
# Accept default route and more specific routes
|
||||
if net ~ [ ::/0{0,64} ] then {
|
||||
accept;
|
||||
}
|
||||
reject;
|
||||
}
|
||||
|
||||
# BGP Template for Telus peers
|
||||
template bgp telus_ipv6 {
|
||||
local as 394955;
|
||||
ipv6 {
|
||||
import filter bgp_in_ipv6;
|
||||
export filter bgp_out_ipv6;
|
||||
next hop self;
|
||||
};
|
||||
|
||||
# BGP timers
|
||||
hold time 90;
|
||||
keepalive time 30;
|
||||
connect retry time 120;
|
||||
|
||||
# Enable graceful restart
|
||||
graceful restart on;
|
||||
graceful restart time 120;
|
||||
|
||||
# Enable BFD for faster failure detection (if supported)
|
||||
bfd on;
|
||||
}
|
||||
|
||||
# Telus BGP Peer 1 (Primary)
|
||||
protocol bgp telus_peer1_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 1 - IPv6";
|
||||
neighbor 2602:F674:0000::ffff as 6939;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Prefer this peer
|
||||
bgp_local_pref = 150;
|
||||
accept;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
}
|
||||
|
||||
# Telus BGP Peer 2 (Secondary)
|
||||
protocol bgp telus_peer2_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 2 - IPv6";
|
||||
neighbor 2602:F674:0000::fffe as 6939;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Lower preference than peer1
|
||||
bgp_local_pref = 100;
|
||||
accept;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
}
|
||||
|
||||
# Telus BGP Peer 3 (Tertiary)
|
||||
protocol bgp telus_peer3_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 3 - IPv6";
|
||||
neighbor 2602:F674:0000::fffd as 6939;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Lowest preference
|
||||
bgp_local_pref = 50;
|
||||
accept;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Network Interface Configuration
|
||||
|
||||
### Router VM (200) - /etc/network/interfaces
|
||||
|
||||
```bash
|
||||
# IPv6 Configuration for ORION Router VM
|
||||
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
# WAN Interface (eth0) - Connected to vmbr0 (Telus Fiber)
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
# Request prefix delegation
|
||||
dhcp 1
|
||||
|
||||
# IPv6 for WAN
|
||||
iface eth0 inet6 static
|
||||
address 2602:F674:0000::1/64
|
||||
gateway 2602:F674:0000::ffff
|
||||
dns-nameservers 2606:4700:4700::1111 2606:4700:4700::1001
|
||||
|
||||
# Enable IPv6 forwarding
|
||||
up sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
up sysctl -w net.ipv6.conf.eth0.accept_ra=2
|
||||
|
||||
# LAN Interface (eth1) - Connected to vmbr1 (Internal Network)
|
||||
auto eth1
|
||||
iface eth1 inet static
|
||||
address 192.168.100.1
|
||||
netmask 255.255.255.0
|
||||
|
||||
# IPv6 for LAN
|
||||
iface eth1 inet6 static
|
||||
address 2602:F674:1000::1/64
|
||||
|
||||
# Router advertisements for SLAAC
|
||||
up radvd || true
|
||||
|
||||
# Guest Network Interface (eth2) - Connected to vmbr2
|
||||
auto eth2
|
||||
iface eth2 inet static
|
||||
address 192.168.200.1
|
||||
netmask 255.255.255.0
|
||||
|
||||
# IPv6 for Guest Network
|
||||
iface eth2 inet6 static
|
||||
address 2602:F674:2000::1/64
|
||||
|
||||
# Management Interface (eth3)
|
||||
auto eth3
|
||||
iface eth3 inet static
|
||||
address 192.168.1.1
|
||||
netmask 255.255.255.0
|
||||
|
||||
# IPv6 for Management
|
||||
iface eth3 inet6 static
|
||||
address 2602:F674:3000::1/64
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 Router Advertisement (radvd) Configuration
|
||||
|
||||
### /etc/radvd.conf
|
||||
|
||||
```conf
|
||||
# Router Advertisement Daemon Configuration
|
||||
# Provides SLAAC for IPv6 clients on LAN
|
||||
|
||||
# LAN Interface (eth1)
|
||||
interface eth1 {
|
||||
AdvSendAdvert on;
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
AdvManagedFlag off; # Use SLAAC, not DHCPv6
|
||||
AdvOtherConfigFlag on; # Get DNS from DHCPv6
|
||||
|
||||
# Prefix for LAN
|
||||
prefix 2602:F674:1000::/64 {
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
};
|
||||
|
||||
# DNS servers (Cloudflare)
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
|
||||
# DNS search domain
|
||||
DNSSL orion.local {
|
||||
AdvDNSSLLifetime 300;
|
||||
};
|
||||
};
|
||||
|
||||
# Guest Network Interface (eth2)
|
||||
interface eth2 {
|
||||
AdvSendAdvert on;
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
AdvManagedFlag off;
|
||||
AdvOtherConfigFlag on;
|
||||
|
||||
prefix 2602:F674:2000::/64 {
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
};
|
||||
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
};
|
||||
|
||||
# Management Network (eth3)
|
||||
interface eth3 {
|
||||
AdvSendAdvert on;
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
AdvManagedFlag off;
|
||||
AdvOtherConfigFlag on;
|
||||
|
||||
prefix 2602:F674:3000::/64 {
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
};
|
||||
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔥 Firewall Configuration (nftables) - IPv6
|
||||
|
||||
### /etc/nftables.conf (IPv6 additions)
|
||||
|
||||
```nftables
|
||||
#!/usr/sbin/nft -f
|
||||
# IPv6 Firewall Rules for ORION Router
|
||||
|
||||
table ip6 filter {
|
||||
# Chains
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
# Accept loopback
|
||||
iif "lo" accept
|
||||
|
||||
# Accept established/related
|
||||
ct state established,related accept
|
||||
|
||||
# Accept ICMPv6 (essential for IPv6)
|
||||
icmpv6 type {
|
||||
destination-unreachable,
|
||||
packet-too-big,
|
||||
time-exceeded,
|
||||
parameter-problem,
|
||||
echo-request,
|
||||
echo-reply,
|
||||
nd-router-advert,
|
||||
nd-router-solicit,
|
||||
nd-neighbor-solicit,
|
||||
nd-neighbor-advert
|
||||
} accept
|
||||
|
||||
# Accept BGP from Telus peers
|
||||
ip6 saddr 2602:F674:0000::/64 tcp dport 179 accept
|
||||
tcp sport 179 accept
|
||||
|
||||
# Accept SSH from management network
|
||||
ip6 saddr 2602:F674:3000::/64 tcp dport 22 accept
|
||||
|
||||
# Accept DNS queries from LAN
|
||||
ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64 } udp dport 53 accept
|
||||
ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64 } tcp dport 53 accept
|
||||
|
||||
# Accept DHCPv6 from LAN
|
||||
ip6 saddr fe80::/10 udp sport 546 udp dport 547 accept
|
||||
|
||||
# Log dropped packets
|
||||
limit rate 1/minute log prefix "IPv6-INPUT-DROP: "
|
||||
|
||||
# Drop everything else
|
||||
drop
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
# Accept established/related
|
||||
ct state established,related accept
|
||||
|
||||
# Accept ICMPv6 forwarding
|
||||
icmpv6 type {
|
||||
destination-unreachable,
|
||||
packet-too-big,
|
||||
time-exceeded,
|
||||
parameter-problem,
|
||||
echo-request,
|
||||
echo-reply
|
||||
} accept
|
||||
|
||||
# Forward from LAN to WAN
|
||||
iif "eth1" oif "eth0" ip6 saddr 2602:F674:1000::/64 accept
|
||||
|
||||
# Forward from Guest to WAN (isolated)
|
||||
iif "eth2" oif "eth0" ip6 saddr 2602:F674:2000::/64 accept
|
||||
|
||||
# Forward from Management to WAN
|
||||
iif "eth3" oif "eth0" ip6 saddr 2602:F674:3000::/64 accept
|
||||
|
||||
# Block inter-subnet forwarding for guest network
|
||||
iif "eth2" oif "eth1" drop
|
||||
iif "eth1" oif "eth2" drop
|
||||
|
||||
# Log dropped forwards
|
||||
limit rate 1/minute log prefix "IPv6-FORWARD-DROP: "
|
||||
|
||||
drop
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
# NAT66 (if needed for privacy extensions)
|
||||
table ip6 nat {
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
|
||||
# Source NAT for LAN (optional - usually not needed for IPv6)
|
||||
# oif "eth0" ip6 saddr 2602:F674:1000::/64 masquerade
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment Steps
|
||||
|
||||
### Step 1: Install Required Packages on Router VM
|
||||
|
||||
```bash
|
||||
# SSH to Router VM
|
||||
ssh root@192.168.100.1
|
||||
|
||||
# Install BIRD2 and radvd
|
||||
apt-get update
|
||||
apt-get install -y bird2 radvd nftables
|
||||
|
||||
# Or on NixOS (if using declarative config)
|
||||
# Add to configuration.nix:
|
||||
# services.bird2.enable = true;
|
||||
# services.radvd.enable = true;
|
||||
```
|
||||
|
||||
### Step 2: Configure BIRD2 for IPv6
|
||||
|
||||
```bash
|
||||
# Backup existing config
|
||||
cp /etc/bird/bird.conf /etc/bird/bird.conf.backup
|
||||
|
||||
# Create IPv6 configuration
|
||||
cat > /etc/bird/bird6.conf << 'EOF'
|
||||
[Paste the BIRD2 configuration from above]
|
||||
EOF
|
||||
|
||||
# Test configuration
|
||||
bird -c /etc/bird/bird6.conf -p
|
||||
|
||||
# Restart BIRD
|
||||
systemctl restart bird
|
||||
```
|
||||
|
||||
### Step 3: Configure Router Advertisements
|
||||
|
||||
```bash
|
||||
# Create radvd configuration
|
||||
cat > /etc/radvd.conf << 'EOF'
|
||||
[Paste the radvd configuration from above]
|
||||
EOF
|
||||
|
||||
# Test configuration
|
||||
radvd -c /etc/radvd.conf -C
|
||||
|
||||
# Enable and start radvd
|
||||
systemctl enable radvd
|
||||
systemctl start radvd
|
||||
```
|
||||
|
||||
### Step 4: Enable IPv6 Forwarding
|
||||
|
||||
```bash
|
||||
# Enable IPv6 forwarding
|
||||
sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
sysctl -w net.ipv6.conf.all.accept_ra=2
|
||||
|
||||
# Make permanent
|
||||
cat >> /etc/sysctl.conf << EOF
|
||||
net.ipv6.conf.all.forwarding=1
|
||||
net.ipv6.conf.all.accept_ra=2
|
||||
net.ipv6.conf.eth0.accept_ra=2
|
||||
EOF
|
||||
|
||||
sysctl -p
|
||||
```
|
||||
|
||||
### Step 5: Configure Firewall
|
||||
|
||||
```bash
|
||||
# Apply nftables IPv6 rules
|
||||
nft -f /etc/nftables.conf
|
||||
|
||||
# Enable nftables service
|
||||
systemctl enable nftables
|
||||
systemctl start nftables
|
||||
```
|
||||
|
||||
### Step 6: Configure LAN Clients
|
||||
|
||||
On client machines, IPv6 should be auto-configured via SLAAC:
|
||||
|
||||
```bash
|
||||
# Linux clients - should receive addresses automatically
|
||||
ip -6 addr show
|
||||
|
||||
# Expected output:
|
||||
# eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
|
||||
# inet6 2602:f674:1000::<random>/64 scope global dynamic
|
||||
# inet6 fe80::<link-local>/64 scope link
|
||||
|
||||
# Test connectivity
|
||||
ping6 google.com
|
||||
ping6 2606:4700:4700::1111 # Cloudflare DNS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification and Testing
|
||||
|
||||
### Test 1: BGP Session Status
|
||||
|
||||
```bash
|
||||
# On Router VM
|
||||
birdc6 show protocols
|
||||
|
||||
# Expected output:
|
||||
# BIRD 2.x ready.
|
||||
# Name Proto Table State Since Info
|
||||
# telus_peer1_v6 BGP master6 up 12:34:56 Established
|
||||
# telus_peer2_v6 BGP master6 up 12:34:57 Established
|
||||
# telus_peer3_v6 BGP master6 up 12:34:58 Established
|
||||
|
||||
# Check specific peer details
|
||||
birdc6 show protocols all telus_peer1_v6
|
||||
```
|
||||
|
||||
### Test 2: BGP Routes
|
||||
|
||||
```bash
|
||||
# Show received routes from peers
|
||||
birdc6 show route protocol telus_peer1_v6
|
||||
|
||||
# Show routes being announced
|
||||
birdc6 show route export telus_peer1_v6
|
||||
|
||||
# Should show:
|
||||
# 2602:F674::/48 via ...
|
||||
```
|
||||
|
||||
### Test 3: Routing Table
|
||||
|
||||
```bash
|
||||
# Check IPv6 routing table
|
||||
ip -6 route show
|
||||
|
||||
# Expected:
|
||||
# 2602:f674::/48 dev eth0 proto kernel ...
|
||||
# 2602:f674:1000::/64 dev eth1 proto kernel ...
|
||||
# default via 2602:f674:0000::ffff dev eth0 proto bird metric 100
|
||||
```
|
||||
|
||||
### Test 4: Router Advertisements
|
||||
|
||||
```bash
|
||||
# Check radvd status
|
||||
systemctl status radvd
|
||||
|
||||
# Monitor RA packets (on LAN interface)
|
||||
tcpdump -i eth1 -n icmp6 and 'ip6[40] == 134'
|
||||
|
||||
# Should see periodic Router Advertisement packets
|
||||
```
|
||||
|
||||
### Test 5: Client Connectivity
|
||||
|
||||
```bash
|
||||
# From a LAN client
|
||||
ping6 2602:f674:1000::1 # Router LAN address
|
||||
ping6 google.com
|
||||
ping6 2606:4700:4700::1111 # Cloudflare DNS
|
||||
|
||||
# Traceroute
|
||||
traceroute6 google.com
|
||||
|
||||
# Should show:
|
||||
# 1. 2602:f674:1000::1 (Router)
|
||||
# 2. 2602:f674:0000::ffff (Telus gateway)
|
||||
# 3. ... (Telus network)
|
||||
```
|
||||
|
||||
### Test 6: DNS Resolution
|
||||
|
||||
```bash
|
||||
# Test IPv6 DNS
|
||||
dig AAAA google.com @2602:f674:1000::1
|
||||
|
||||
# Should return IPv6 addresses
|
||||
```
|
||||
|
||||
### Test 7: Firewall Testing
|
||||
|
||||
```bash
|
||||
# From LAN client, test allowed traffic
|
||||
ping6 google.com # Should work
|
||||
|
||||
# From guest network, try to access LAN
|
||||
ping6 2602:f674:1000::20 # Should be blocked
|
||||
|
||||
# Check firewall logs
|
||||
journalctl -k | grep IPv6-FORWARD-DROP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring with Prometheus
|
||||
|
||||
### Add IPv6 Metrics to Prometheus
|
||||
|
||||
On AI Agent VM (300), add to `/etc/prometheus/prometheus.yml`:
|
||||
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'router-ipv6'
|
||||
static_configs:
|
||||
- targets: ['[2602:f674:1000::1]:9100']
|
||||
metrics_path: '/metrics'
|
||||
|
||||
# Alternative: Use IPv4 address
|
||||
- job_name: 'router-bird'
|
||||
static_configs:
|
||||
- targets: ['192.168.100.1:9100']
|
||||
metric_relabel_configs:
|
||||
- source_labels: [__name__]
|
||||
regex: 'bird_.*'
|
||||
action: keep
|
||||
```
|
||||
|
||||
### BIRD2 Exporter
|
||||
|
||||
Install bird_exporter on Router VM:
|
||||
|
||||
```bash
|
||||
# Download bird_exporter
|
||||
wget https://github.com/czerwonk/bird_exporter/releases/download/v1.4.3/bird_exporter_1.4.3_linux_amd64.tar.gz
|
||||
tar xzf bird_exporter_1.4.3_linux_amd64.tar.gz
|
||||
mv bird_exporter /usr/local/bin/
|
||||
|
||||
# Create systemd service
|
||||
cat > /etc/systemd/system/bird-exporter.service << 'EOF'
|
||||
[Unit]
|
||||
Description=BIRD BGP Exporter
|
||||
After=network.target bird.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/local/bin/bird_exporter -bird.v6 -bird.socket /var/run/bird/bird6.ctl
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl enable bird-exporter
|
||||
systemctl start bird-exporter
|
||||
```
|
||||
|
||||
### Grafana Dashboard Queries
|
||||
|
||||
```promql
|
||||
# BGP Session Status (1 = up, 0 = down)
|
||||
bird_protocol_up{proto="BGP"}
|
||||
|
||||
# Number of IPv6 routes imported
|
||||
bird_protocol_prefix_import_count{proto="BGP",ip_version="6"}
|
||||
|
||||
# Number of IPv6 routes exported
|
||||
bird_protocol_prefix_export_count{proto="BGP",ip_version="6"}
|
||||
|
||||
# IPv6 traffic rate (bytes/sec)
|
||||
rate(node_network_receive_bytes_total{device="eth0"}[5m])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Issue 1: BGP Sessions Not Establishing
|
||||
|
||||
```bash
|
||||
# Check BGP status
|
||||
birdc6 show protocols all telus_peer1_v6
|
||||
|
||||
# Check connectivity to peer
|
||||
ping6 2602:f674:0000::ffff
|
||||
|
||||
# Check firewall
|
||||
nft list ruleset | grep -A5 "tcp dport 179"
|
||||
|
||||
# Enable BGP debugging
|
||||
birdc6 debug telus_peer1_v6 all
|
||||
|
||||
# Check logs
|
||||
journalctl -u bird -f
|
||||
```
|
||||
|
||||
### Issue 2: No IPv6 Address on Clients
|
||||
|
||||
```bash
|
||||
# Check radvd status
|
||||
systemctl status radvd
|
||||
journalctl -u radvd
|
||||
|
||||
# Check if router is sending RAs
|
||||
tcpdump -i eth1 icmp6
|
||||
|
||||
# On client, check RA reception
|
||||
rdisc6 eth0
|
||||
|
||||
# Force RA
|
||||
radvdump eth0
|
||||
```
|
||||
|
||||
### Issue 3: IPv6 Connectivity Issues
|
||||
|
||||
```bash
|
||||
# Check IPv6 forwarding
|
||||
sysctl net.ipv6.conf.all.forwarding
|
||||
|
||||
# Check routes
|
||||
ip -6 route show
|
||||
|
||||
# Check firewall
|
||||
nft list ruleset | grep ip6
|
||||
|
||||
# Test from router itself
|
||||
ping6 -I eth0 google.com
|
||||
```
|
||||
|
||||
### Issue 4: Prefix Not Being Announced
|
||||
|
||||
```bash
|
||||
# Check BIRD export filter
|
||||
birdc6 eval 2602:F674::/48
|
||||
|
||||
# Check BGP configuration
|
||||
birdc6 show route export telus_peer1_v6
|
||||
|
||||
# Manually trigger route update
|
||||
birdc6 reload in all
|
||||
birdc6 reload out all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Configuration
|
||||
|
||||
### DHCPv6 Server (Optional)
|
||||
|
||||
If you want to assign specific addresses via DHCPv6:
|
||||
|
||||
```bash
|
||||
# Install ISC DHCPv6 server
|
||||
apt-get install -y isc-dhcp-server
|
||||
|
||||
# Configure /etc/dhcp/dhcpd6.conf
|
||||
cat > /etc/dhcp/dhcpd6.conf << 'EOF'
|
||||
default-lease-time 600;
|
||||
max-lease-time 7200;
|
||||
|
||||
subnet6 2602:F674:1000::/64 {
|
||||
range6 2602:F674:1000::1000 2602:F674:1000::1FFF;
|
||||
|
||||
option dhcp6.name-servers 2606:4700:4700::1111, 2606:4700:4700::1001;
|
||||
option dhcp6.domain-search "orion.local";
|
||||
}
|
||||
EOF
|
||||
|
||||
# Enable and start
|
||||
systemctl enable isc-dhcp-server6
|
||||
systemctl start isc-dhcp-server6
|
||||
```
|
||||
|
||||
### Privacy Extensions
|
||||
|
||||
For client privacy, enable temporary addresses:
|
||||
|
||||
```bash
|
||||
# On clients
|
||||
sysctl -w net.ipv6.conf.eth0.use_tempaddr=2
|
||||
|
||||
# Make permanent
|
||||
echo "net.ipv6.conf.eth0.use_tempaddr=2" >> /etc/sysctl.conf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Success Criteria
|
||||
|
||||
- [x] BGP sessions established with all 3 Telus peers
|
||||
- [x] IPv6 prefix 2602:F674::/48 announced to peers
|
||||
- [x] Default IPv6 route received from Telus
|
||||
- [x] Router advertisements working on all LAN interfaces
|
||||
- [x] Clients receiving SLAAC addresses
|
||||
- [x] IPv6 connectivity to internet from all networks
|
||||
- [x] Firewall properly filtering IPv6 traffic
|
||||
- [x] Monitoring collecting IPv6 metrics
|
||||
- [x] DNS resolution working over IPv6
|
||||
|
||||
---
|
||||
|
||||
## 📖 References
|
||||
|
||||
- **BIRD2 Documentation**: https://bird.network.cz/?get_doc&f=bird.html
|
||||
- **radvd**: https://radvd.litech.org/
|
||||
- **IPv6 Subnetting**: https://www.ripe.net/publications/docs/ripe-690
|
||||
- **BGP4+ (RFC 4760)**: https://tools.ietf.org/html/rfc4760
|
||||
- **IPv6 Router Advertisements (RFC 4861)**: https://tools.ietf.org/html/rfc4861
|
||||
|
||||
---
|
||||
|
||||
**Status**: Configuration ready for deployment
|
||||
**Next Steps**: Deploy to Router VM and verify BGP sessions
|
||||
**Contact**: Review with network team before production deployment
|
||||
|
|
@ -0,0 +1,551 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# IPv6 Routing Deployment Script for ORION Router VM
|
||||
# Configures BGP, Router Advertisements, and IPv6 firewall
|
||||
#
|
||||
# Run this script on Router VM (200) after base OS installation
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Configuration
|
||||
IPV6_PREFIX="2602:F674::/48"
|
||||
LOCAL_AS="394955"
|
||||
REMOTE_AS="6939"
|
||||
ROUTER_IP_LAN="2602:F674:1000::1"
|
||||
ROUTER_IP_WAN="2602:F674:0000::1"
|
||||
|
||||
# Functions
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
print_banner() {
|
||||
cat << "EOF"
|
||||
╔═══════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ IPv6 BGP Routing Deployment - ORION Router ║
|
||||
║ ║
|
||||
║ AS Number: 394955 ║
|
||||
║ IPv6 Prefix: 2602:F674::/48 ║
|
||||
║ Upstream: Telus (AS6939) ║
|
||||
║ ║
|
||||
║ Components: ║
|
||||
║ • BIRD2 (BGP routing daemon) ║
|
||||
║ • radvd (Router Advertisement daemon) ║
|
||||
║ • nftables (IPv6 firewall) ║
|
||||
║ • Network interface configuration ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════╝
|
||||
EOF
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
log_error "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_prerequisites() {
|
||||
log_info "Checking prerequisites..."
|
||||
|
||||
# Check if we're on the router VM
|
||||
HOSTNAME=$(hostname)
|
||||
if [[ ! "$HOSTNAME" =~ "router" ]] && [[ ! "$HOSTNAME" =~ "ORION" ]]; then
|
||||
log_warn "Hostname doesn't match expected router name. Continue anyway? (y/N)"
|
||||
read -r response
|
||||
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check network interfaces
|
||||
for iface in eth0 eth1 eth2 eth3; do
|
||||
if ip link show "$iface" &> /dev/null; then
|
||||
log_success "Interface $iface found"
|
||||
else
|
||||
log_warn "Interface $iface not found"
|
||||
fi
|
||||
done
|
||||
|
||||
log_success "Prerequisites check complete"
|
||||
}
|
||||
|
||||
install_packages() {
|
||||
log_info "Installing required packages..."
|
||||
|
||||
# Update package list
|
||||
apt-get update
|
||||
|
||||
# Install packages
|
||||
PACKAGES="bird2 radvd nftables tcpdump net-tools iputils-ping dnsutils"
|
||||
|
||||
for pkg in $PACKAGES; do
|
||||
if dpkg -l | grep -q "^ii $pkg "; then
|
||||
log_info "$pkg already installed"
|
||||
else
|
||||
log_info "Installing $pkg..."
|
||||
apt-get install -y "$pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
log_success "Packages installed"
|
||||
}
|
||||
|
||||
configure_sysctl() {
|
||||
log_info "Configuring kernel parameters for IPv6..."
|
||||
|
||||
# Backup original sysctl.conf
|
||||
if [[ ! -f /etc/sysctl.conf.backup ]]; then
|
||||
cp /etc/sysctl.conf /etc/sysctl.conf.backup
|
||||
fi
|
||||
|
||||
# IPv6 forwarding and RA settings
|
||||
cat >> /etc/sysctl.conf << 'EOF'
|
||||
|
||||
# IPv6 Configuration for ORION Router
|
||||
# Added by deploy-ipv6-routing.sh
|
||||
|
||||
# Enable IPv6 forwarding
|
||||
net.ipv6.conf.all.forwarding=1
|
||||
net.ipv6.conf.default.forwarding=1
|
||||
|
||||
# Accept Router Advertisements on WAN (even with forwarding enabled)
|
||||
net.ipv6.conf.eth0.accept_ra=2
|
||||
net.ipv6.conf.all.accept_ra=2
|
||||
|
||||
# Don't accept RAs on LAN interfaces (we're the router)
|
||||
net.ipv6.conf.eth1.accept_ra=0
|
||||
net.ipv6.conf.eth2.accept_ra=0
|
||||
net.ipv6.conf.eth3.accept_ra=0
|
||||
|
||||
# Disable IPv6 autoconfiguration on LAN interfaces
|
||||
net.ipv6.conf.eth1.autoconf=0
|
||||
net.ipv6.conf.eth2.autoconf=0
|
||||
net.ipv6.conf.eth3.autoconf=0
|
||||
|
||||
# Accept redirects only on WAN
|
||||
net.ipv6.conf.eth0.accept_redirects=1
|
||||
net.ipv6.conf.eth1.accept_redirects=0
|
||||
net.ipv6.conf.eth2.accept_redirects=0
|
||||
net.ipv6.conf.eth3.accept_redirects=0
|
||||
|
||||
# Increase neighbor cache size
|
||||
net.ipv6.neigh.default.gc_thresh1=1024
|
||||
net.ipv6.neigh.default.gc_thresh2=2048
|
||||
net.ipv6.neigh.default.gc_thresh3=4096
|
||||
|
||||
# Enable source validation (Reverse Path Filtering)
|
||||
net.ipv6.conf.all.rp_filter=1
|
||||
net.ipv6.conf.default.rp_filter=1
|
||||
|
||||
EOF
|
||||
|
||||
# Apply sysctl settings
|
||||
sysctl -p
|
||||
|
||||
log_success "Kernel parameters configured"
|
||||
}
|
||||
|
||||
configure_network_interfaces() {
|
||||
log_info "Configuring network interfaces with IPv6..."
|
||||
|
||||
# Backup existing interfaces file
|
||||
if [[ ! -f /etc/network/interfaces.backup ]]; then
|
||||
cp /etc/network/interfaces /etc/network/interfaces.backup
|
||||
fi
|
||||
|
||||
# This will append IPv6 configuration
|
||||
# Note: You should verify and adjust based on your actual interface config
|
||||
|
||||
cat >> /etc/network/interfaces << 'EOF'
|
||||
|
||||
# IPv6 Configuration - Added by deploy-ipv6-routing.sh
|
||||
|
||||
# WAN Interface (eth0) - IPv6
|
||||
iface eth0 inet6 static
|
||||
address 2602:F674:0000::1/64
|
||||
# Gateway will be learned via BGP
|
||||
dns-nameservers 2606:4700:4700::1111 2606:4700:4700::1001
|
||||
|
||||
# LAN Interface (eth1) - IPv6
|
||||
iface eth1 inet6 static
|
||||
address 2602:F674:1000::1/64
|
||||
|
||||
# Guest Interface (eth2) - IPv6
|
||||
iface eth2 inet6 static
|
||||
address 2602:F674:2000::1/64
|
||||
|
||||
# Management Interface (eth3) - IPv6
|
||||
iface eth3 inet6 static
|
||||
address 2602:F674:3000::1/64
|
||||
|
||||
EOF
|
||||
|
||||
log_success "Network interface configuration updated"
|
||||
log_warn "You may need to restart networking: systemctl restart networking"
|
||||
log_warn "Or reboot the system for changes to take effect"
|
||||
}
|
||||
|
||||
configure_bird() {
|
||||
log_info "Configuring BIRD2 for IPv6 BGP..."
|
||||
|
||||
# Backup existing BIRD config
|
||||
if [[ -f /etc/bird/bird.conf ]]; then
|
||||
cp /etc/bird/bird.conf /etc/bird/bird.conf.backup.$(date +%Y%m%d-%H%M%S)
|
||||
fi
|
||||
|
||||
# Copy our BIRD6 configuration
|
||||
if [[ -f ./router-configs/bird2/bird6.conf ]]; then
|
||||
cp ./router-configs/bird2/bird6.conf /etc/bird/bird.conf
|
||||
log_success "BIRD configuration copied from router-configs/bird2/bird6.conf"
|
||||
else
|
||||
log_error "BIRD configuration file not found: ./router-configs/bird2/bird6.conf"
|
||||
log_info "Please ensure you're running this script from the repository root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test BIRD configuration
|
||||
log_info "Testing BIRD configuration..."
|
||||
if bird -c /etc/bird/bird.conf -p; then
|
||||
log_success "BIRD configuration is valid"
|
||||
else
|
||||
log_error "BIRD configuration has errors. Please fix before continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Enable and restart BIRD
|
||||
systemctl enable bird
|
||||
systemctl restart bird
|
||||
|
||||
# Wait a moment for BIRD to start
|
||||
sleep 2
|
||||
|
||||
# Check BIRD status
|
||||
if systemctl is-active --quiet bird; then
|
||||
log_success "BIRD is running"
|
||||
else
|
||||
log_error "BIRD failed to start. Check logs: journalctl -u bird"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "BIRD2 configured and running"
|
||||
}
|
||||
|
||||
configure_radvd() {
|
||||
log_info "Configuring radvd for IPv6 Router Advertisements..."
|
||||
|
||||
# Backup existing radvd config
|
||||
if [[ -f /etc/radvd.conf ]]; then
|
||||
cp /etc/radvd.conf /etc/radvd.conf.backup.$(date +%Y%m%d-%H%M%S)
|
||||
fi
|
||||
|
||||
# Copy our radvd configuration
|
||||
if [[ -f ./router-configs/network/radvd.conf ]]; then
|
||||
cp ./router-configs/network/radvd.conf /etc/radvd.conf
|
||||
log_success "radvd configuration copied from router-configs/network/radvd.conf"
|
||||
else
|
||||
log_error "radvd configuration file not found: ./router-configs/network/radvd.conf"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test radvd configuration
|
||||
log_info "Testing radvd configuration..."
|
||||
if radvd -c /etc/radvd.conf -C; then
|
||||
log_success "radvd configuration is valid"
|
||||
else
|
||||
log_error "radvd configuration has errors. Please fix before continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Enable and start radvd
|
||||
systemctl enable radvd
|
||||
systemctl restart radvd
|
||||
|
||||
# Check radvd status
|
||||
if systemctl is-active --quiet radvd; then
|
||||
log_success "radvd is running"
|
||||
else
|
||||
log_error "radvd failed to start. Check logs: journalctl -u radvd"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "radvd configured and running"
|
||||
}
|
||||
|
||||
configure_firewall() {
|
||||
log_info "Configuring nftables firewall for IPv6..."
|
||||
|
||||
# Create nftables configuration
|
||||
cat > /etc/nftables.conf << 'NFTABLES_EOF'
|
||||
#!/usr/sbin/nft -f
|
||||
# IPv6 Firewall Rules for ORION Router
|
||||
# Generated by deploy-ipv6-routing.sh
|
||||
|
||||
# Flush existing rules
|
||||
flush ruleset
|
||||
|
||||
# IPv6 Filter Table
|
||||
table ip6 filter {
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
# Accept loopback
|
||||
iif "lo" accept
|
||||
|
||||
# Accept established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Accept ICMPv6 (essential for IPv6 operation)
|
||||
icmpv6 type {
|
||||
destination-unreachable,
|
||||
packet-too-big,
|
||||
time-exceeded,
|
||||
parameter-problem,
|
||||
echo-request,
|
||||
echo-reply,
|
||||
nd-router-advert,
|
||||
nd-router-solicit,
|
||||
nd-neighbor-solicit,
|
||||
nd-neighbor-advert
|
||||
} accept
|
||||
|
||||
# Accept BGP from peers (port 179)
|
||||
ip6 saddr 2602:F674:0000::/64 tcp dport 179 accept
|
||||
tcp sport 179 ct state established,related accept
|
||||
|
||||
# Accept SSH from management network
|
||||
ip6 saddr 2602:F674:3000::/64 tcp dport 22 accept
|
||||
|
||||
# Accept DNS queries from LAN networks
|
||||
ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64, 2602:F674:3000::/64 } udp dport 53 accept
|
||||
ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64, 2602:F674:3000::/64 } tcp dport 53 accept
|
||||
|
||||
# Accept DHCPv6 from clients
|
||||
ip6 saddr fe80::/10 udp sport 546 udp dport 547 accept
|
||||
|
||||
# Accept NTP from LAN
|
||||
ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64 } udp dport 123 accept
|
||||
|
||||
# Log dropped packets (rate limited)
|
||||
limit rate 5/minute log prefix "IPv6-INPUT-DROP: "
|
||||
|
||||
# Drop everything else
|
||||
drop
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
# Accept established/related
|
||||
ct state established,related accept
|
||||
|
||||
# Accept ICMPv6 forwarding
|
||||
icmpv6 type {
|
||||
destination-unreachable,
|
||||
packet-too-big,
|
||||
time-exceeded,
|
||||
parameter-problem,
|
||||
echo-request,
|
||||
echo-reply
|
||||
} accept
|
||||
|
||||
# Forward from LAN to WAN
|
||||
iif "eth1" oif "eth0" ip6 saddr 2602:F674:1000::/64 accept
|
||||
|
||||
# Forward from Guest to WAN (no access to LAN)
|
||||
iif "eth2" oif "eth0" ip6 saddr 2602:F674:2000::/64 accept
|
||||
|
||||
# Forward from Management to WAN
|
||||
iif "eth3" oif "eth0" ip6 saddr 2602:F674:3000::/64 accept
|
||||
|
||||
# Block guest network from accessing LAN
|
||||
iif "eth2" oif { "eth1", "eth3" } drop
|
||||
iif { "eth1", "eth3" } oif "eth2" drop
|
||||
|
||||
# Log dropped forwards (rate limited)
|
||||
limit rate 5/minute log prefix "IPv6-FORWARD-DROP: "
|
||||
|
||||
drop
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
# IPv6 NAT table (usually not needed for IPv6, but included for completeness)
|
||||
table ip6 nat {
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
# IPv6 typically doesn't use NAT
|
||||
# If you need NPTv6 (Network Prefix Translation), add rules here
|
||||
}
|
||||
}
|
||||
NFTABLES_EOF
|
||||
|
||||
# Make executable
|
||||
chmod +x /etc/nftables.conf
|
||||
|
||||
# Test nftables configuration
|
||||
log_info "Testing nftables configuration..."
|
||||
if nft -c -f /etc/nftables.conf; then
|
||||
log_success "nftables configuration is valid"
|
||||
else
|
||||
log_error "nftables configuration has errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Apply nftables rules
|
||||
nft -f /etc/nftables.conf
|
||||
|
||||
# Enable nftables service
|
||||
systemctl enable nftables
|
||||
|
||||
log_success "nftables firewall configured"
|
||||
}
|
||||
|
||||
verify_configuration() {
|
||||
log_info "Verifying IPv6 configuration..."
|
||||
|
||||
echo ""
|
||||
echo "=== Interface IPv6 Addresses ==="
|
||||
ip -6 addr show | grep -E "inet6|^[0-9]:"
|
||||
echo ""
|
||||
|
||||
echo "=== IPv6 Routing Table ==="
|
||||
ip -6 route show
|
||||
echo ""
|
||||
|
||||
echo "=== BIRD Protocols ==="
|
||||
birdc show protocols 2>/dev/null || log_warn "BIRD not responding (may need to restart)"
|
||||
echo ""
|
||||
|
||||
echo "=== radvd Status ==="
|
||||
systemctl status radvd --no-pager | head -10
|
||||
echo ""
|
||||
|
||||
echo "=== Firewall Rules ==="
|
||||
nft list ruleset | grep -A3 "table ip6"
|
||||
echo ""
|
||||
|
||||
log_success "Verification complete"
|
||||
}
|
||||
|
||||
print_next_steps() {
|
||||
cat << 'EOF'
|
||||
|
||||
╔═══════════════════════════════════════════════════════════════╗
|
||||
║ DEPLOYMENT COMPLETE ║
|
||||
╚═══════════════════════════════════════════════════════════════╝
|
||||
|
||||
Next Steps:
|
||||
|
||||
1. Update BIRD Configuration with Actual Telus Gateway Addresses:
|
||||
- Edit /etc/bird/bird.conf
|
||||
- Replace placeholder addresses (fe80::1, fe80::2, fe80::3)
|
||||
- With actual Telus IPv6 gateway addresses
|
||||
- Restart BIRD: systemctl restart bird
|
||||
|
||||
2. Verify BGP Sessions:
|
||||
birdc show protocols
|
||||
birdc show protocols all telus_peer1_v6
|
||||
|
||||
3. Check Routes:
|
||||
birdc show route protocol telus_peer1_v6
|
||||
ip -6 route show
|
||||
|
||||
4. Test Connectivity:
|
||||
ping6 google.com
|
||||
ping6 2606:4700:4700::1111
|
||||
|
||||
5. Verify Router Advertisements:
|
||||
# On a LAN client
|
||||
rdisc6 eth0
|
||||
ip -6 addr show
|
||||
|
||||
6. Monitor Logs:
|
||||
journalctl -u bird -f
|
||||
journalctl -u radvd -f
|
||||
journalctl -k | grep IPv6
|
||||
|
||||
7. Optional: Restart networking if interfaces didn't configure:
|
||||
systemctl restart networking
|
||||
# Or reboot: reboot
|
||||
|
||||
Configuration Files:
|
||||
- BIRD: /etc/bird/bird.conf
|
||||
- radvd: /etc/radvd.conf
|
||||
- nftables: /etc/nftables.conf
|
||||
- sysctl: /etc/sysctl.conf
|
||||
|
||||
Documentation:
|
||||
- Full guide: IPV6_ROUTING_INTEGRATION.md
|
||||
- Architecture: ORION_HYBRID_ARCHITECTURE.md
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
print_banner
|
||||
echo ""
|
||||
|
||||
check_root
|
||||
check_prerequisites
|
||||
echo ""
|
||||
|
||||
install_packages
|
||||
echo ""
|
||||
|
||||
configure_sysctl
|
||||
echo ""
|
||||
|
||||
log_warn "The following step will modify network configuration."
|
||||
log_warn "Continue? (y/N)"
|
||||
read -r response
|
||||
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
||||
log_info "Aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
configure_network_interfaces
|
||||
echo ""
|
||||
|
||||
configure_bird
|
||||
echo ""
|
||||
|
||||
configure_radvd
|
||||
echo ""
|
||||
|
||||
configure_firewall
|
||||
echo ""
|
||||
|
||||
verify_configuration
|
||||
echo ""
|
||||
|
||||
print_next_steps
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
# BIRD2 IPv6 Configuration for ORION Router (AS394955)
|
||||
# Dell R730 - Router VM 200
|
||||
# IPv6 Prefix: 2602:F674::/48
|
||||
# Generated: 2025-01-22
|
||||
|
||||
log syslog all;
|
||||
debug protocols { states, routes, filters, interfaces };
|
||||
|
||||
# Router ID (use IPv4 address as ID for both IPv4 and IPv6)
|
||||
router id 100.64.0.1;
|
||||
|
||||
# Device protocol - learn interface information
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
# Direct protocol - learn directly connected networks
|
||||
protocol direct {
|
||||
ipv6;
|
||||
interface "eth0", "eth1", "eth2", "eth3";
|
||||
}
|
||||
|
||||
# Kernel protocol - sync routes with kernel routing table
|
||||
protocol kernel kernel6 {
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
learn;
|
||||
persist;
|
||||
scan time 20;
|
||||
metric 100;
|
||||
}
|
||||
|
||||
# Static routes
|
||||
protocol static static6 {
|
||||
ipv6;
|
||||
|
||||
# Announce our prefix (blackhole to prevent loops)
|
||||
route 2602:F674::/48 reject;
|
||||
|
||||
# Specific subnets (will be directly connected)
|
||||
# These are learned via the direct protocol, but we keep them for reference
|
||||
# route 2602:F674:1000::/64 via "eth1"; # LAN
|
||||
# route 2602:F674:2000::/64 via "eth2"; # Guest
|
||||
# route 2602:F674:3000::/64 via "eth3"; # Management
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# FILTER DEFINITIONS
|
||||
# ============================================================================
|
||||
|
||||
# Outbound filter - what we announce to Telus
|
||||
filter bgp_out_ipv6 {
|
||||
# Only announce our allocated prefix and more specific subnets
|
||||
if net ~ [ 2602:F674::/48{48,64} ] then {
|
||||
# Prepend our AS to the path
|
||||
bgp_path.prepend(394955);
|
||||
|
||||
# Set communities (optional - adjust based on Telus requirements)
|
||||
# bgp_community.add((394955, 100)); # Example community
|
||||
|
||||
accept;
|
||||
}
|
||||
|
||||
# Reject everything else
|
||||
reject;
|
||||
}
|
||||
|
||||
# Inbound filter - what we accept from Telus
|
||||
filter bgp_in_ipv6 {
|
||||
# Accept default route
|
||||
if net = ::/0 then {
|
||||
accept;
|
||||
}
|
||||
|
||||
# Accept global unicast addresses (2000::/3)
|
||||
if net ~ [ 2000::/3{0,64} ] then {
|
||||
accept;
|
||||
}
|
||||
|
||||
# Reject our own prefix (should never receive this)
|
||||
if net ~ [ 2602:F674::/48+ ] then {
|
||||
print "Rejecting our own prefix from peer: ", net;
|
||||
reject;
|
||||
}
|
||||
|
||||
# Reject bogon prefixes
|
||||
if net ~ [
|
||||
::/0{0,7}, # Too short
|
||||
::/8+, # Loopback, etc.
|
||||
100::/8+, # Discard
|
||||
2001::/32+, # TEREDO
|
||||
2001:2::/48+, # Benchmarking
|
||||
2001:10::/28+, # ORCHID
|
||||
2001:db8::/32+, # Documentation
|
||||
2002::/16+, # 6to4
|
||||
3ffe::/16+, # Old 6bone
|
||||
fc00::/7+, # ULA
|
||||
fe80::/10+, # Link-local
|
||||
fec0::/10+, # Old site-local
|
||||
ff00::/8+ # Multicast
|
||||
] then {
|
||||
print "Rejecting bogon prefix: ", net;
|
||||
reject;
|
||||
}
|
||||
|
||||
# Accept everything else
|
||||
accept;
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# BGP TEMPLATE FOR TELUS PEERS
|
||||
# ============================================================================
|
||||
|
||||
template bgp telus_ipv6 {
|
||||
local as 394955;
|
||||
|
||||
ipv6 {
|
||||
import filter bgp_in_ipv6;
|
||||
export filter bgp_out_ipv6;
|
||||
next hop self;
|
||||
};
|
||||
|
||||
# BGP timers
|
||||
hold time 90;
|
||||
keepalive time 30;
|
||||
connect retry time 120;
|
||||
connect delay time 5;
|
||||
error wait time 60,300;
|
||||
|
||||
# Enable graceful restart
|
||||
graceful restart on;
|
||||
graceful restart time 120;
|
||||
|
||||
# Path selection
|
||||
path metric 1;
|
||||
|
||||
# Disable MED comparison for multiple paths
|
||||
igp metric on;
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# TELUS BGP PEERS (IPv6)
|
||||
# ============================================================================
|
||||
|
||||
# Note: Replace these IPv6 addresses with actual Telus gateway addresses
|
||||
# The addresses below are examples based on your IPv6 prefix allocation
|
||||
|
||||
# Telus BGP Peer 1 (Primary)
|
||||
protocol bgp telus_peer1_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 1 - IPv6 (Primary)";
|
||||
|
||||
# TODO: Replace with actual Telus IPv6 gateway address
|
||||
# This is a placeholder - get actual address from Telus
|
||||
neighbor fe80::1 % 'eth0' as 6939;
|
||||
# Or if they provide global address:
|
||||
# neighbor 2602:F674:0000::ffff as 6939;
|
||||
|
||||
source address 2602:F674:0000::1;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Prefer this peer (highest local preference)
|
||||
bgp_local_pref = 150;
|
||||
|
||||
# Apply inbound filter
|
||||
if bgp_in_ipv6() then accept;
|
||||
reject;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
|
||||
# Prefer routes from this peer
|
||||
preference 100;
|
||||
}
|
||||
|
||||
# Telus BGP Peer 2 (Secondary)
|
||||
protocol bgp telus_peer2_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 2 - IPv6 (Secondary)";
|
||||
|
||||
# TODO: Replace with actual Telus IPv6 gateway address
|
||||
neighbor fe80::2 % 'eth0' as 6939;
|
||||
# Or: neighbor 2602:F674:0000::fffe as 6939;
|
||||
|
||||
source address 2602:F674:0000::1;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Lower preference than peer1
|
||||
bgp_local_pref = 100;
|
||||
|
||||
if bgp_in_ipv6() then accept;
|
||||
reject;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
|
||||
# Lower preference than peer 1
|
||||
preference 90;
|
||||
}
|
||||
|
||||
# Telus BGP Peer 3 (Tertiary)
|
||||
protocol bgp telus_peer3_v6 from telus_ipv6 {
|
||||
description "Telus Gateway 3 - IPv6 (Tertiary)";
|
||||
|
||||
# TODO: Replace with actual Telus IPv6 gateway address
|
||||
neighbor fe80::3 % 'eth0' as 6939;
|
||||
# Or: neighbor 2602:F674:0000::fffd as 6939;
|
||||
|
||||
source address 2602:F674:0000::1;
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
# Lowest preference
|
||||
bgp_local_pref = 50;
|
||||
|
||||
if bgp_in_ipv6() then accept;
|
||||
reject;
|
||||
};
|
||||
export filter bgp_out_ipv6;
|
||||
};
|
||||
|
||||
# Lowest preference
|
||||
preference 80;
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# BFD (Bidirectional Forwarding Detection) - Optional
|
||||
# ============================================================================
|
||||
# Uncomment if Telus supports BFD for faster failure detection
|
||||
|
||||
# protocol bfd {
|
||||
# interface "eth0" {
|
||||
# min rx interval 100 ms;
|
||||
# min tx interval 100 ms;
|
||||
# idle tx interval 300 ms;
|
||||
# multiplier 5;
|
||||
# };
|
||||
# }
|
||||
|
||||
# ============================================================================
|
||||
# NOTES
|
||||
# ============================================================================
|
||||
#
|
||||
# 1. Update the neighbor addresses with actual Telus IPv6 gateway addresses
|
||||
# These should be provided by Telus during BGP setup
|
||||
#
|
||||
# 2. If using link-local addresses (fe80::), you must specify the interface
|
||||
# with % 'eth0' syntax
|
||||
#
|
||||
# 3. Verify BGP session status with:
|
||||
# birdc6 show protocols
|
||||
# birdc6 show protocols all telus_peer1_v6
|
||||
#
|
||||
# 4. Check received routes:
|
||||
# birdc6 show route protocol telus_peer1_v6
|
||||
#
|
||||
# 5. Check announced routes:
|
||||
# birdc6 show route export telus_peer1_v6
|
||||
#
|
||||
# 6. Test filters:
|
||||
# birdc6 eval 2602:F674::/48
|
||||
#
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
# Router Advertisement Daemon Configuration
|
||||
# ORION Router VM 200 - IPv6 SLAAC
|
||||
# Provides automatic IPv6 configuration for LAN clients
|
||||
|
||||
# ============================================================================
|
||||
# LAN Interface (eth1) - 2602:F674:1000::/64
|
||||
# ============================================================================
|
||||
interface eth1 {
|
||||
# Enable router advertisements
|
||||
AdvSendAdvert on;
|
||||
|
||||
# Minimum time between RAs (seconds)
|
||||
MinRtrAdvInterval 3;
|
||||
|
||||
# Maximum time between RAs (seconds)
|
||||
MaxRtrAdvInterval 10;
|
||||
|
||||
# Don't use DHCPv6 for address assignment (use SLAAC)
|
||||
AdvManagedFlag off;
|
||||
|
||||
# Use DHCPv6 for other configuration (DNS, NTP, etc.)
|
||||
AdvOtherConfigFlag on;
|
||||
|
||||
# Router lifetime (0 = not a default router, >0 = default router)
|
||||
AdvDefaultLifetime 1800;
|
||||
|
||||
# Preference for this router (low, medium, high)
|
||||
AdvDefaultPreference high;
|
||||
|
||||
# Link MTU
|
||||
AdvLinkMTU 1500;
|
||||
|
||||
# Reachable time (milliseconds)
|
||||
AdvReachableTime 30000;
|
||||
|
||||
# Retrans timer (milliseconds)
|
||||
AdvRetransTimer 1000;
|
||||
|
||||
# Current hop limit
|
||||
AdvCurHopLimit 64;
|
||||
|
||||
# Prefix for LAN
|
||||
prefix 2602:F674:1000::/64 {
|
||||
# Prefix is on-link
|
||||
AdvOnLink on;
|
||||
|
||||
# Clients can use SLAAC
|
||||
AdvAutonomous on;
|
||||
|
||||
# Include router address in RA
|
||||
AdvRouterAddr on;
|
||||
|
||||
# Valid lifetime (seconds) - how long prefix is valid
|
||||
AdvValidLifetime 86400; # 24 hours
|
||||
|
||||
# Preferred lifetime (seconds) - how long to prefer this prefix
|
||||
AdvPreferredLifetime 43200; # 12 hours
|
||||
};
|
||||
|
||||
# Recursive DNS Servers (Cloudflare)
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
|
||||
# DNS Search List
|
||||
DNSSL orion.local {
|
||||
AdvDNSSLLifetime 300;
|
||||
};
|
||||
|
||||
# Route Information (optional - for more specific routes)
|
||||
# route 2602:F674::/48 {
|
||||
# AdvRouteLifetime 1800;
|
||||
# AdvRoutePreference high;
|
||||
# };
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Guest Network Interface (eth2) - 2602:F674:2000::/64
|
||||
# ============================================================================
|
||||
interface eth2 {
|
||||
AdvSendAdvert on;
|
||||
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
|
||||
AdvManagedFlag off;
|
||||
AdvOtherConfigFlag on;
|
||||
|
||||
AdvDefaultLifetime 1800;
|
||||
AdvDefaultPreference medium; # Lower than LAN
|
||||
|
||||
AdvLinkMTU 1500;
|
||||
|
||||
prefix 2602:F674:2000::/64 {
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
AdvValidLifetime 86400;
|
||||
AdvPreferredLifetime 43200;
|
||||
};
|
||||
|
||||
# Use public DNS for guest network (no local DNS)
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
|
||||
DNSSL guest.orion.local {
|
||||
AdvDNSSLLifetime 300;
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Management Network Interface (eth3) - 2602:F674:3000::/64
|
||||
# ============================================================================
|
||||
interface eth3 {
|
||||
AdvSendAdvert on;
|
||||
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
|
||||
AdvManagedFlag off;
|
||||
AdvOtherConfigFlag on;
|
||||
|
||||
AdvDefaultLifetime 1800;
|
||||
AdvDefaultPreference high;
|
||||
|
||||
AdvLinkMTU 1500;
|
||||
|
||||
prefix 2602:F674:3000::/64 {
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
AdvValidLifetime 86400;
|
||||
AdvPreferredLifetime 43200;
|
||||
};
|
||||
|
||||
RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 {
|
||||
AdvRDNSSLifetime 300;
|
||||
};
|
||||
|
||||
DNSSL mgmt.orion.local {
|
||||
AdvDNSSLLifetime 300;
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# NOTES
|
||||
# ============================================================================
|
||||
#
|
||||
# Test configuration:
|
||||
# radvd -c /etc/radvd.conf -C
|
||||
#
|
||||
# Start daemon:
|
||||
# systemctl start radvd
|
||||
#
|
||||
# Check status:
|
||||
# systemctl status radvd
|
||||
#
|
||||
# Monitor RAs on client:
|
||||
# rdisc6 eth0
|
||||
# tcpdump -i eth0 -n icmp6
|
||||
#
|
||||
# Verify clients receive addresses:
|
||||
# ip -6 addr show
|
||||
#
|
||||
# Expected client address format:
|
||||
# 2602:f674:1000::<EUI-64 or random>/64
|
||||
#
|
||||
Loading…
Reference in New Issue