Skip to main content

One post tagged with "BIRD2"

View All Tags

· 7 min read

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

生产环境中应继续加内部过滤器,避免错误传播默认路由或测试前缀。

参考资料#