注册 DN42

dn42 gitea 注册账号。

在网页上绑定 SSH/GPG 公钥。

Clone Repo

Fork 注册仓库 ,然后拉到本地。

记得使用Linux拉取,Windows会报错的,因为冒号的存在。似乎有方法绕过,但是因为我有wsl,很方便,所以就用wsl了

然后签一个分支出来,免得操作不当搞炸了。当然你艺高人胆大不弄也行。

1
git checkout -b <username>/register

注册相关信息

可以参照 官方概要

可以先选个心仪的 ASN, IPv4/IPv6 Prefix 。

维护者

data/mntner 文件夹下新建一个名为 <FOO>-MNT 的文件。

写入以下内容

1
2
3
4
5
6
mntner:             <FOO>-MNT
admin-c: <FOO>-DN42
tech-c: <FOO>-DN42
mnt-by: <FOO>-MNT
auth: pgp-fingerprint 0123456789ABCDEF0123456789ABCDEF01234567
source: DN42

这是官方参照的翻译版本:

1
2
3
4
5
6
7
8
9
10
mntner         (必要)  (单项)    primary schema                 维护者名称,应与文件名相同
descr (可选) (单项) 维护者描述
mnt-by (必要) (多项) lookup=dn42.mntner 实际维护人,个人就是维护者
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员联系信息,在 联系人 中注册的人,个人一般就是自己,维护者
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员联系信息,在 联系人 中注册的人,个人一般就是自己,维护者
auth (可选) (多项) > [method] [value]... 身份验证信息,可以使用 GPG/SSH 公钥
org (可选) (多项) lookup=dn42.organisation 组织
abuse-mailbox (可选) (单项) 滥用反馈邮箱
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42

联系人

data/person 目录下新建一个名为 <FOO>-DN42 的文件。

1
2
3
4
5
person:             <FOO>
e-mail: <YourEmail>
nic-hdl: <FOO>-DN42
mnt-by: <FOO>-MNT
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
person          (必要)   (单项)    schema                       姓名,可以为昵称
nic-hdl (必要) (单项) primary NIC 管理者,与文件名相同
mnt-by (必要) (多项) lookup=dn42.mntner 维护人
org (可选) (多项) lookup=dn42.organisation 组织
nick (可选) (多项) 昵称
pgp-fingerprint (可选) (多项) pgp 指纹
www (可选) (多项) 网站
e-mail (可选) (多项) 邮件
contact (可选) (多项) 联系方式
abuse-mailbox (可选) (多项) 滥用反馈邮箱
phone (可选) (多项) 手机号
fax-no (可选) (多项) 传真号
address (可选) (多项) 地址
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42

注册 ASN

DN42 占用的私人地址块为:4242420000 - 4242429999 。目前 DN42 开放注册的 ASN 范围是 4242420000 - 4242423999 ,我注册时还剩一千多个,靓号都没了,看到个顺眼的就选了吧。

你可以在 这里 检查剩余可用 ASN。

data/aut-num 目录下新建一个文件,文件名为你选定的 ASN。

1
2
3
4
5
6
aut-num:            <你想要的 ASN,需要带“AS”>
as-name: <AS 名称>
admin-c: <FOO>-DN42
tech-c: <FOO>-DN42
mnt-by: <FOO>-MNT
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
12
13
aut-num    (必要)  (单项)   primary schema                      AS 号码,如 AS4242423999
as-name (必要) (单项) AS 名称,一个单词,多个单词可用 '-' / '_' 连接
descr (可选) (单项) 描述
mnt-by (必要) (多项) lookup=dn42.mntner 维护人
member-of (可选) (多项) lookup=dn42.as-set,dn42.route-set 谁的成员
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员,个人即之前注册的 nic-hdl
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员,个人即之前注册的 nic-hdl
org (可选) (单项) lookup=dn42.organisation 组织
mp-import (可选) (多项) 多路由器之间的路由信息导入
mp-export (可选) (多项) 多路由器之间的路由信息导出
mp-default (可选) (多项) 默认路由
geo-loc (可选) (多项) > [lat-c] [long-c] [name] 地理位置
remarks (可选) (多项) 注释、说明

