全球多入口 IPv6 BGP 宣告与 Anycast VPN 自动就近接入方案

全球多入口 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/64fd00::3/64


3. 基础系统配置(香港 & 美国节点)

3.1 系统更新与必要软件安装

bash
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 转发并优化内核参数

bash
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 地址(根据实际情况)

香港节点:

bash
ip -6 addr add 2886:880:668:4::1/64 dev eth0

持久化(以 Netplan 为例):

yaml
# /etc/netplan/01-netcfg.yaml
network:
  version: 2
  ethernets:
    eth0:
      addresses:
        - 2886:880:668:4::1/64
bash
netplan apply

美国节点:

bash
ip -6 addr add 2886:880:668:3::1/64 dev eth0

持久化类似。

3.4 配置 Anycast VIP(两节点相同)

bash
ip -6 addr add 2886:880:668:ff::1/128 dev lo

持久化(Netplan 或 systemd-networkd):

yaml
# /etc/netplan/99-anycast.yaml
network:
  version: 2
  ethernets:
    lo:
      addresses:
        - "2886:880:668:ff::1/128"
bash
netplan apply

4. 节点间 iBGP 隧道(WireGuard)

4.1 生成密钥对(两节点)

bash
mkdir -p /etc/wireguard
cd /etc/wireguard
umask 077
wg genkey | tee wg0-privatekey | wg pubkey > wg0-publickey

4.2 香港节点配置 /etc/wireguard/wg0.conf

ini
[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

ini
[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 启动并启用自启

bash
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

bird
# 非法前缀列表(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

bird
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; route 2886:880:6680::/44 blackhole; } protocol static static_local { ipv6; route 2886:880:6680:4::/48 blackhole; } protocol static static_anycast { ipv6; route 2886:880:6680:ff::1/128 blackhole; } # 动态客户端路由将通过 birdc 注入,此处仅初始化空文件 include "/etc/bird/static-routes.conf"; # EBGP 香港上游(请替换为真实对端信息) protocol bgp bgp_hk_isp { local 2886:880:6680:4::1 as ASN; neighbor 2886:880:6680 as 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

bird
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 { local 2886: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 初始化静态路由文件

bash
touch /etc/bird/static-routes.conf
chmod 644 /etc/bird/static-routes.conf

5.5 启动 BIRD

bash
systemctl enable bird
systemctl restart bird
birdc show protocols

确保 EBGP、iBGP 均为 Established


6. 原生 WireGuard 服务端(客户端接入)

6.1 生成服务器密钥对

bash
cd /etc/wireguard
umask 077
wg genkey | tee server-privatekey | wg pubkey > server-publickey

6.2 创建服务端接口配置文件 /etc/wireguard/server.conf

ini
[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 启动服务端接口

bash
systemctl enable wg-quick@server
systemctl start wg-quick@server
wg show server

7. 自动化脚本部署(核心)

7.1 创建项目目录

bash
mkdir -p /opt/wg-bgp/{db,scripts,config,logs}
cd /opt/wg-bgp

7.2 初始化 SQLite 数据库

数据库结构文件 /opt/wg-bgp/db/schema.sql

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)
);

初始化地址池(香港节点示例)

bash
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

python
#!/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 脚本权限设置

bash
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 测试脚本

bash
# 添加客户端(输出配置文件)
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

bash
# 启用 IPv6 转发
sysctl -w net.ipv6.conf.all.forwarding=1

# 配置内网接口 IPv6 地址
ip -6 addr add 2886: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; prefix 2886: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 常用命令

bash
# 查看 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 备份

bash
# 数据库备份
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 routebirdc 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 智能接入网络的可靠选择。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