DN42 Guide
Post on Edit on 1 revisionsWhat is DN42?
dn42 is a big dynamic VPN, which employs Internet technologies (BGP, whois database, DNS, etc). Participants connect to each other using network tunnels (GRE, OpenVPN, WireGuard, Tinc, IPsec) and exchange routes thanks to the Border Gateway Protocol. Network addresses are assigned in the 172.20.0.0/14 range and private AS numbers are used (see registry) as well as IPv6 addresses from the ULA-Range (fd00::/8)
概括一下,DN42是一个实验性网络。在这个网络上,参与者们通过隧道/物理链路相互连接,并在此之上运行各种Internet上存在的动态路由协议(如BGP/OSPF)等,来与其他参与者交换路由信息进行互联,来搭建一个覆盖网络(Internet over Internet)。
那么这篇博客,我就来写写如何加入DN42、与其他人Peer以及组建自己的内网。
Note
注:本文全程处于Ubuntu 24.04.2环境下操作
0、事先准备
你需要先行在本地环境下通过gpg --full-generate-key
来生成一个GPG key,来为你之后在Registry的提交签名,或者在其他DN42服务里验证ASN的身份,然后gpg --list-keys
把你的KEY ID列出来,在Registry上添加
1、在DN42 Registry上注册(也可参考Wiki)
Caution
记得将EXAMPLE-MNT
和EXAMPLE-DN42
换成你自己的*-MNT
和*-DN42
!
首先打开DN42 Registry,注册一个帐户,然后对Registry进行一个Fork,接着在本地用git clone https://git.dn42.dev/[username]/registry.git
将Registry仓库给克隆到本地。
接着,在data/mntner下新建一个名称为EXAMPLE-MNT
的文件,内容如下
mntner: EXAMPLE-MNT
admin-c: EXAMPLE-DN42
tech-c: EXAMPLE-DN42
mnt-by: EXAMPLE-MNT
source: DN42
auth: pgp-fingerprint ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
(ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD换成你在gpg --list-keys
列出来的公钥)
在data/person/里建一个EXAMPLE-DN42
的文件(命名要求同上,和admin-c里保持一致),内容如下
person: [NAME]
e-mail: [EMAIL]
nic-hdl: EXAMPLE-DN42
mnt-by: [同上mnt-by]
source: DN42
(Name自己取,加一个自己的Email)
接着来添加属于自己的自治系统编号ASN
,
首先在https://explorer.burble.com/free#/asn 挑一个尚未被注册的ASN
然后在data/aut-num/下新建一个名称为AS424242****的文件(换成上步选的ASN),内容如下
aut-num: AS424242****
as-name: [AS Name]
descr: [description]
admin-c: [同上admin-c]
tech-c: [同上tech-c]
mnt-by: [同上mnt-by]
source: DN42
添加如下文件,申请属于自己的IPv4地址块(可以去https://explorer.burble.com/free#/4 找不冲突的)
(个人能申请的网络从/26到/29,默认建议申请/27)
在data/inetnum/下新建一个名称格式为地址块CIDR,把/换成_
的文件,内容如下
inetnum: [地址块第一个地址] - [地址块最后一个地址]
netname: [地址块名称]
descr: [描述]
country: [国家代码,一般CN]
admin-c: [同上admin-c]
tech-c: [同上tech-c]
mnt-by: [同上mnt-by]
status: ASSIGNED
cidr: [地址块CIDR]
source: DN42
然后在data/route/下建同名文件,内容如下
route: [地址块CIDR]
descr: [描述]
origin: [同上aut-num]
mnt-by: [同上mnt-by]
source: DN42
如果要申请IPv6的话,去https://explorer.burble.com/free#/6 找可用的ULA,或者在fd00::/8里找一块/48跟他人不同的ULA,然后在data/inet6num/和data/route6/里建立文件,名称和内容与前面类似
添加完这些文件后,通过git add .
和git commit -S
来提交和签名你的更改,git push -f
把修改推到Fork仓库,然后就可以给Registry发Pull Request等待审核了。
(如果检查格式机器人有报错的话,在本地作好修改,commit,然后./squash-my-commits -S
接着git push -f
就可以把修改推到Fork仓库,无需重开PR)
待PR合入主仓库后,你就可以在DN42和他人进行Peer了
2、配置 BIRD
并与他人进行Peer
为了与他人的路由器交换路由信息,我们也需要在自己的路由器上安装相应的路由软件,本文将使用BIRD(鸟)(BIRD Internet Routing Daemon)来作为路由软件
首先在你系统的sysctl.conf
里添加如下内容,启用IPv4和IPv6转发,并且关闭rp_filter:
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.*.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
(rp_filter一定要关掉! 在DN42里,来源网卡和回复的网卡未必是同一张,如果没有关闭,这种情况下的数据包会被内核丢掉)
参考这篇网页来安装BIRD
然后修改/etc/bird/bird.conf
配置文件内容引用自DN42 Wiki
示例配置文件
################################################
# Variable header #
################################################
define OWNAS = 424242****;
define OWNIP = 分配给本机的IPv4地址;
define OWNIPv6 = 分配给本机的IPv6地址;
define OWNNET = IPv4地址块的CIDR;
define OWNNETv6 = IPv4地址块的CIDR;
define OWNNETSET = [<OWNNET>+];
define OWNNETSETv6 = [<OWNNETv6>+];
################################################
# Header end #
################################################
router id OWNIP;
protocol device {
scan time 10;
}
/*
* Utility functions
*/
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+, # 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 {
# Reject when unknown or invalid according to ROA
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
} else reject;
};
export filter { if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
import limit 9000 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 {
# Reject when unknown or invalid according to ROA
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
} else reject;
};
export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
import limit 9000 action block;
};
}
include "/etc/bird/peers/*";
*/15 * * * * curl -sfSLR {-o,-z}/etc/bird/roa_dn42.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf && birdc configure > /dev/null
*/15 * * * * curl -sfSLR {-o,-z}/etc/bird/roa_dn42_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf && birdc configure > /dev/null
这样可以保证不会收其他人乱发给你的路由
由于DN42是去中心化的网络,所以你需要联系其他的参与者来跟你进行互联,你可以去DN42 Peer Finder以及各种渠道找到其他的参与者,来和你配置隧道链路
当你配置好与其他人的隧道链路后,可以在/etc/bird/peers/(没有的话自己mkdir -p)添加配置文件[名称].conf
来配置BGP会话
示例配置文件(MP-BGP+Extended nexh-hop)
protocol bgp DN42_0000 from dnpeers {
neighbor [IPv6 Link-local or ULA] % '[网络设备名称]' as [Other DN42 participants ASN];
ipv4 {
extended next hop on;
};
ipv6;
}
接着birdc configure
重载配置,如果不出意外的话,birdc show protocols
可以看见与其他人的BGP状态变为Established
,恭喜,你已经成功接入了DN42!
3、组建自己的内网(OSPF+IBGP Fullmesh)
(如果你只有单个节点接入DN42的话,本节应该对你没用,可以忽略)
假如你手上有很多的服务器,想都接入DN42,实现大内网互通的话,本节内容可以帮助你
首先当然是保证内网是互通的,所以你可以使用各种隧道(L2/L3)技术打通链路,具体创建方法各有不同,在此不再阐述
注意隧道接口的MTU两端应需一致
在你需要组内网的机器上的/etc/bird/peers/里新建ospf.conf
示例配置文件
protocol ospf v3 INTERNAL_OSPF_IPv4 {
ipv4 {
import filter {
if is_self_net() then accept;
reject;
};
export where (source = RTS_BGP || source = RTS_STATIC);
};
area 0 {
interface "INTERNAL_*" #接口名称,可以使用通配符
type ptp;
};
};
}
protocol ospf v3 INTERNAL_OSPF_IPv6 {
ipv6 {
import filter {
if is_self_net_v6() then accept;
reject;
};
export where (source = RTS_BGP || source = RTS_STATIC);
};
area 0 {
interface "INTERNAL_*" { #接口名称,可以使用通配符
type ptp;
};
};
}
同时修改/etc/bird/bird.conf:
示例配置文件(部分)
################################################
# Variable header #
################################################
define INTRANET=([你的ASN后五位],11111);#加上这句
...
################################################
# Header end #
################################################
protocol static {
route OWNNET reject;
route [IP] reject {bgp_community.add(INTRANET);}; #[IP]换成你在这个节点分配的IPv4地址块的CIDR表述(比如172.20.0.53/32)
ipv4 {
import all;
export none;
};
}
protocol static {
route OWNNETv6 reject;
route [IP] reject {bgp_community.add(INTRANET);}; #[IP]换成你在这个节点分配的IPv6地址块的CIDR表述(比如fd42:d42:d42:80::/64)
ipv6 {
import all;
export none;
};
}
template bgp dnpeers{
...
ipv4{
...
export filter { if (is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] && !(INTRANET ~ bgp_community)) then accept; else reject; }; #把小段地址在向BGP邻居宣告时过滤掉,带INTRANET community的地址只应该在OSPF里宣告,下面同理
};
ipv6{
...
export filter { if (is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] && !(INTRANET ~ bgp_community)) then accept; else reject; }; #同理
};
};
template bgp dninternals {
local as OWNAS;
path metric 1;
enable extended messages on;
ipv4 {
next hop self;
extended next hop on;
import all;
export filter { if (is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] && !(INTRANET ~ bgp_community)) then accept; else reject; }; #同理
};
ipv6 {
next hop self;
import all;
export filter { if (is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] && !(INTRANET ~ bgp_community)) then accept; else reject; }; #同理
};
graceful restart;
};
当然,OSPF只保证内网可达,不负责在各个边界路由器上交换路由,所以还需要IBGP来在边界路由器上交换路由
像跟其他人peer一样,在/etc/bird/peers/加个IBGP的conf:
示例配置文件
protocol bgp [名称] from dninternals {
neighbor [节点IPv6 ULA,不是fe80::/64的Link-Local,更不是IPv4] internal;
};
然后记得birdc c
重载配置,birdc s p
可以看见与IBGP邻居的BGP状态变为Established
,那么也就完成了内网的搭建
4、取得域名,搭建起属于自己的权威DNS
你可以参考potat0的blog在 DN42 中注册域名并开启 DNSSEC (2023.1.25 更新)