IPv6 Address

你可以在 这里 检查剩余可用 IPv6 地址段。不过 DN42 拥有整个 fd00::/8 ,非常庞大,基本是想要什么就有什么。

data/inet6num 目录下新建一个文件,文件名为你想要的 IPv6 地址块的 CIDR 格式,记得用 _ 代替 /

1
2
3
4
5
6
7
8
9
10
inet6num:           <起始 IP 地址> - <结束 IP 地址>
cidr: <你想要的 IP 地址块的 CIDR 格式>
netname: <FOO>-NETWORK
descr: <描述>
country: XD
admin-c: <FOO>-DN42
tech-c: <FOO>-DN42
mnt-by: <FOO>-MNT
status: ASSIGNED
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
inet6num    (必要)   (单项)    schema                           IP 起始地址 - IP 结束地址
cidr (必要) (单项) primary IP 地址的 CIDR 表示
netname (必要) (单项) 网络名,此处可加 '-IPv6' 加以区分为 v6 网络
nserver (可选) (多项) > [domain-name] NS
country (可选) (多项) 国家
descr (可选) (单项) 描述
status (可选) (单项) > {ALLOCATED|ASSIGNED} {PI|PA|} 状态
policy (可选) (单项) > {open|closed|ask|reserved} 政策
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员
zone-c (可选) (多项) lookup=dn42.person,dn42.role 联系人/组织
ds-rdata (可选) (多项) DNSSEC
mnt-by (可选) (多项) lookup=dn42.mntner 维护人
mnt-lower (可选) (多项) lookup=dn42.mntner 维护子集
mnt-routes (可选) (多项) lookup=dn42.mntner 维护路由
org (可选) (单项) lookup=dn42.organisation 组织
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42

IPv4 Address

你可以在 这里 检查剩余可用 IPv4 地址段。 DN42 不推荐使用过小/过大的地址段。过小的不好分配,过大的地址不足。/26 - /28 都是比较好获取的。

data/inetnum 目录下新建一个文件,文件名为你想要的 IPv4 地址块的 CIDR 格式,用 _ 代替 /

1
2
3
4
5
6
7
8
9
10
inetnum:            <起始 IP 地址> - <结束 IP 地址>
cidr: <你想要的 IP 地址块的 CIDR 格式>
netname: <FOO>-NETWORK
descr: <描述>
country: XD
admin-c: <FOO>-DN42
tech-c: <FOO>-DN42
mnt-by: <FOO>-MNT
status: ASSIGNED
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
inetnum     (必要)   (单项)    schema                           IP 起始地址 - IP 结束地址
cidr (必要) (单项) primary IP 地址的 CIDR 表示
netname (必要) (单项) 网络名,此处可加 '-IPv6' 加以区分为 v6 网络
nserver (可选) (多项) > [domain-name] NS
country (可选) (多项) 国家
descr (可选) (单项) 描述
status (可选) (单项) > {ALLOCATED|ASSIGNED} {PI|PA|} 状态
policy (可选) (单项) > {open|closed|ask|reserved} 政策
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员
zone-c (可选) (多项) lookup=dn42.person,dn42.role 联系人/组织
ds-rdata (可选) (多项) DNSSEC
mnt-by (可选) (多项) lookup=dn42.mntner 维护人
mnt-lower (可选) (多项) lookup=dn42.mntner 维护子集
mnt-routes (可选) (多项) lookup=dn42.mntner 维护路由
org (可选) (单项) lookup=dn42.organisation 组织
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42

Route Record

data/route 目录下新建一个文件,命名为你想要的 IP 地址块的 CIDR 格式,用 _ 代替 /

IPv6

