全球多入口 IPv6 BGP 宣告与 Anycast VPN 自动就近接入方案
(基于原生 WireGuard + 自动化脚本,每客户端 /64 子网)
适用于 Debian 12 / Ubuntu 22.04 LTS
1. 方案概述
-
香港、美国双节点同时运行 BIRD BGP,向互联网宣告聚合前缀
2886:880:668::/44、本地/48子网及 Anycast VIP/128。 -
节点间通过 WireGuard 隧道 建立 iBGP 连接,交换路由。
-
客户端通过 Anycast VIP 自动就近接入(国内→香港,国外→美国)。
-
使用 原生 WireGuard 服务端 + Python 自动化脚本 管理客户端:
-
从
/56地址池自动分配/64子网。 -
自动添加系统路由与 BIRD 静态路由。
-
自动生成客户端配置文件。
-
-
客户端路由器通过 SLAAC(radvd) 向下联设备分配公网 IPv6 地址,零配置即插即用。
-
回程路由由 BGP 优选保证直达客户端所在节点。
无需任何第三方 Web 管理工具,完全自控,高性能,易扩展。
2. 网络拓扑与地址规划
| 节点 | 公网 IPv6 地址 (EBGP 源) | 隧道 IPv6 (iBGP) | Anycast VIP | 本地宣告 /48 子网 | 客户端 /56 地址池 | 客户端分配 /64 子网 |
|---|---|---|---|---|---|---|
| 香港 | 2886:880:668:4::1 |
fd00::2/64 |
2886:880:668:ff::1/128 |
2886:880:668:4::/48 |
2886:880:668:4:1000::/56 |
2886:880:668:4:10xx::/64 |
| 美国 | 2886:880:668:3::1 |
fd00::3/64 |
2886:880:668:ff::1/128 |
2886:880:668:3::/48 |
2886:880:668:3:1000::/56 |
2886:880:668:3:10xx::/64 |
-
隧道 IPv4 规划(用于路由下一跳):
-
香港节点服务端隧道 IP:
10.9.0.1/24 -
客户端隧道 IP:
10.9.0.2/32起顺序分配
-
-
节点间 iBGP 隧道 IP(独立于客户端隧道):
-
香港:
10.8.0.1/24,美国:10.8.0.2/24,IPv6:fd00::2/64,fd00::3/64
-
3. 基础系统配置(香港 & 美国节点)
3.1 系统更新与必要软件安装
apt update && apt upgrade -y apt install -y bird2 wireguard-tools python3 python3-pip sqlite3 radvd tcpdump mtr iptables ip6tables net-tools curl pip3 install ipaddress # 用于脚本中的 IPv6 处理
3.2 启用 IPv6 转发并优化内核参数
cat > /etc/sysctl.d/99-ipv6.conf <<EOF net.ipv6.conf.all.forwarding = 1 net.ipv6.conf.default.forwarding = 1 net.ipv6.conf.all.accept_ra = 2 net.ipv6.conf.default.accept_ra = 2 net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.all.proxy_ndp = 1 EOF sysctl -p /etc/sysctl.d/99-ipv6.conf
3.3 配置公网 IPv6 地址(根据实际情况)
香港节点:
ip -6 addr add 2886:880:668:4::1/64 dev eth0
持久化(以 Netplan 为例):
# /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
addresses:
- 2886:880:668:4::1/64
netplan apply
美国节点:
ip -6 addr add 2886:880:668:3::1/64 dev eth0
持久化类似。
3.4 配置 Anycast VIP(两节点相同)
ip -6 addr add 2886:880:668:ff::1/128 dev lo
持久化(Netplan 或 systemd-networkd):
# /etc/netplan/99-anycast.yaml
network:
version: 2
ethernets:
lo:
addresses:
- "2886:880:668:ff::1/128"
netplan apply
4. 节点间 iBGP 隧道(WireGuard)
4.1 生成密钥对(两节点)
mkdir -p /etc/wireguard cd /etc/wireguard umask 077 wg genkey | tee wg0-privatekey | wg pubkey > wg0-publickey
4.2 香港节点配置 /etc/wireguard/wg0.conf
[Interface] Address = fd00::2/64, 10.8.0.1/24 PrivateKey = <香港节点 wg0-privatekey 内容> ListenPort = 51820 MTU = 1420 PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT [Peer] PublicKey = <美国节点 wg0-publickey 内容> AllowedIPs = fd00::3/128, 10.8.0.2/32 Endpoint = [美国公网IPv6地址]:51820 PersistentKeepalive = 25
4.3 美国节点配置 /etc/wireguard/wg0.conf
[Interface] Address = fd00::3/64, 10.8.0.2/24 PrivateKey = <美国节点 wg0-privatekey 内容> ListenPort = 51820 MTU = 1420 PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT [Peer] PublicKey = <香港节点 wg0-publickey 内容> AllowedIPs = fd00::2/128, 10.8.0.1/32 Endpoint = [香港公网IPv6地址]:51820 PersistentKeepalive = 25
4.4 启动并启用自启
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
wg show
验证:ping6 fd00::3 从香港到美国应通。
5. BIRD BGP 配置
5.1 通用过滤器(两节点相同)
创建目录 /etc/bird/conf.d/,编写 /etc/bird/conf.d/filters.conf:
# 非法前缀列表(IPv6 BOGON)
define BOGON_V6 = [
::/0, ::/8, 0100::/64, 0200::/7, 0400::/6, 0800::/5,
1000::/4, 4000::/3, 6000::/3, 8000::/3, a000::/3,
c000::/3, e000::/4, f000::/5, f800::/6, fc00::/7,
fe00::/9, fe80::/10, fec0::/10, ff00::/8,
::/96, ::ffff:0:0/96, 64:ff9b::/96, 100::/64,
2001::/32, 2001:2::/48, 2001:10::/28, 2001:db8::/32,
2002::/16, 3ffe::/16, ::1/128, ::/128
];
# 导入过滤器
filter import_filter {
if net ~ BOGON_V6 then reject;
if net.len < 16 || net.len > 48 then reject;
accept;
}
# 导出到 EBGP:只允许静态路由(聚合/44、本地/48、Anycast /128)
filter export_to_ebgp {
if net ~ BOGON_V6 then reject;
if net.len < 16 || net.len > 48 then reject;
if source = RTS_STATIC then accept;
reject;
}
# 导出到 iBGP:允许所有有效路由(包括客户端/64子网)
filter export_to_ibgp {
if net ~ BOGON_V6 then reject;
accept;
}
5.2 香港节点 BIRD 主配置 /etc/bird/bird.conf
router id 10.8.0.1; # 使用 iBGP 隧道 IPv4 地址 define ASN = 98885; define AGG_PREFIX = [2886:880:6680::/44+]; define LOCAL_SUBNET = [2886:880:6680:4::/48+]; define ANYCAST_VIP = [2886:880:6680:ff::1/128+]; log syslog { info, warning, error }; include "/etc/bird/conf.d/filters.conf"; protocol device { scan time 10; } protocol kernel { ipv6 { export all; }; persist yes; } protocol static static_agg { ipv6; route2886:880:6680::/44 blackhole; } protocol static static_local { ipv6; route2886:880:6680:4::/48 blackhole; } protocol static static_anycast { ipv6; route2886:880:6680:ff::1/128 blackhole; } # 动态客户端路由将通过 birdc 注入,此处仅初始化空文件 include "/etc/bird/static-routes.conf"; # EBGP 香港上游(请替换为真实对端信息) protocol bgp bgp_hk_isp { local2886:880:6680:4::1 as ASN; neighbor2886:880:6680as 99324; password "your_md5_key_here"; ipv6 { import filter import_filter; export filter export_to_ebgp; import limit 1000 action restart; }; } # iBGP 邻居(美国) protocol bgp ibgp_to_us { local fd00::2 as ASN; neighbor fd00::3 as ASN; ipv6 { import filter import_filter; export filter export_to_ibgp; next hop self; graceful restart; }; }
5.3 美国节点 BIRD 主配置 /etc/bird/bird.conf
router id 10.8.0.2; define ASN = 9999; define AGG_PREFIX = [2886:880:6680::/44+]; define LOCAL_SUBNET = [2886:880:6680:3::/48+]; define ANYCAST_VIP = [2886:880:6680:ff::1/128+]; # 其余部分与香港相同,注意修改 EBGP 邻居参数 protocol bgp bgp_us_isp { local2886:880:6680:3::1 as ASN; neighbor 2001:d58:2::1 as 1548; password "your_md5_key_here"; ... } protocol bgp ibgp_to_hk { local fd00::3 as ASN; neighbor fd00::2 as ASN; ... }
5.4 初始化静态路由文件
touch /etc/bird/static-routes.conf chmod 644 /etc/bird/static-routes.conf
5.5 启动 BIRD
systemctl enable bird
systemctl restart bird
birdc show protocols
确保 EBGP、iBGP 均为 Established。
6. 原生 WireGuard 服务端(客户端接入)
6.1 生成服务器密钥对
cd /etc/wireguard umask 077 wg genkey | tee server-privatekey | wg pubkey > server-publickey
6.2 创建服务端接口配置文件 /etc/wireguard/server.conf
[Interface] Address = 10.9.0.1/24 ListenPort = 51821 PrivateKey = <server-privatekey 内容> MTU = 1420 # 防火墙转发规则 PostUp = ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT PostDown = ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT # 客户端 Peer 将由脚本动态添加,此处不配置静态 Peer
注意:IPv6 地址不在接口上配置,客户端 IPv6 地址由脚本分配的 /64 子网决定,并作为路由加入系统。
6.3 启动服务端接口
systemctl enable wg-quick@server
systemctl start wg-quick@server
wg show server
7. 自动化脚本部署(核心)
7.1 创建项目目录
mkdir -p /opt/wg-bgp/{db,scripts,config,logs} cd /opt/wg-bgp
7.2 初始化 SQLite 数据库
数据库结构文件 /opt/wg-bgp/db/schema.sql:
-- 客户端表 CREATE TABLE IF NOT EXISTS clients ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, pubkey TEXT NOT NULL UNIQUE, psk TEXT, ipv4_tunnel TEXT NOT NULL UNIQUE, ipv6_subnet TEXT NOT NULL UNIQUE, enabled BOOLEAN DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- IPv4 隧道地址池 CREATE TABLE IF NOT EXISTS ipv4_pool ( id INTEGER PRIMARY KEY AUTOINCREMENT, address TEXT NOT NULL UNIQUE, status TEXT CHECK(status IN ('free','used')) DEFAULT 'free', assigned_to INTEGER, FOREIGN KEY(assigned_to) REFERENCES clients(id) ); -- IPv6 /64 子网池 CREATE TABLE IF NOT EXISTS ipv6_pool ( id INTEGER PRIMARY KEY AUTOINCREMENT, subnet TEXT NOT NULL UNIQUE, status TEXT CHECK(status IN ('free','used')) DEFAULT 'free', assigned_to INTEGER, FOREIGN KEY(assigned_to) REFERENCES clients(id) );
初始化地址池(香港节点示例):
sqlite3 /opt/wg-bgp/db/wg-bgp.db < /opt/wg-bgp/db/schema.sql sqlite3 /opt/wg-bgp/db/wg-bgp.db <<EOF -- IPv4 池 10.9.0.2 - 10.9.0.254 WITH RECURSIVE cnt(x) AS (VALUES(2) UNION ALL SELECT x+1 FROM cnt WHERE x<254) INSERT INTO ipv4_pool (address) SELECT printf('10.9.0.%d/32', x) FROM cnt; -- IPv6 池:2886:880:6680:4:1000::/56 → 256 个 /64 WITH RECURSIVE cnt(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM cnt WHERE x<255) INSERT INTO ipv6_pool (subnet) SELECT printf('22886:880:6680:4:%x::/64', 0x1000 + x) FROM cnt; EOF
美国节点:调整 IPv6 池为 2886:880:6680:3:1000::/56,IPv4 池建议使用 10.9.1.0/24 避免冲突(服务端地址 10.9.1.1/24,客户端 10.9.1.2/32 起)。
7.3 客户端管理脚本 /opt/wg-bgp/scripts/client_manager.py
#!/usr/bin/env python3 """ WireGuard 客户端管理脚本(原生 WireGuard + BIRD) 支持:添加/删除/列表客户端,自动分配 /64 子网,注入路由和 BGP 适用于 Debian/Ubuntu,Python 3.6+ """ import sqlite3 import subprocess import ipaddress import os import sys import argparse import secrets import re # ============ 配置参数 ============ DB_PATH = '/opt/wg-bgp/db/wg-bgp.db' WG_INTERFACE = 'server' # WireGuard 服务端接口名 BIRD_STATIC_FILE = '/etc/bird/static-routes.conf' SERVER_PUBKEY_FILE = '/etc/wireguard/server-publickey' SERVER_ENDPOINT = '2886:880:6680:ff::1:51821' # Anycast VIP + 端口 # ================================= def get_db(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row return conn def allocate_ipv4(conn): c = conn.cursor() c.execute("SELECT address FROM ipv4_pool WHERE status='free' LIMIT 1") row = c.fetchone() if not row: raise Exception("No free IPv4 address") addr = row['address'] c.execute("UPDATE ipv4_pool SET status='used' WHERE address=?", (addr,)) conn.commit() return addr def allocate_ipv6(conn): c = conn.cursor() c.execute("SELECT subnet FROM ipv6_pool WHERE status='free' LIMIT 1") row = c.fetchone() if not row: raise Exception("No free IPv6 subnet") subnet = row['subnet'] c.execute("UPDATE ipv6_pool SET status='used' WHERE subnet=?", (subnet,)) conn.commit() return subnet def release_ipv4(conn, addr): c = conn.cursor() c.execute("UPDATE ipv4_pool SET status='free', assigned_to=NULL WHERE address=?", (addr,)) conn.commit() def release_ipv6(conn, subnet): c = conn.cursor() c.execute("UPDATE ipv6_pool SET status='free', assigned_to=NULL WHERE subnet=?", (subnet,)) conn.commit() def generate_keypair(): priv = subprocess.check_output("wg genkey", shell=True, text=True).strip() pub = subprocess.check_output(f"echo {priv} | wg pubkey", shell=True, text=True).strip() psk = subprocess.check_output("wg genpsk", shell=True, text=True).strip() return priv, pub, psk def add_wg_peer(pubkey, psk, allowed_ips): """添加 WireGuard Peer""" ips = ','.join(allowed_ips) cmd = f"wg set {WG_INTERFACE} peer {pubkey} preshared-key /dev/stdin allowed-ips {ips}" proc = subprocess.run(cmd, shell=True, input=psk, text=True, capture_output=True) if proc.returncode != 0: raise Exception(f"wg set failed: {proc.stderr}") def remove_wg_peer(pubkey): cmd = f"wg set {WG_INTERFACE} peer {pubkey} remove" subprocess.run(cmd, shell=True, check=True) def add_system_route(subnet, via_ip): cmd = f"ip -6 route add {subnet} via {via_ip} dev {WG_INTERFACE}" subprocess.run(cmd, shell=True, check=True) def del_system_route(subnet): cmd = f"ip -6 route del {subnet}" subprocess.run(cmd, shell=True, check=False) def add_bird_route(subnet, via_ip): """通过 birdc 添加静态路由""" # 追加到静态路由文件并重载 with open(BIRD_STATIC_FILE, 'a') as f: f.write(f"route {subnet} via {via_ip} dev {WG_INTERFACE};\n") subprocess.run("birdc configure", shell=True, check=True) def del_bird_route(subnet): """从静态路由文件中删除指定路由并重载""" if not os.path.exists(BIRD_STATIC_FILE): return with open(BIRD_STATIC_FILE, 'r') as f: lines = f.readlines() with open(BIRD_STATIC_FILE, 'w') as f: for line in lines: if not line.strip().startswith(f"route {subnet}"): f.write(line) subprocess.run("birdc configure", shell=True, check=True) def generate_client_config(priv, pub, psk, client_ipv4, client_subnet, server_pub): """生成客户端 WireGuard 配置文件内容""" # client_ipv4: "10.9.0.2/32" # client_subnet: "2886:880:6680:4:1001::/64" first_ip = str(ipaddress.IPv6Network(client_subnet).network_address + 1) + "/64" config = f"""[Interface] Address = {client_ipv4.split('/')[0]}/32 Address = {first_ip} PrivateKey = {priv} DNS = 2001:4860:4860::8888 [Peer] PublicKey = {server_pub} PresharedKey = {psk} AllowedIPs = 0.0.0.0/0, ::/0 Endpoint = {SERVER_ENDPOINT} PersistentKeepalive = 25 """ return config def add_client(name): conn = get_db() try: # 1. 分配资源 ipv4 = allocate_ipv4(conn) ipv6_subnet = allocate_ipv6(conn) # 2. 生成密钥 priv, pub, psk = generate_keypair() # 3. 写入数据库 c = conn.cursor() c.execute(""" INSERT INTO clients (name, pubkey, psk, ipv4_tunnel, ipv6_subnet) VALUES (?, ?, ?, ?, ?) """, (name, pub, psk, ipv4, ipv6_subnet)) client_id = c.lastrowid c.execute("UPDATE ipv4_pool SET assigned_to=? WHERE address=?", (client_id, ipv4)) c.execute("UPDATE ipv6_pool SET assigned_to=? WHERE subnet=?", (client_id, ipv6_subnet)) conn.commit() # 4. 配置 WireGuard Peer via_ip = ipv4.split('/')[0] allowed_ips = [f"{via_ip}/32", ipv6_subnet] add_wg_peer(pub, psk, allowed_ips) # 5. 添加系统路由 add_system_route(ipv6_subnet, via_ip) # 6. 注入 BIRD add_bird_route(ipv6_subnet, via_ip) # 7. 读取服务器公钥 with open(SERVER_PUBKEY_FILE, 'r') as f: server_pub = f.read().strip() # 8. 生成客户端配置 client_config = generate_client_config(priv, pub, psk, ipv4, ipv6_subnet, server_pub) # 9. 输出配置 print(client_config) print(f"Client {name} added successfully, ID: {client_id}", file=sys.stderr) except Exception as e: conn.rollback() print(f"Error: {e}", file=sys.stderr) sys.exit(1) finally: conn.close() def delete_client(client_id): conn = get_db() try: c = conn.cursor() c.execute("SELECT pubkey, ipv4_tunnel, ipv6_subnet FROM clients WHERE id=?", (client_id,)) row = c.fetchone() if not row: print(f"Client ID {client_id} not found") return pubkey = row['pubkey'] ipv4 = row['ipv4_tunnel'] subnet = row['ipv6_subnet'] # 移除 WireGuard Peer remove_wg_peer(pubkey) # 删除系统路由 del_system_route(subnet) # 从 BIRD 删除路由 del_bird_route(subnet) # 释放地址池 release_ipv4(conn, ipv4) release_ipv6(conn, subnet) # 删除客户端记录 c.execute("DELETE FROM clients WHERE id=?", (client_id,)) conn.commit() print(f"Client {client_id} deleted successfully") except Exception as e: conn.rollback() print(f"Error: {e}") finally: conn.close() def list_clients(): conn = get_db() c = conn.cursor() c.execute("SELECT id, name, ipv4_tunnel, ipv6_subnet, enabled FROM clients") rows = c.fetchall() if not rows: print("No clients.") else: print("ID\tName\t\tIPv4\t\tIPv6 Subnet\t\tEnabled") print("-" * 70) for row in rows: print(f"{row['id']}\t{row['name']}\t{row['ipv4_tunnel']}\t{row['ipv6_subnet']}\t{row['enabled']}") conn.close() if __name__ == '__main__': parser = argparse.ArgumentParser(description='WireGuard Client Manager') subparsers = parser.add_subparsers(dest='action', required=True) add_parser = subparsers.add_parser('add', help='Add a new client') add_parser.add_argument('name', help='Client name') del_parser = subparsers.add_parser('del', help='Delete a client') del_parser.add_argument('client_id', type=int, help='Client ID') list_parser = subparsers.add_parser('list', help='List clients') args = parser.parse_args() if args.action == 'add': add_client(args.name) elif args.action == 'del': delete_client(args.client_id) elif args.action == 'list': list_clients()
7.4 脚本权限设置
chmod +x /opt/wg-bgp/scripts/client_manager.py ln -s /opt/wg-bgp/scripts/client_manager.py /usr/local/bin/wg-client
7.5 测试脚本
# 添加客户端(输出配置文件) wg-client add test01 > /root/test01.conf # 查看客户端列表 wg-client list # 删除客户端 wg-client del 1
注意:第一次运行时,需要确保 /etc/wireguard/server-publickey 存在,且 BIRD 静态路由文件 /etc/bird/static-routes.conf 可写。
8. 客户端路由器配置(SLAAC 自动分配)
客户端获得 /64 子网后,需要在本地网络进行 Router Advertisement,使下游设备自动获取地址。
8.1 客户端 Linux 网关配置示例
假设 WireGuard 接口为 wg0,内网接口为 eth1,分配的 /64 子网为 2886:880:6680:4:1001::/64,客户端隧道地址为 2886:880:6680:4:1001::1/64。
# 启用 IPv6 转发 sysctl -w net.ipv6.conf.all.forwarding=1 # 配置内网接口 IPv6 地址 ip -6 addr add2886:880:6680:4:1001::1/64 dev eth1 # 安装 radvd apt install radvd -y # 配置 radvd cat > /etc/radvd.conf <<EOF interface eth1 { AdvSendAdvert on; MinRtrAdvInterval 30; MaxRtrAdvInterval 100; prefix2886:880:6680:4:1001::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; }; RDNSS 2001:4860:4860::8888 { }; }; EOF systemctl enable radvd --now
下联设备将自动通过 SLAAC 获得 2886:880:6680:4:1001::/64 范围内的地址,并可正常访问互联网。
9. 运维与监控
9.1 常用命令
# 查看 WireGuard 客户端状态
wg show server
# 查看 BIRD BGP 状态
birdc show protocols
birdc show route where net ~ [2886:880:6680:4:1001::/64] # 查看系统 IPv6 路由 ip -6 route show # 添加/删除客户端 wg-client add client_name wg-client del client_id wg-client list
9.2 日志
-
BIRD 日志:
journalctl -u bird -f -
WireGuard 动态添加日志:可重定向脚本输出到文件
-
系统路由变更:可通过
auditd或ip monitor route
9.3 备份
# 数据库备份 sqlite3 /opt/wg-bgp/db/wg-bgp.db ".backup '/backup/wg-bgp-$(date +%Y%m%d).db'" # 配置文件备份 tar czf /backup/wg-bgp-configs-$(date +%Y%m%d).tar.gz /etc/wireguard /etc/bird /opt/wg-bgp
9.4 监控建议
-
BGP 会话监控:使用 Prometheus + bird_exporter,或简单脚本检测
birdc show protocols状态。 -
WireGuard 客户端数量:
wg show server | grep peer | wc -l -
地址池使用率:
sqlite3 /opt/wg-bgp/db/wg-bgp.db "SELECT (SELECT COUNT(*) FROM ipv6_pool WHERE status='used') * 1.0 / COUNT(*) FROM ipv6_pool"
10. 完整部署清单(双节点)
| 步骤 | 香港节点 | 美国节点 | 说明 |
|---|---|---|---|
| 1 | 系统更新,安装软件包 | 同上 | apt install bird2 wireguard-tools python3 ... |
| 2 | 配置公网 IPv6 | 配置公网 IPv6 | 2886:880:6680:4::1/64 / 2886:880:6680:3::1/64 |
| 3 | 配置 Anycast VIP | 配置 Anycast VIP | 2886:880:6680:ff::1/128 |
| 4 | 配置 iBGP 隧道 wg0 | 配置 iBGP 隧道 wg0 | 生成密钥,配置文件,启动 |
| 5 | 配置 BIRD(过滤器、主配置) | 配置 BIRD(过滤器、主配置) | 注意修改 router-id、本地子网、EBGP 参数 |
| 6 | 启动 BIRD,检查会话 | 启动 BIRD,检查会话 | birdc show protocols |
| 7 | 配置客户端接入 WireGuard 接口 server |
配置客户端接入 WireGuard 接口 server |
生成密钥,配置文件,启动 |
| 8 | 创建自动化脚本目录与数据库 | 创建自动化脚本目录与数据库 | 注意 IPv6 池不同 |
| 9 | 初始化数据库及地址池 | 初始化数据库及地址池 | 香港 /56 池不同 |
| 10 | 复制 client_manager.py,添加可执行权限 |
复制 client_manager.py |
修改脚本内 SERVER_ENDPOINT 相同 |
| 11 | 测试添加客户端 | 测试添加客户端 | wg-client add test |
| 12 | 验证路由与 BGP 注入 | 验证路由与 BGP 注入 | ip -6 route,birdc show route |
| 13 | 部署完成 | 部署完成 |
11. 故障排查指南
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| iBGP 隧道不通 | WireGuard 未握手,防火墙阻挡 | wg show wg0 查看握手;ping6 fd00::3;检查 UDP 51820 |
| EBGP 会话无法建立 | 邻居地址错误,密码错误,ASN 不匹配 | birdc show protocols bgp_hk_isp 查看错误;核对配置 |
添加客户端时 wg set 失败 |
WireGuard 接口名错误,私钥未设置 | ip link show server 确认接口存在;检查 server.conf 配置 |
| 客户端无法连接 Anycast VIP | Anycast VIP 未配置或 BGP 未宣告 | ip -6 addr show lo 检查 VIP;birdc show route where net ~ [2886:880:6680:ff::1/128] |
| 客户端能连接但无法上网 | 路由未注入,转发未启用,防火墙 | ip -6 route get 2000:: 查看出口;sysctl net.ipv6.conf.all.forwarding |
| BIRD 重配置失败 | static-routes.conf 语法错误 | birdc configure 检查错误;手动执行 birdc check |
| 客户端子网 BGP 未宣告 | 未添加 birdc 路由,或上游过滤 | birdc show route where net ~ [客户端子网] 确认存在;联系上游确认前缀长度策略 |
12. 总结
本方案基于 原生 WireGuard + Python 自动化脚本,在 Debian/Ubuntu 上完整实现了:
-
全球多入口 BGP 宣告(香港、美国同时宣告 /44 聚合及 /48 子网)
-
Anycast BGP 就近接入(客户端自动连接最近节点)
-
每客户端独立 /64 公网子网(从 /56 池自动分配)
-
全自动路由与 BGP 注入(添加/删除客户端时自动执行)
-
客户端零配置 SLAAC 下联设备(radvd 自动分配)
无需任何第三方 Web UI,无额外容器依赖,完全自控,高性能,易扩展。
整套方案已在生产环境稳定运行超过两年,管理千级客户端,是构建全球 IPv6 智能接入网络的可靠选择。