为什么需要内部路由(用典 简称照搬)
任何两台服务器都可以互相沟通,即可以 Ping 通。
- 这样做的原因是你的 AS 外部的路由只负责把数据包发送进你的 AS,数据包可能从任何一个节点进入。你自己的节点需要负责在内部将数据包转发给目标节点。
- 你可以使用这些方案:
- 使用 Tinc,ZeroTier One 之类的软件建立 Full-Mesh VPN,使得每两台服务器之间都能直接连通。
- 使用 OpenVPN,WireGuard 等软件建立 n(n−1)22n(n−1) 条点对点隧道连接,使得每两台服务器之间都能直接连通。
- (相对危险) 使用 OpenVPN,WireGuard 等建立少于 n(n−1)22n(n−1) 条点对点隧道连接,但需要保证每两台服务器之间能连通(可以间接连通),然后使用 Babel、OSPF、RIP 等协议在内部寻路。
- 这种方案很容易配置出错,并造成严重后果。
- 一些实例详见《如何引爆 DN42 网络》。
- Babel、OSPF、RIP 等路由协议可以自动识别整个网络的拓扑结构,并设置好相应的路由。
- 但注意,Babel、OSPF、RIP 等只应该处理你内部的路由,不能用于转发由 BGP 从外部收到的路由!
- 当 BGP 路由信息被 Babel、OSPF、RIP 等转发时,包括来源、路径长度、Community 等信息都会丢失。
- 因此其它节点从 Babel、OSPF、RIP 收到路由时,会认为它们来自你的网络,并将你的 AS 作为源头,向外再次广播路由信息。
- 简单的说:你会劫持整个 DN42 的路由。
- Babel、OSPF、RIP 等应被严格限制,它们只应处理你自己拥有的 IP 段内,各个 IP 之间的连接关系。来自外部的路由必须且只能由 BGP 处理。
风险与收益成正比,为了节省工作量,为了方便扩展,我决定冒险一下
叠buff
注意:
本人是BGP小白,本文章写的十分不严谨,缝合自多位大佬的著作,可能有任何的 错误 / 笔误 / 小白式理解 。请诸位大佬们手下留情。
本文蓝色字体可以点击跳转到对应的网页
如果您能接受的话,可以继续看下去,如果不能接受,建议现在就关闭此文章
网络结构
我的DN42网络拓补图如下

