加入DN42

摸索DN42

前言

首先非常感谢 Razuritta ,没有他就没有这篇文章!

他的博客专业性较强,文章非常厉害。

注册 DN42

dn42 gitea 注册账号。

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

Clone Repo

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

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

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

git checkout -b <username>/register

注册相关信息

可以参照 官方概要

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

维护者

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

写入以下内容

mntner:             <FOO>-MNT
admin-c:            <FOO>-DN42
tech-c:             <FOO>-DN42
mnt-by:             <FOO>-MNT
auth:               pgp-fingerprint 0123456789ABCDEF0123456789ABCDEF01234567
source:             DN42

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

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 的文件。

person:             <FOO>
e-mail:             <YourEmail>
nic-hdl:            <FOO>-DN42
mnt-by:             <FOO>-MNT
source:             DN42

官方参照:

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。

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

官方参照:

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 格式,记得用 _ 代替 /

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

官方参照:

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 格式,用 _ 代替 /

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

官方参照:

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
route6:             <你想要的 IPv6 地址块>
origin:             <你想要的 ASN>
max-length:         48
mnt-by:             <FOO>-MNT
source:             DN42

官方参照:

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
route:              <你想要的 IPv4 地址块>
origin:             <你想要的 ASN>
max-length:         <你 IP 长度,比如 27>
mnt-by:             <FOO>-MNT
source:             DN42

官方参照:

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 签名对您的提交进行签名

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

推送

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 ,然后等就行了。

系统配置

打开 Linux 内核的数据包转发功能,即 ip_forwarding

在 DN42 内,没有绝对意义上的客户端,每个人的服务器都是其它人的路由器,都可能需要转发数据包。具体步骤如下:

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
sysctl -p     # 查看配置是否正确

同时,如果你配置过 iptables 等防火墙软件,请检查相关配置,确保放行数据包的转发。

然后,关闭 Linux 内核 rp_filter 的严格模式,具体步骤如下:

echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
sysctl -p

lantian Blog

Bird2 配置

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

安装 Bird2

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

配置

参照 官方文档 内容即可

################################################
#               Variable header                #
################################################

define OWNAS =  <你的ASN>;                   # 4242423999
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 劫持。

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

加载配置

重载并查看状态

birdc c # birdc configure
birdc show protocol

查看状态
查看状态

自动化

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

*/15 * * * * ? 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
*/15 * * * * ? 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
*/15 * * * * ? birdc c

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

WireGuard 配置

安装 WireGuard

apt install wireguard -y

生成密钥

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

wg genkey | tee privatekey | wg pubkey > publickey

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

cat privatekey && cat publickey

搭建隧道

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

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

Interface 部分是自己的配置。

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

[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

这是一份示例

[Interface]
PrivateKey = 114514asdasdasdasdasd=
ListenPort = 23999

[Peer]
PublicKey = 1919810asdasdasdasdasd=
Endpoint = 对方公网IP:对方端口(一般为自己ASN后五位)

# 限制 IP
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12, fe80::/64, fd00::/8

开启隧道

使用 ifupdown 进行配置。

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

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

开启隧道:

ifup <wg配置文件名(无需后缀)>

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

设置 Peers

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

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”,对方提供
birdc c
birdc show protocol all <FOO>

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

与邻居的协议
与邻居的协议

第二个节点

这就需要拉内网了,而内网有许多种方法去组。在这里,我选择的是较为简单的方法:zerotier

这是 OSPF,以防你需要。由于我直接使用 zt 管理我的 dn42 IP 段,路由自然也由 zt 管理,我就不用去配置 OSPF, RIP 这种东西了。

protocol ospf v3 dn42_internal_ospf_v4 {
    ipv4 {
        import all;
        export filter {
            if net ~ [<OWNNET>{27,29}] then accept;
            reject;
        };
    };
    area 0.0.0.0 {
        interface "zt*" {
            tx length 2800;
            cost 1;
            type ptp;
        };
    };
}

protocol ospf v3 dn42_internal_ospf_v6 {
    ipv6 {
        import all;
        export filter {
            if net ~ [<OWNNETv6>{48,64}] then accept;
            reject;
        };
    };
    area 0.0.0.0 {
        interface "zt*" {
            tx length 2800;
            cost 1;
            type ptp;
        };
    };
}

这是另外一种 OSPF 写法。

protocol ospf v3 dn42_v6_ospf {
        router id DN42_OWNIP;
        ipv6 {
        table dn42_v6_table;
                import all;
                export none;
        };
        area 0 {
                interface "foo" {
                        cost 200;
                        type pointopoint;
                };
                interface "bar" {
                        cost 10;
                        type pointopoint;
                };
                interface "foobar" {
                        cost 200;
                        type ptp;
                };
                interface "dummy42" {
                        stub yes;
                };
        };
}

事故处理

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

后话

现在整理了一边,还是有点稀里糊涂的。希望随着时间推移,我能了解更多。欢迎联系我 Peer ~

不会就多看 Wiki 就好了。或者问带你入坑的人,XD。我是问了一整天的

参见

  1. DN42 Wiki
  2. lantian Blog - DN42 实验网络介绍及注册教程(2022-12 更新)