BIRD2 是 DN42 中最常用的 BGP 路由守护进程之一。WireGuard 让节点之间“连得上”,BIRD2 让节点之间“知道怎么走”。
安装#
sudo apt updatesudo apt install -y bird2sudo systemctl enable --now bird检查:
sudo birdc show status主配置#
创建 /etc/bird/bird.conf:
define OWNAS = 4242423777;define OWNIP = 172.22.107.1;define OWNIPv6 = fd42:3777:3777::1;define OWNNET = 172.22.107.0/27;define OWNNETv6 = fd42:3777:3777::/48;define OWNNETSET = [ 172.22.107.0/27+ ];define OWNNETSETv6 = [ fd42:3777:3777::/48+ ];
router id OWNIP;
protocol device { scan time 10;}
protocol kernel kernel4 { ipv4 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIP; accept; }; }; scan time 20;}
protocol kernel kernel6 { ipv6 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIPv6; accept; }; }; scan time 20;}
protocol static static4 { route OWNNET reject;
ipv4 { import all; export none; };}
protocol static static6 { route OWNNETv6 reject;
ipv6 { import all; export none; };}
include "/etc/bird/roa.conf";include "/etc/bird/filters.conf";include "/etc/bird/peers/*.conf";关键点:
router id是 IPv4 格式,即使你主要使用 IPv6。static reject让 BIRD 有稳定的本地前缀可宣告。kernel协议负责把 BIRD 选出的路由安装进 Linux 路由表。krt_prefsrc可以让 Linux 发起到 DN42 的连接时优先使用你的 DN42 loopback 地址作为源地址。- DN42 wiki 提醒,如果没有给本机配置 DN42 dummy 地址,内核安装路由时可能出现 netlink 错误。
ROA 更新#
创建 /etc/bird/roa.conf:
roa4 table dn42_roa;roa6 table dn42_roa_v6;
protocol static roa_dn42_v4 { roa4 { table dn42_roa; }; include "/etc/bird/roa_dn42.conf";}
protocol static roa_dn42_v6 { roa6 { table dn42_roa_v6; }; include "/etc/bird/roa_dn42_v6.conf";}Burble 生成的 ROA 文件内容类似 route 172.20.0.0/24 max 29 as 4242420000;,这些语句需要放在 protocol static 里导入对应的 ROA table。
创建更新脚本 /usr/local/sbin/update-dn42-roa.sh:
#!/usr/bin/env bashset -euo pipefail
ROA4_URL="https://dn42.burble.com/roa/dn42_roa_bird2_4.conf"ROA6_URL="https://dn42.burble.com/roa/dn42_roa_bird2_6.conf"ROA4_FILE="/etc/bird/roa_dn42.conf"ROA6_FILE="/etc/bird/roa_dn42_v6.conf"BIRDC="/usr/sbin/birdc"[ -x "$BIRDC" ] || BIRDC="/usr/bin/birdc"
tmp4="$(mktemp)"tmp6="$(mktemp)"trap 'rm -f "$tmp4" "$tmp6"' EXIT
curl -fsSL -o "$tmp4" "$ROA4_URL"curl -fsSL -o "$tmp6" "$ROA6_URL"
[ -f "$ROA4_FILE" ] && cp -a "$ROA4_FILE" "$ROA4_FILE.bak"[ -f "$ROA6_FILE" ] && cp -a "$ROA6_FILE" "$ROA6_FILE.bak"
install -m 0644 "$tmp4" "$ROA4_FILE"install -m 0644 "$tmp6" "$ROA6_FILE"
if "$BIRDC" configure; then rm -f "$ROA4_FILE.bak" "$ROA6_FILE.bak"else [ -f "$ROA4_FILE.bak" ] && mv "$ROA4_FILE.bak" "$ROA4_FILE" [ -f "$ROA6_FILE.bak" ] && mv "$ROA6_FILE.bak" "$ROA6_FILE" "$BIRDC" configure || true exit 1fi授权:
sudo chmod +x /usr/local/sbin/update-dn42-roa.sh创建 systemd service:
# /etc/systemd/system/dn42-roa.service[Unit]Description=Update DN42 ROA tables
[Service]Type=oneshotExecStart=/usr/local/sbin/update-dn42-roa.sh创建 timer:
# /etc/systemd/system/dn42-roa.timer[Unit]Description=Update DN42 ROA periodically
[Timer]OnBootSec=2minOnUnitActiveSec=15minAccuracySec=1min
[Install]WantedBy=timers.target启用:
sudo systemctl daemon-reloadsudo systemctl enable --now dn42-roa.timersudo systemctl start dn42-roa.service检查:
sudo birdc show route table dn42_roasudo birdc show route table dn42_roa_v6过滤器#
创建 /etc/bird/filters.conf:
define DN42_ASNS = [ 64511..64855, 76100..76199, 4242420000..4242423999 ];
function is_valid_network_v4() -> bool { return net ~ [ 172.20.0.0/14{21,29}, 172.20.0.0/24{28,32}, 172.21.0.0/24{28,32}, 172.22.0.0/24{28,32}, 172.23.0.0/24{28,32}, 172.31.0.0/16+, 10.100.0.0/14+, 10.127.0.0/16+, 10.0.0.0/8{15,24} ];}
function is_valid_network_v6() -> bool { return net ~ [ fd00::/8{44,64} ];}
filter dn42_import_filter_v4 { if !is_valid_network_v4() then reject; if net ~ OWNNETSET then reject; if bgp_path.first !~ DN42_ASNS then reject; if roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID then reject; accept;}
filter dn42_import_filter_v6 { if !is_valid_network_v6() then reject; if net ~ OWNNETSETv6 then reject; if bgp_path.first !~ DN42_ASNS then reject; if roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID then reject; accept;}
filter dn42_export_filter_v4 { if net ~ [ OWNNET ] then accept; reject;}
filter dn42_export_filter_v6 { if net ~ [ OWNNETv6 ] then accept; reject;}这是严格 ROA 策略:只有 ROA_VALID 才接受。如果想兼容尚未生成 ROA 的路由,可以只拒绝 invalid:
if roa_check(dn42_roa, net, bgp_path.last) = ROA_INVALID then reject;严格模式更安全,宽松模式兼容性更强。生产网络建议理解差异后再选择。
上面的 export filter 只向 peer 宣告自己的前缀,适合刚入门、暂时不想给别人提供 transit 的节点。如果你已经理解 DN42 的 transit 关系,并愿意把从其他 peer 学到的合法路由继续转发给当前 peer,可以改成下面这种策略:
filter dn42_transit_export_filter_v4 { if is_valid_network_v4() && source ~ [ RTS_STATIC, RTS_BGP ] then accept; reject;}
filter dn42_transit_export_filter_v6 { if is_valid_network_v6() && source ~ [ RTS_STATIC, RTS_BGP ] then accept; reject;}然后在对应 peer 的 export filter 中引用 transit 版本。是否提供 transit,最好提前和 peer 说明清楚。
BGP peer 模板#
创建 /etc/bird/peers/peer1.conf:
template bgp dn42_peer { local as OWNAS; path metric on; graceful restart on;
ipv4 { extended next hop on; import keep filtered; import filter dn42_import_filter_v4; export filter dn42_export_filter_v4; };
ipv6 { import keep filtered; import filter dn42_import_filter_v6; export filter dn42_export_filter_v6; };}
protocol bgp peer1 from dn42_peer { neighbor fe80::1%wg-peer1 as 4242420001; interface "wg-peer1";}DN42 中常用 IPv6 link-local 建 BGP。fe80::1%wg-peer1 中的 %wg-peer1 不能省略,因为 link-local 地址只在单条链路上有意义。
extended next hop on; 让 IPv4 路由可以使用 IPv6 next-hop,这样就不必为每条隧道额外分配 IPv4 点对点地址。
import keep filtered; 会保留被 import filter 拒绝的路由,方便用 birdc show route filtered protocol peer1 排查。路由很多的节点会增加一些内存开销,如果你不需要看 filtered route,可以去掉它。
应用配置#
sudo birdc configure checksudo birdc configuresudo birdc show protocolssudo birdc show protocols all peer1如果配置有语法错误,先修正,不要用重启服务代替 configure check。
查看路由#
sudo birdc show route countsudo birdc show route for 172.20.0.1sudo birdc show route for fd00::1sudo birdc show route protocol peer1sudo birdc show route export peer1sudo birdc show route filtered protocol peer1查看 Linux kernel 是否拿到路由:
ip route get 172.20.0.1ip -6 route get fd00::1多节点网络#
有多个自有节点时:
- 小网络可以使用 iBGP 全互联。
- 节点多了以后使用 route reflector。
- OSPF/IS-IS 只承载内部 loopback 和基础设施路由。
- 不要把所有 eBGP 学到的 DN42 路由灌进 OSPF。
一个简单 iBGP 模板:
template bgp ibgp_peer { local as OWNAS; direct;
ipv4 { next hop self; import all; export all; };
ipv6 { next hop self; import all; export all; };}生产环境中应继续加内部过滤器,避免错误传播默认路由或测试前缀。