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:
Claude 2025-11-22 02:39:02 +00:00
parent 43c22f4243
commit 5a99cbeb52
No known key found for this signature in database
4 changed files with 1842 additions and 0 deletions

859
IPV6_ROUTING_INTEGRATION.md Normal file
View File

@ -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

551
deploy-ipv6-routing.sh Executable file
View File

@ -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 "$@"

View File

@ -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
#

View File

@ -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
#