1
2
3
4
5
route6:             <你想要的 IPv6 地址块>
origin: <你想要的 ASN>
max-length: 48
mnt-by: <FOO>-MNT
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
route6      (必要)  (单项)    primary schema                    IP 地址的 CIDR 表示
mnt-by (必要) (多项) lookup=dn42.mntner 维护人
origin (必要) (多项) lookup=dn42.aut-num ASN,带 “AS”
member-of (可选) (多项) lookup=dn42.route-set 谁的成员
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员
descr (可选) (多项) 描述
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42
pingable (可选) (多项) 是否相应 ICMP
max-length (可选) (单项) 最大 IP 长度,如 48

IPv4

1
2
3
4
5
route:              <你想要的 IPv4 地址块>
origin: <你想要的 ASN>
max-length: <你 IP 长度,比如 27>
mnt-by: <FOO>-MNT
source: DN42

官方参照:

1
2
3
4
5
6
7
8
9
10
11
route       (必要)  (单项)    primary schema                    IP 地址的 CIDR 表示
mnt-by (必要) (多项) lookup=dn42.mntner 维护人
origin (必要) (多项) lookup=dn42.aut-num ASN,带 “AS”
member-of (可选) (多项) lookup=dn42.route-set 谁的成员
admin-c (可选) (多项) lookup=dn42.person,dn42.role 管理员
tech-c (可选) (多项) lookup=dn42.person,dn42.role 技术员
descr (可选) (多项) 描述
remarks (可选) (多项) 注释、说明
source (必要) (单项) lookup=dn42.registry DN42
pingable (可选) (多项) 是否相应 ICMP
max-length (可选) (单项) 最大 IP 长度,如 27

检查

仓库根目录包含许多脚本来帮助检查您的请求:

  • fmt-my-stuff <FOO>-MNT :自动修复较小的格式错误
  • check-my-stuff <FOO>-MNT :根据注册表模式验证您的对象
  • check-pol origin/master <FOO>-MNT :检查策略违规情况
  • squash-my-commits :自动更新并压缩您的本地提交,在第一次提交出现问题后,修改之后使用
  • sign-my-commit :使用 pgp 密钥或标准 SSH 签名对您的提交进行签名

前三个运行、检查无误后即可提交了

推送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git add .
git commit -S 'FOOBAR'

# 签名
./sign-my-commit --pgp <FOO>-MNT
# 推送
git push --set-upstream origin <username>/register

# 被拒修复后
git add .
git commit -S 'FOOBAR'
./squash-my-commits
./sign-my-commit --pgp <FOO>-MNT
git push --force

PR

这个,去官方 Repo 拉个 PR ,然后等就行了。

Bird2 配置

Debian 11 中的 Bird2 应当是 2.0.7 版本的。我使用的是这个版本。目前 Debian 12 是 2.0.12,小版本不同,配置是一样的。

安装 Bird2

1
2
apt update # && apt upgrade -y
apt install bird2 -y

配置

参照 官方文档 内容即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
################################################
# Variable header #
################################################
define OWNAS = <你的ASN>; # AS4242423999
define OWNIP = <你的IPv4地址>; # 172.20.1.129
define OWNIPv6 = <你的IPv6地址>; # fd88:1234:1234::1
define OWNNET = <IPv4 CIDR>; # 172.20.1.128/27
define OWNNETv6 = <IPv6 CIDR>; # fd88:1234:1234::/48
define OWNNETSET = [<IPv4 CIDR>+]; # [172.20.1.128/27+]
define OWNNETSETv6 = [<IPv6 CIDR>+]; # [fd88:1234:1234::/48+]
################################################
# 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{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;
} else accept;
} else reject;
};
export filter { if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept; else 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;
} else accept;
} else reject;
};
export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
import limit 1000 action block;
};
}
include "/etc/bird/peers/*";

然后在 /etc/bird 目录下创建一个文件夹,名为 peers ,这是待会要用到的喵喵工具。

下载 ROA 文件

ROA 应该经常性的自动下载和更新,以防止 BGP 劫持。

1
2
wget -O /tmp/dn42_roa.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf && mv -f /tmp/dn42_roa.conf /etc/bird/roa_dn42.conf
wget -O /tmp/dn42_roa_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf && mv -f /tmp/dn42_roa_v6.conf /etc/bird/roa_dn42_v6.conf

加载配置

重载并查看状态