(节点之间的连线代表了这俩个节点间的wg隧道。)
那么问题就来了,各节点没有俩俩配置wg隧道,是咋互访的?
1.首先是配置好了OSPF,使得在一个节点上访问内网中的任意节点。也能让IBGP找到下一跳的地址。
2.其次是配置好了IBGP,使得各个节点能互相学习BPG路由。
3.就是灾备嘛,有点薄弱,至少它省事,不用各节点俩俩配置wg隧道,不是吗?(雾)
更新 Bird 至 v2.16 及以上
使用 IPv6 Link-Local 地址传递 IPv4 的 OSPF 数据,需要 bird 版本为 v2.16 及以上才支持这一特性,如果不希望更新可以跳过。
使用以下命令安装最新版本的Bird2:
sudo apt update && sudo apt -y install apt-transport-https ca-certificates wget lsb-release
sudo wget -O /usr/share/keyrings/cznic-labs-pkg.gpg https://pkg.labs.nic.cz/gpg
echo "deb [signed-by=/usr/share/keyrings/cznic-labs-pkg.gpg] https://pkg.labs.nic.cz/bird2 $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/cznic-labs-bird2.list
sudo apt update && sudo apt install bird2
wireguard 配置
[Interface]
# WireGuard 私钥
PrivateKey = <key>
# 你的端口号
ListenPort = <port>
Table = off
# IPv6 Link-Local 地址
PostUp = ip addr add <IPv6 Link-Local Addr> dev %i
PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0
[Peer]
# 对端 WireGuard 公钥
PublicKey = <key>
# 对端的公网地址和端口
Endpoint = <Addr>:<port>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64, ff02::5
ff02::5
是OSPFv3路由器专用的链路本地范围组播地址,需要添加进AllowedIPs。- 如果你正在使用v2.16以前的Bird,请再为隧道配置一个IPv4地址,不一定非要是DN42 IPv4,其他私有地址也可以。
含IPv4地址的wireguard配置参考
[Interface]
# WireGuard 私钥
PrivateKey = <key>
# 你的端口号
ListenPort = <port>
Table = off
# IPv6 Link-Local 地址
PostUp = ip addr add <IPv6 Link-Local Addr> dev %i
# IPv4 地址(可为任意私有段的ipv4,也可为您的DN42 ipv4)
PostUp = ip addr add 100.64.0.225/32 peer 100.64.0.226/32 dev %i
PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0
[Peer]
# 对端 WireGuard 公钥
PublicKey = <key>
# 对端的公网地址和端口
Endpoint = <Addr>:<port>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64, ff02::5
如果是自定义私有IPv4,别忘了把这个段加进 AllowedIPs
启动wg隧道后,IPv6 Link-Local 地址 能ping通,说明你已经完成了Wireguard的配置。接下来就配置OSPF吧!
OSPF 配置
注意:我的小鸟(bird2)的配置大部分是照搬bingxin大佬的 文章 ,除了 babeld.conf 和 ibgp.conf 部分,我只做了一些修改(弃用rpki改用ROA),小鸟(bird2)的配置不一样的话可能会出现致命错误。
此处默认你配置好了 bird
ospf的配置依旧 照抄 参考米露大佬写的 文章 。
以下是ospf的配置 (路径:/etc/bird/ospf.conf
)
protocol ospf v3 init_ospf {
ipv4 {
# 只使用 OSPF 对内部网络进行路由 - 忽略从 BGP 发送的所有内容。
import where is_self_net() && source != RTS_BGP;
export where is_self_net() && source != RTS_BGP;
};
include "/etc/bird/ospf/*";
};
protocol ospf v3 init_ospf6 {
ipv6 {
import where is_self_net_v6() && source != RTS_BGP;
export where is_self_net_v6() && source != RTS_BGP;
};
include "/etc/bird/ospf/*";
};
然后创建 /etc/bird/ospf
路径,在里边新建 abc.conf
文件( “abc”可为自定义字符,尽量为纯字母数字组成的名字,不要使用特殊字符)。
在文件中写道
area 0.0.0.0 {
#示例
interface "dn42-fr01" {
type ptp;
cost 100;
};
interface "dn42-jp01" {
type ptp;
cost 141;
};
#模板
#wireguard启动后会根据配置文件的文件名字命名网口。
interface "<你的wireguard配置文件的文件名字>" {
# 下面这玩意别丢了
type ptp;
# 可以根据你的真实延迟来
cost 141;
};
#下面的不是模板
# 将dummy接口标记为 stub 后,Bird 就不会向其发送 OSPF 流量,但仍会将与之相关的前缀路由到其他对等体
interface "dn42-dummy" { stub; };
};
0.0.0.0
区域代表骨干网cost
值本应该是用于开销计算,但在DN42这种对带宽要求不大而对延迟较为敏感的场景下可以直接填写延迟,OSPF会自动走开销值之和最短的路由。
dummy接口快速设置,如有请忽略
创建环回虚拟接口,适用于 IPv4 和 IPv6
使用以下命令创建虚拟接口:
ip link add dn42-dummy type dummy
ip link set dev dn42-dummy up
然后,赋予你给节点分配的 DN42 的 IPv4 和 IPv6 地址给它:
ip addr add dev dn42-dummy <ip addr>
在每个节点上都配置好OSPF后,在 bird.conf
塞 include "/etc/bird/ospf.conf";
(如果你也是照搬bingxin大佬的bird配置,麻烦把 include "/etc/bird/babeld.conf";
给扬了)
然后执行 birdc c
,再执行 birdc s p
不出意外的话,能看见OSPF为Running状态了。如果不是,请检查配置步骤是否出错。
root@XeiuJP01-IIJ-acck:~# birdc s p
BIRD 2.17.1 ready.
Name Proto Table State Since Info
device1 Device --- up 2025-07-25
static1 Static dn42_roa up 2025-07-25
static2 Static dn42_roa_v6 up 2025-07-25
kernel1 Kernel master6 up 2025-07-25
kernel2 Kernel master4 up 2025-07-25
static3 Static master4 up 2025-07-25
static4 Static master6 up 2025-07-25
init_ospf OSPF master4 up 2025-07-25 Running
init_ospf6 OSPF master6 up 2025-07-25 Running
root@XeiuJP01-IIJ-acck:~#
现在,俩台非直连的的机器能ping通了,如果不能,请检查配置步骤是否出错,或者睡一觉。
root@XeiuHK02-acck:~# traceroute 172.20.159.2
traceroute to 172.20.159.2 (172.20.159.2), 30 hops max, 60 byte packets
1 hk01.xeiu.dn42 (172.20.159.4) 0.665 ms 0.817 ms 0.768 ms
2 jp01.xeiu.dn42 (172.20.159.1) 72.730 ms 72.658 ms 72.608 ms
3 us01.xeiu.dn42 (172.20.159.2) 215.162 ms 215.126 ms 215.089 ms
root@XeiuHK02-acck:~#
IBGP配置
在从多个地点建立对等连接之前,您的各个节点必须首先完整掌握自身网络的拓扑结构。除了所有外部 BGP 连接外,这还需要配置另一个关键组件:内部 BGP(即 iBGP)。
在 /etc/bird/
中创建 ibgp.conf
文件
ibgp配置
template bgp ibgpeers {
local as OWNAS;
ipv4 {
import where source = RTS_BGP && is_valid_network() && !is_self_net();
export where source = RTS_BGP && is_valid_network() && !is_self_net();
next hop self;
};
ipv6 {
import where source = RTS_BGP && is_valid_network_v6() && !is_self_net_v6();
export where source = RTS_BGP && is_valid_network_v6() && !is_self_net_v6();
next hop self;
};
}
#示例(此配置在我HK02节点的IBGP配置里)
protocol bgp ibgp_jp01 from ibgpeers {
neighbor 172.20.159.1 as OWNAS;
}
#模板(根据自己的需求修改,用[]框起来的表示该字符可以修改,记得连带着[]一起改)
protocol bgp [ibgp_jp01] from ibgpeers {
neighbor [DN42 IP (v4 or v6) ] as OWNAS;
}
在每个节点上都配置好IBGP后,在 bird.conf
塞 include "/etc/bird/ibgp.conf";
然后执行 birdc c
后再执行 birdc s p 就能看见ibgp的状态为Established了。
root@XeiuJP01-IIJ-acck:~# birdc s p
BIRD 2.17.1 ready.
Name Proto Table State Since Info
device1 Device --- up 2025-07-25
static1 Static dn42_roa up 2025-07-25
static2 Static dn42_roa_v6 up 2025-07-25
kernel1 Kernel master6 up 2025-07-25
kernel2 Kernel master4 up 2025-07-25
static3 Static master4 up 2025-07-25
static4 Static master6 up 2025-07-25
ibgp_us01 BGP --- up 2025-07-29 Established
ibgp_fa01 BGP --- up 2025-07-29 Established
ibgp_hk01 BGP --- up 21:20:46.047 Established
ibgp_hk02 BGP --- up 2025-07-29 Established
init_ospf OSPF master4 up 2025-07-25 Running
init_ospf6 OSPF master6 up 2025-07-25 Running
root@XeiuJP01-IIJ-acck:~#
可执行 birdc s p a <ibgp的名字,例如我网络中的ibgp_jp01>
检查是否有路由导入/导出
太长了,塞这里来
root@XeiuHK02-acck:~# birdc s p a ibgp_jp01
BIRD 2.17.1 ready.
Name Proto Table State Since Info
ibgp_jp01 BGP --- up 2025-07-29 Established
BGP state: Established
Neighbor address: 172.20.159.1
Neighbor AS: 4242421336
Local AS: 4242421336
Neighbor ID: 172.20.159.1
Local capabilities
Multiprotocol
AF announced: ipv4 ipv6
Route refresh
Graceful restart
4-octet AS numbers
Enhanced refresh
Long-lived graceful restart
Neighbor capabilities
Multiprotocol
AF announced: ipv4 ipv6
Route refresh
Graceful restart
4-octet AS numbers
Enhanced refresh
Long-lived graceful restart
Session: internal multihop AS4
Source address: 172.20.159.5
Hold timer: 182.788/240
Keepalive timer: 0.852/80
Send hold timer: 401.536/480
Channel ipv4
State: UP
Table: master4
Preference: 100
Input filter: (unnamed)
Output filter: (unnamed)
Routes: 650 imported, 787 exported, 65 preferred
Route change stats: received rejected filtered ignored accepted
Import updates: 269156 0 0 2323 266833
Import withdraws: 12364 0 --- 213 12151
Export updates: 263633 72439 201 --- 190993
Export withdraws: 23 --- --- --- 52794
BGP Next hop: 172.20.159.5
IGP IPv4 table: master4
Channel ipv6
State: UP
Table: master6
Preference: 100
Input filter: (unnamed)
Output filter: (unnamed)
Routes: 699 imported, 785 exported, 106 preferred
Route change stats: received rejected filtered ignored accepted
Import updates: 155711 0 0 2430 153281
Import withdraws: 16825 0 --- 371 16454
Export updates: 184363 44958 195 --- 139210
Export withdraws: 665 --- --- --- 14177
BGP Next hop: fd43:83b9:82e2::5
IGP IPv6 table: master6
root@XeiuHK02-acck:~#
在 Routes:
这一行, imported
和 exported
前的数字不为零就说明非常正常。
Channel ipv4
和 Channel ipv6
都要检查
增加节点
增加节点就非常简单了。
修改与新节点建立wg隧道的老节点的 ospf.conf
,然后修改所有节点的 ibgp.conf
即可。
参考资料(缝合材料)
- 萌新入坑 DN42 之 —— 基于 tailscale + vxlan + OSPF 的组网 – 米露小窝
- [译] dn42 多服务器环境中的 iBGP 与 IGP 配置 | liuzhen932 的小窝
- 使用 WireGuard + Babald(Bird2) 快速组网 – Bingxin Blog
- Bird2 – DN42 Wiki
- DN42探究日记 – Ep.2 通过OSPF搭建内部网络 – 悠笙の开发日记
- 第一章·第二节 如何在 Linux 上安装最新版本的 BIRD? | BIRD 中文文档
特别鸣谢:感谢Nuro Trance大佬指导!
(顺带提一嘴,如果你想与我peer,请点击 这里 阅读我的DN42信息。)