-
Notifications
You must be signed in to change notification settings - Fork 461
Use Cases Enterprise WAN
ExaBGP enables enterprise WAN connectivity using MPLS L3VPN, SD-WAN integration, and hybrid multi-cloud networking for branch offices and remote sites.
- Overview
- MPLS L3VPN for Branch Offices
- SD-WAN Integration
- Hybrid Cloud Connectivity
- Configuration Examples
- See Also
Modern enterprise WANs need:
- Multi-site connectivity: Connect headquarters, branch offices, data centers
- Application performance: Prioritize critical applications
- Cost efficiency: Balance MPLS, internet, and cloud connectivity
- Security: Encrypt traffic, segment networks
- Resilience: Automatic failover between links
- Cloud integration: Connect to AWS, Azure, GCP
ExaBGP enables enterprise WAN by:
- VPN route distribution: Advertise site prefixes via L3VPN
- SD-WAN integration: Dynamic path selection based on health/performance
- Cloud connectivity: Integrate with cloud provider BGP services
- Traffic engineering: Use communities for policy-based routing
Important: ExaBGP exchanges routes but does NOT create VPN tunnels. Use IPsec, GRE, or MPLS for actual connectivity.
[HQ Site] <--L3VPN--> [Service Provider MPLS] <--L3VPN--> [Branch Sites]
VRF: CORP VRF: CORP
Branch Office (/etc/exabgp/branch-vpn.conf):
process vpn-routes {
run python3 /etc/exabgp/announce-branch.py;
encoder text;
}
neighbor 192.0.2.1 {
router-id 10.1.1.1;
local-address 10.1.1.1;
local-as 65001;
peer-as 65000;
family {
ipv4 mpls-vpn;
}
api {
processes [ vpn-routes ];
}
}API Program (/etc/exabgp/announce-branch.py):
#!/usr/bin/env python3
import sys
# Branch site configuration
BRANCH_ID = "branch-01"
BRANCH_PREFIX = "10.100.1.0/24"
RD = "10.1.1.1:100"
RT_EXPORT = "65000:100"
RT_IMPORT = "65000:100"
NEXT_HOP = "10.1.1.1"
# Announce branch prefix to MPLS VPN
print(f"announce route {BRANCH_PREFIX} "
f"next-hop {NEXT_HOP} "
f"route-distinguisher {RD} "
f"route-target {RT_EXPORT}", flush=True)
while True:
line = sys.stdin.readline().strip()
if not line:
breakSupport multiple customer VRFs:
#!/usr/bin/env python3
import sys
# Multiple VRFs for segmentation
VRFS = {
'corporate': {
'prefix': '10.100.1.0/24',
'rd': '10.1.1.1:100',
'rt': '65000:100'
},
'guest': {
'prefix': '10.200.1.0/24',
'rd': '10.1.1.1:200',
'rt': '65000:200'
},
'iot': {
'prefix': '10.300.1.0/24',
'rd': '10.1.1.1:300',
'rt': '65000:300'
}
}
NEXT_HOP = "10.1.1.1"
# Announce all VRFs
for vrf_name, config in VRFS.items():
print(f"announce route {config['prefix']} "
f"next-hop {NEXT_HOP} "
f"route-distinguisher {config['rd']} "
f"route-target {config['rt']}", flush=True)
while True:
line = sys.stdin.readline().strip()
if not line:
breakDynamically select best WAN path:
#!/usr/bin/env python3
import sys
import time
import subprocess
# WAN links
LINKS = {
'mpls': {'next_hop': '10.1.1.1', 'priority': 1},
'internet': {'next_hop': '10.2.2.1', 'priority': 2},
'lte': {'next_hop': '10.3.3.1', 'priority': 3}
}
PREFIX = "10.100.1.0/24"
def check_link_health(link_name):
"""Check if WAN link is healthy"""
next_hop = LINKS[link_name]['next_hop']
try:
result = subprocess.run(
['ping', '-c', '3', '-W', '2', next_hop],
capture_output=True
)
return result.returncode == 0
except:
return False
def select_best_link():
"""Select best available WAN link"""
for link_name in sorted(LINKS.keys(), key=lambda x: LINKS[x]['priority']):
if check_link_health(link_name):
return link_name, LINKS[link_name]['next_hop']
return None, None
# Monitor and switch paths
current_link = None
while True:
best_link, next_hop = select_best_link()
if best_link != current_link:
# Withdraw old path
if current_link:
old_hop = LINKS[current_link]['next_hop']
print(f"withdraw route {PREFIX} next-hop {old_hop}", flush=True)
# Announce new path
if next_hop:
print(f"announce route {PREFIX} next-hop {next_hop}", flush=True)
current_link = best_link
time.sleep(10)Route based on application requirements:
#!/usr/bin/env python3
import sys
# Application-to-path mapping
APPLICATIONS = {
'voice': {
'prefix': '10.100.10.0/24',
'path': 'mpls', # Low latency
'community': '65000:100'
},
'bulk-transfer': {
'prefix': '10.100.20.0/24',
'path': 'internet', # High bandwidth
'community': '65000:200'
},
'guest': {
'prefix': '10.100.30.0/24',
'path': 'internet', # Separate from corporate
'community': '65000:300'
}
}
LINKS = {
'mpls': '10.1.1.1',
'internet': '10.2.2.1',
'lte': '10.3.3.1'
}
# Announce application routes with appropriate paths
for app_name, config in APPLICATIONS.items():
next_hop = LINKS.get(config['path'])
if next_hop:
print(f"announce route {config['prefix']} "
f"next-hop {next_hop} "
f"community [{config['community']}]", flush=True)
while True:
line = sys.stdin.readline().strip()
if not line:
breakConnect enterprise WAN to AWS VPC:
#!/usr/bin/env python3
import sys
import boto3
# AWS configuration
AWS_REGION = 'us-east-1'
VPC_ID = 'vpc-12345678'
# On-premises configuration
ONPREM_PREFIX = "10.100.0.0/16"
NEXT_HOP = "10.1.1.1"
def get_vpc_prefixes():
"""Get VPC CIDR blocks from AWS"""
ec2 = boto3.client('ec2', region_name=AWS_REGION)
try:
vpcs = ec2.describe_vpcs(VpcIds=[VPC_ID])
cidrs = []
for vpc in vpcs['Vpcs']:
cidr = vpc.get('CidrBlock')
if cidr:
cidrs.append(cidr)
return cidrs
except:
return []
# Announce on-premises routes to AWS
print(f"announce route {ONPREM_PREFIX} next-hop {NEXT_HOP}", flush=True)
# Can also learn and re-advertise AWS VPC routes
vpc_prefixes = get_vpc_prefixes()
for prefix in vpc_prefixes:
# Re-advertise VPC routes to other sites if needed
pass
while True:
line = sys.stdin.readline().strip()
if not line:
breakRoute between on-prem, AWS, Azure, GCP:
#!/usr/bin/env python3
import sys
# Cloud connectivity
CLOUDS = {
'aws': {
'prefix': '10.10.0.0/16',
'next_hop': '169.254.1.1', # AWS VGW
'community': '65000:10'
},
'azure': {
'prefix': '10.20.0.0/16',
'next_hop': '169.254.2.1', # Azure VNG
'community': '65000:20'
},
'gcp': {
'prefix': '10.30.0.0/16',
'next_hop': '169.254.3.1', # GCP Cloud Router
'community': '65000:30'
},
'onprem': {
'prefix': '10.100.0.0/16',
'next_hop': '10.1.1.1',
'community': '65000:100'
}
}
# Announce all cloud routes
for cloud_name, config in CLOUDS.items():
print(f"announce route {config['prefix']} "
f"next-hop {config['next_hop']} "
f"community [{config['community']}]", flush=True)
while True:
line = sys.stdin.readline().strip()
if not line:
breakCentral hub site connecting to multiple branches:
Hub Site (/etc/exabgp/hub.conf):
process hub-routes {
run python3 /etc/exabgp/hub-announce.py;
encoder json;
}
# Connection to service provider
neighbor 192.0.2.1 {
router-id 10.0.0.1;
local-address 10.0.0.1;
local-as 65001;
peer-as 65000;
family {
ipv4 mpls-vpn;
ipv4 unicast;
}
api {
processes [ hub-routes ];
}
}Hub API Program:
#!/usr/bin/env python3
import sys
# Hub site routes
HUB_ROUTES = {
'datacenter': '10.0.0.0/16',
'services': '10.1.0.0/16',
'internet-gateway': '0.0.0.0/0'
}
RD = "10.0.0.1:100"
RT = "65000:100"
NEXT_HOP = "10.0.0.1"
# Announce hub routes to all branches
for route_name, prefix in HUB_ROUTES.items():
print(f"announce route {prefix} "
f"next-hop {NEXT_HOP} "
f"route-distinguisher {RD} "
f"route-target {RT}", flush=True)
while True:
line = sys.stdin.readline().strip()
if not line:
breakBranch with redundant WAN links:
#!/usr/bin/env python3
import sys
import time
BRANCH_PREFIX = "10.100.1.0/24"
# Primary and backup links
LINKS = {
'primary': {
'next_hop': '10.1.1.1',
'as_prepend': '', # Preferred path
'local_pref': 200
},
'backup': {
'next_hop': '10.2.2.1',
'as_prepend': '65001 65001 65001', # Less preferred
'local_pref': 100
}
}
def check_link(next_hop):
"""Check link health"""
import subprocess
try:
result = subprocess.run(
['ping', '-c', '2', '-W', '1', next_hop],
capture_output=True
)
return result.returncode == 0
except:
return False
# Announce via both links with different preferences
primary_ok = check_link(LINKS['primary']['next_hop'])
backup_ok = check_link(LINKS['backup']['next_hop'])
if primary_ok:
print(f"announce route {BRANCH_PREFIX} "
f"next-hop {LINKS['primary']['next_hop']} "
f"local-preference {LINKS['primary']['local_pref']}", flush=True)
if backup_ok:
print(f"announce route {BRANCH_PREFIX} "
f"next-hop {LINKS['backup']['next_hop']} "
f"local-preference {LINKS['backup']['local_pref']} "
f"as-path [{LINKS['backup']['as_prepend']}]", flush=True)
while True:
time.sleep(30)π» Ghost written by Claude (Anthropic AI)
π Home
π Getting Started
π§ API
π‘οΈ Use Cases
π Address Families
βοΈ Configuration
π Operations
π Reference
- Architecture
- BGP State Machine
- Communities (RFC)
- Extended Communities
- BGP Ecosystem
- Capabilities (AFI/SAFI)
- RFC Support
π Migration
π Community
π External
- GitHub Repo β
- Slack β
- Issues β
π» Ghost written by Claude (Anthropic AI)