1
2
birdc c # birdc configure
birdc show protocol

656af893239fe.png

查看状态

自动化

ROA 是需要经常更新的,这是对应的 Crontab 语句

1
2
3
0 0 */1 * * ? wget -O /tmp/dn42_roa.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf && mv -f /tmp/dn42_roa.conf /etc/bird/roa_dn42.conf
0 0 */1 * * ? wget -O /tmp/dn42_roa_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf && mv -f /tmp/dn42_roa_v6.conf /etc/bird/roa_dn42_v6.conf
3 0 */1 * * ? birdc c

每小时执行一次下载,并且会更新 bird 的配置文件。

WireGuard 配置

安装 WireGuard

生成密钥

运行下面的命令,在当前目录下生成一对公钥和私钥。

1
wg genkey | tee privatekey | wg pubkey > publickey

使用时直接查看就行,比如

1
cat privatekey && cat publickey

搭建隧道

需要一位已经在 DN42 的上游来和您 Peer 。

/etc/wireguard 目录下新建一个名为 <FOO>.conf 的文件。文件名应当能让自己好区分,比如 dn42-3999.conf

Interface 部分是自己的配置。

为保持方便,ListenPort 一般为 2 / 3 + ASN 后四位

1
2
3
4
5
6
7
8
9
10
11
12
13
[Interface]
PrivateKey = <private_key>
ListenPort = <YOUR_LOCAL_UDP_PORT>
[Peer]
PublicKey = <public_key_of_your_peer>
# OPTIONAL, its also possible to define a pre-shared key for additional security
PresharedKey = <PSK,双方约定好的>
# at least one peer needs to provide this one
Endpoint = <end_point_hostname_or_ip:port>
# in theory this could be restricted to dn42 networks,
# however it is easier to do this with iptables/bgp filters/routing table
# instead just like for openvpn-based peerings
AllowedIPs = 0.0.0.0/0,::/0

这是一份示例

1
2
3
4
5
6
7
8
[Interface]
PrivateKey = 114514asdasdasdasdasd=
ListenPort = 23999
[Peer]
PublicKey = 1919810asdasdasdasdasd=
Endpoint = 对方公网IP:对方端口
# 限制 IP
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12, fe80::/64, fd00::/8

开启隧道

使用 ifupdown 进行配置。

/etc/network/interfaces.d 文件夹内新建一个名为 <FOO> 的文件,内容如下

1
2
3
4
5
6
7
8
9
auto <FOO>
iface <FOO> inet manual
pre-up ip link add $IFACE type wireguard
pre-up wg setconf $IFACE /etc/wireguard/<FOO>.conf
up ip link set $IFACE up
post-up ip addr add <本机DN42 IP>/32 peer <对方Dn42 IP>/32 dev $IFACE
post-up ip addr add <本机endpoint>/64 dev $IFACE
post-up ip addr add <本机IPv6> dev $IFACE
post-down ip link del $IFACE

开启隧道:

可以通过 ping <NEIGHBOR_IPv6>%'<NEIGHBOR_INTERFACE>' 测试隧道是否正常拉起。

设置 Peers

开启隧道后,在 /etc/bird/peers 目录下新建 <FOO>.conf ,内容为(如果v4 v6都有,那就只需要v6的内容)

1
2
3
protocol bgp <NEIGHBOR_NAME>_v6 from dnpeers {
neighbor <NEIGHBOR_IPv6>%'<NEIGHBOR_INTERFACE>' as <NEIGHBOR_ASN>;
}

其中,

  • <NEIGHBOR_NAME>: 自己设置个邻居的名称
  • <NEIGHBOR_IPv6>: 邻居的IPv6,对方提供
  • <NEIGHBOR_INTERFACE>: 邻居的接口名,对方提供
  • <NEIGHBOR_ASN>: 不需要带 “AS”,对方提供
1
2
birdc c
birdc show protocol all

然后就能见到类似的输出啦

656b00ae0a538.png

与邻居的协议

事故处理

  • ip link del <FOO>:删除错误配置的网络

参见

  1. DN42 Wiki