欢迎与我建立对等连接!详情请查看:iYoRoy DN42 Network
想研究BGP,奈何租一个ASN和IP段实在是太贵了,又怕自己因为配置错误干掉半个互联网,因此决定研究一下DN42这个虚拟的网络。DN42是个大型去中心化网络,使用BGP协议建立路由,和当今互联网的结构很相像,因此适合用于BGP等网络技术学习。在DN42中,每个人都将扮演ISP(网络服务提供商)的角色,和其他用户Peer,以加入并参与建设整个DN42网络。DN42运行在172.20.0.0/14
和fd00::/8
上,这两个地址都是内网地址,因此不会影响到正常的互联网。
注册
这一部分其实参考宝硕大佬的初探 DN42 网络就差不多了,但是有些内容有点过时,因此在这里补充一下。
可以参考我的commit:Add AS4242422024 · d1f9046ecb - registry - dn42 git
「克隆 DN42 注册表 Git 仓库」章节
现在dn42官方不再采用直接在官方仓库创建分支的方式注册了,现在需要创建一个Fork,添加自己的信息后再创建Pull Request
「注册联系人」章节
contact
参数现更改为e-mail
,这个参数不是必须的,但是如果不写这个参数在后续创建pr时需要手动回复确认
配置Bird
首先安装bird,以Ubuntu22.04为例:
apt install bird2 -y
如果要一并安装后续使用的WireGuard,就再加上wireguard
、wireguard-tools
软件包:
apt install bird2 wireguard wireguard-tools -y
可参考宝硕博客的「DN42 BIRD2 使用入门」章节,以下是一些值得注意的点
define OWNAS = <AS 号>;
define OWNIP = <DN42 IPv4 地址>;
define OWNIPv6 = <DN42 IPv6 地址>;
define OWNNET = <DN42 IPv4 地址块, CIDR 格式>;
define OWNNETv6 = <DN42 IPv6 地址块, CIDR 格式>;
define OWNNETSET = [ <DN42 IPv4 地址块, CIDR 格式>+ ];
define OWNNETSETv6 = [ <DN42 IPv6 地址块, CIDR 格式>+ ];
router id OWNIP;
protocol device {
scan time 10;
}
function is_self_net() {
return net ~ OWNNETSET;
}
function is_self_net_v6() {
return net ~ OWNNETSETv6;
}
function is_valid_network() {
return net ~ [
172.20.0.0/14{21,29}, # dn42
172.20.0.0/24{28,32}, # dn42 Anycast
172.21.0.0/24{28,32}, # dn42 Anycast
172.22.0.0/24{28,32}, # dn42 Anycast
172.23.0.0/24{28,32}, # dn42 Anycast
172.31.0.0/16+, # ChaosVPN
10.100.0.0/14+, # ChaosVPN
10.127.0.0/16{16,32}, # neonetwork
10.0.0.0/8{15,24} # Freifunk.net
];
}
roa4 table dn42_roa;
roa6 table dn42_roa_v6;
protocol static {
roa4 { table dn42_roa; };
include "/etc/bird/roa_dn42.conf";
};
protocol static {
roa6 { table dn42_roa_v6; };
include "/etc/bird/roa_dn42_v6.conf";
};
function is_valid_network_v6() {
return net ~ [
fd00::/8{44,64} # ULA address space as per RFC 4193
];
}
protocol kernel {
scan time 20;
ipv6 {
import none;
export filter {
if source = RTS_STATIC then reject;
krt_prefsrc = OWNIPv6;
accept;
};
};
};
protocol kernel {
scan time 20;
ipv4 {
import none;
export filter {
if source = RTS_STATIC then reject;
krt_prefsrc = OWNIP;
accept;
};
};
}
protocol static {
route OWNNET reject;
ipv4 {
import all;
export none;
};
}
protocol static {
route OWNNETv6 reject;
ipv6 {
import all;
export none;
};
}
template bgp dnpeers {
local as OWNAS;
path metric 1;
ipv4 {
import filter {
if is_valid_network() && !is_self_net() then {
if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then {
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
}
accept;
}
reject;
};
export filter {
if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept;
reject;
};
import limit 1000 action block;
};
ipv6 {
import filter {
if is_valid_network_v6() && !is_self_net_v6() then {
if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then {
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
}
accept;
}
reject;
};
export filter {
if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept;
reject;
};
import limit 1000 action block;
};
}
include "/etc/bird/peers/*";
{/collapse-item}
此处OWNIP
和OWNIPV6
参数意为本机的DN42 IPv4和IPv6地址,不是地址块的地址,比如我申请到的地址段是172.20.234.224/28,我给A机器分配了172.20.234.225,则OWNIP
为172.20.234.225,IPv6同理。
定时更新ROA可以使用cron服务实现,运行crontab -e
,在打开的文件中加入如下内容,该配置将会在每半小时更新一次roa配置文件并且重载Bird:
*/30 * * * * wget -4 -O /tmp/dn42_roa.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf && wget -4 -O /tmp/dn42_roa_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf && mv -f /tmp/dn42_roa.conf /etc/bird/dn42_roa.conf && mv -f /tmp/dn42_roa_v6.conf /etc/bird/dn42_roa_v6.conf && birdc c
记得创建/etc/bird/peers
文件夹用作后续peer。
与其他成员Peer
对新手最友好的应该就是Potat0大佬的自助Peer服务了,详情可参考他的DN42 Network页面。按照指引找到他的自动对等连接机器人,按照要求在机器人上注册你的账号,需要提供你的DN42 ASN、上文注册时Maintainer里记录的邮箱(这也是为什么在注册的时候最好需要填邮箱,很多验证服务都会使用),并且用该邮箱接收验证码,然后按照机器人的要求建立peer即可。以下是我通过Bot建立peer的过程,全程使用Ubuntu22.04系统的香港VPS操作。
系统配置
因为每个节点都可能会作为其他节点的路由器使用,因此需要打开Linux内核数据包转发;同时因为使用了WireGuard,并不是通过物理网卡转发,因此需要关闭rp_filter
严格模式。
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.forwarding=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
sysctl -p
安装WireGuard、Bird2
apt install wireguard wireguard-tools -y
注:现在的软件包管理一般会在安装wireguard
的时候自动安装wireguard-tools
以使用wg-quick
指令。
生成密钥对
wg genkey | tee privatekey | wg pubkey > publickey
记下privatekey、publickey中的内容,代表私钥和公钥
建立Peer
一般而言有两种建立Peer的模式,即使用MP-BGP(Multiprotocol BGP,多协议BGP)和不使用MP-BGP。个人感觉MP-BGP更为常用,因为其配置较为简单。两种配置稍有不同,请根据你的需求参考。
使用MP-BGP
与Peer对方交换信息
你需要提供对方以下信息,同时你也需要知道对方的以下信息:
- 公钥
- 公网地址(非DN42地址)
- 公网WireGuard端口,一般是监听对方ASN的后5位
- DN42 ASN
- LLA(Link-Local Address)地址,一般而言是
fe80::<对方ASN后4位>
- 是否支持ENH(Extended Next Hop),注意,若使用v6交换路由而不启用ENH则无法交换v4路由
也有时会将公网地址和公网wg端口放在一起称作Endpoint。
配置DN42虚拟网卡
因为MP-BGP通常使用LLA地址建立BGP,因此我们需要在系统里设置一个dummy网卡并绑定我们给这台机器分配的DN42 IP。运行以下指令:
ip link add dn42 type dummy
ip addr add <你给这这台机器分配的DN42 IPv4> dev dn42
ip addr add <你给这这台机器分配的DN42 IPv6> dev dn42
如果需要持久化配置,可以参考以下三种方式:
tee /etc/systemd/network/10-dn42.netdev > /dev/null <<EOF
[NetDev]
Name=dn42
Kind=dummy
EOF
tee /etc/systemd/network/20-dn42.network > /dev/null <<EOF
[Match]
Name=dn42
[Network]
Address=<你给这台机器分配的DN42 IPv4>/32
Address=<你给这台机器分配的DN42 IPv6>/128
EOF
systemctl enable systemd-networkd
systemctl restart systemd-networkd
{/tabs-pane}
{tabs-pane label="netplan"}
tee /etc/netplan/99-dn42.yaml > /dev/null <<EOF
network:
version: 2
renderer: networkd
ethernets:
dn42:
match:
name: dn42
addresses:
- <你给这台机器分配的DN42 IPv4>/32
- "<你给这台机器分配的DN42 IPv6>/128"
accept-ra: no
EOF
netplan apply
{/tabs-pane}
{tabs-pane label="/etc/network/interfaces"}
tee -a /etc/network/interfaces > /dev/null <<EOF
auto dn42
iface dn42 inet static
address <你给这台机器分配的DN42 IPv4>
netmask 255.255.255.255
iface dn42 inet6 static
address <你给这台机器分配的DN42 IPv6>/128
EOF
ifup dn42
{/tabs-pane}
配置WireGuard
在/etc/wireguard
下创建一个配置文件,名称随意,但是我的命名习惯是dn42-<对方ASN后4位>.conf
,其中dn42-xxxx
即为隧道名。往文件内填入如下内容:
[Interface]
PrivateKey = <上文「生成密钥对」章节生成的私钥>
ListenPort = <公网WireGuard监听端口>
Table = off
Address = <你的LLA地址>/64
PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0
[Peer]
PublicKey = <对方给你的公钥>
Endpoint = <对方的Endpoint,即IP:端口>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe00::/8
编辑完成后保存,运行:
wg-quick up <隧道名>
即可启动wg隧道。使用wg show <隧道名>
即可查看连接状态。直接运行wg
可查看所有隧道状态
如果需要让隧道开机自启动,可以运行:
systemctl enable wg-quick@<隧道名>
配置Bird2的Peer部分
在/etc/bird/peers
下新建文件<名称>.conf
,填入如下内容:
protocol bgp <BGP会话名称> from dnpeers{
neighbor <对方LLA地址> % '<WireGuard隧道名>' as <对方ASN,不带AS前缀>;
};
如果使用使用了Extended next hop(如上图交换信息时协商的),则配置:
protocol bgp <BGP会话名称> from dnpeers{
neighbor <对方LLA地址> % '<WireGuard隧道名>' as <对方ASN,不带AS前缀>;
ipv4{
extended next hop;
};
};
应用配置
运行birdc configure
(或者birdc c
,等同)重载Bird配置,然后运行birdc show protocols
(或者birdc s p
,等同)即可查看当前建立的BGP连接。
root@hkg2-202501092021514df2f0:~# birdc show protocols
BIRD 2.0.12 ready.
Name Proto Table State Since Info
device1 Device --- up 07:24:14.255
static1 Static dn42_roa up 07:24:14.255
static2 Static dn42_roa_v6 up 07:24:14.255
kernel1 Kernel master6 up 07:24:14.255
kernel2 Kernel master4 up 07:24:14.255
static3 Static master4 up 07:24:14.255
static4 Static master6 up 07:24:14.255
dn42-0298 BGP --- up 08:03:13.347 Established
dn42-1816 BGP --- up 07:53:05.028 Established
不使用MP-BGP
与Peer对方交换信息
你需要提供对方以下信息,同时你也需要知道对方的以下信息:
- 公钥
- 公网地址(非DN42地址)
- 公网WireGuard端口,一般是监听对方ASN的后5位
- DN42 ASN
- DN42 IP,如果交换IPv4路由则需要IPv4地址,如果交换IPv6路由则需要IPv6地址
也有时会将公网地址和公网wg端口放在一起称作Endpoint。
配置WireGuard
在/etc/wireguard
下创建一个配置文件,名称随意,但是我的命名习惯是dn42-<对方ASN后4位>.conf
,其中dn42-xxxx
即为隧道名。往文件内填入如下内容:
[Interface]
PrivateKey = <上文「生成密钥对」章节生成的私钥>
ListenPort = <公网WireGuard监听端口>
Table = off
PostUp = ip addr add <LLA>/64 dev %i
PostUp = ip addr add <本地DN42 IPv6> dev %i
PostUp = ip addr add <本地DN42 IPv4> peer <对方DN42 IPv4> dev %i
PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0
[Peer]
PublicKey = <对方给你的公钥>
Endpoint = <对方的Endpoint,即IP:端口>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe00::/8
编辑完成后保存,运行:
wg-quick up <隧道名>
即可启动wg隧道。使用wg show <隧道名>
即可查看连接状态。直接运行wg
可查看所有隧道状态
如果需要让隧道开机自启动,可以运行:
systemctl enable wg-quick@<隧道名>
配置Bird2的Peer部分
在/etc/bird/peers
下新建文件<名称>.conf
,填入如下内容:
protocol bgp <v4BGP会话名称> from dnpeers{
neighbor <对方DN42 IPv4地址> as <对方ASN,不带AS前缀>;
direct;
ipv6{
import none;
export none;
};
};
protocol bgp <v6BGP会话名称> from dnpeers{
neighbor <对方DN42 IPv6地址> % '<WireGuard隧道名称>' as <对方ASN,不带AS前缀>;
direct;
ipv4{
import none;
export none;
};
};
应用配置
运行birdc configure
(或者birdc c
,等同)重载Bird配置,然后运行birdc show protocols
(或者birdc s p
,等同)即可查看当前建立的BGP连接。
自此,我们成功加入了DN42网络。要想让网络更加稳定,我们可以与更多用户进行Peer,建立多条BGP线路以防止其中部分节点瘫痪导致失联。你可以加入DN42非官方tg交流群获取更多信息。
如果出现BGP Established但是无法Ping通DN42内部IP的情况,请检查bird.conf
中设置的IP和dummy网卡分配的IP或WireGuard中的本地IP是否相同。
配置DNS
DN42内有自己的公共DNS,泛播地址为172.20.0.53
,并且也能解析正常互联网的域名。要想能够访问以dn42结尾的内部域名,需要将这个地址放到resolv.conf最上面:
nameserver 172.20.0.53
nameserver 223.5.5.5 #下面是正常的DNS服务器配置
之后就可以解析DN42内部域名啦,同时ping
、traceroute
、mtr
等命令查询内部IP时也能显示出来rDNS的解析结果。
欢迎与我建立对等连接!详情请查看:iYoRoy DN42 Network
参考文章:
- https://blog.baoshuo.ren/post/dn42-network/
- https://dn42.dev/howto/Bird2#example-configuration
- https://dn42.eu/howto/wireguard
- https://blog.udon.eu.org/archives/dbf21067.html
- https://blog.byteloid.one/2025/06/02/babeld-over-wireguard/
- https://blog.wcysite.com/2021/%E8%B8%A9%E5%9D%91DN42-p2-peer/
- https://blog.chs.pub/p/23-14-joindn42/
- https://www.cnblogs.com/FengZeng666/p/15583434.html
佬,cn节点peer吗
可以的