更新记录 / Changelog
- 20230201:
- wireguard 配置中
AllowedIPs
由0.0.0.0/0, ::/0
更改为 DN42 所在网段10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64
,限制一下 IP 段防止数据包被转发到公网 - 扩展中 extended next hop 新增 wg 配置模板
(太多人问了,不想解释了 - 完善了一下和喵喵 peer 的信息
- wireguard 配置中
- 20220423:系统配置中
rp_filter
由 2 改为 0. - 20210325:首次发布
0x00 前言
其实想玩 DN42 也有一段时间了,正好最近群友也在聊 DN42,动不动就「来 Peer!」。
那咱就来整一个好了!
请注意,本文不是一篇完整的介绍性文章,只是记录一下配置过程中遇到的坑啊什么的。
0x01 What 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, 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
) - see FAQ.A number of services are provided on the network: see internal (only available from within dn42). Also, dn42 is interconnected with other networks, such as ChaosVPN or some Freifunk networks.
Via Official Wiki
DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型、去中心化的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 本身不提供 VPN 出口服务,即不提供规避网络审查、流媒体解锁等类似服务。相反,DN42 的目的是模拟一个互联网。它使用了大量在目前互联网骨干上应用的技术(例如 BGP 和递归 DNS),可以很好地模拟一个真实的网络环境。
简而言之,DN42:
- 不适合单纯想要保护隐私、规避网络审查的用户
- 不适合在网内消耗大量流量,例如用于解锁流媒体服务的用户
- 适合想要研究网络技术,练习服务器、路由器等网络设备配置,甚至后续在真实互联网建立 AS 的用户
- 适合拥有真实 AS,但担心自己配置错误广播出错误路由、干掉半个互联网,希望有个地方测试的用户。
Via Lan Tian’s Blog
其实就是说,DN42 是一个大型 VPN 网络,模拟了现实生活中的真实互联网。
目前 DN42 已经与 NeoNetwork、ChaosVPN 等网络实现了互联,加入就能体验到其他网络内的资源。
那为什么要加入 DN42 呢?
当然是好玩啦 w
你想想,只需要动动手动动脑,就能免费拥有属于自己的 ASN (Autonomous system number,自治系统编号),能宣告一段 IPv4 和 IPv6,体验各种路由协议,还能和别人尽情地 py Peer(对接)。
这可比普通的计算机网络实验好玩多了!
当然,为了折腾 DN42,你至少需要一台能不间断联网的设备以及对它的 root 权限,当然还需要花不少时间……(喵喵好菜啊,别骂了别骂了
0x02 大概的步骤
TL;DR
- 在 Git 仓库申请账号,申请好你需要的 ASN,IP 段(,域名以及反向解析服务器),然后给仓库提PR
- 寻找一个可能的 Peer 节点,按照他留下的联系方式给他发邮件/IRC/Telegram/etc.
- 寻找一个延迟较低的节点,并和他约定好使用的 VPN 软件和路由协议
- 建立 VPN 通信隧道,确保能互相连通
- 建立路由(一般是 BGP)
0x03 注册过程
这部分主要参考 Lan Tian 师祖的 DN42 实验网络介绍及注册教程(2020-10-01 更新) 一文进行。
目前 DN42 采用 git 仓库进行管理,可以参考 DN42 官方 Wiki howto/Getting Started 来进行配置。
也可以参考 喵喵的 PR,喵~ (需要登录 git)
为了找空出来而且好看的 ASN,喵喵还专门写了个脚本……
具体就不说了,但吐槽几句。
这里有几个坑就是,需要用 Linux 系统来进行配置,一定不要用 Windows 系统,因为 win 的文件系统不支持带有 :
的文件名,于是 git 仓库都拉不下来。
如果想要用 win 的话,可以使用 WSL2。
另外就是,找 IP 段很容易碰到冲突,而且自己不容易发现……、
比如之前找了一段发现被人占了好大一块,又或者整个 /18 保留给 /24 - /21 了,人傻了。
再比如之前申请的一个段发现被 DN42 官方保留了。
INFO: 172.22.222.0/26 (inetnum): Inetnum has different mntners than parent and policy of parent is reserved: [MIAOTONY-MNT] vs [DN42-MNT].
找了半天才发现是有个 172.22.192.0/18,直接好家伙。
当然,如果有多个 commit 记录,记得先 squash 一下再 push,可以直接用目录下自带的脚本来 push。
不过其实也没啥关系,PR 上去之后有 CI 自动进行检测,按照要求更改就完事了。
0x04 首先要进行的系统配置
在每一台要加入 DN42 的节点都需要进行以下配置!
- 打开 Linux 内核的数据包转发功能,即
ip_forwarding
。 - 关闭 Linux 内核
rp_filter
的严格模式。 - 关掉 ufw 等帮助配置 iptables 防火墙的工具。(如有需要,手动配置 iptables
前两条设置步骤如下。
vim /etc/sysctl.conf
新增以下几条配置
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.all.rp_filter=0
然后应用配置
sysctl -p
20220423 Update:
rp_filter
由 2 改为 0.主要是因为在某次测试中发现出了点锅,回去看了蓝天的博客,发现更新了……
但是理论归理论,在新版本(5.0+)的内核中,实际使用中依然会有大量来源地址正确的正常数据包被丢弃。因此不要使用这个模式,请统一使用 0。
好吧。
0x05 建立通信隧道
DN42 是基于 VPN 来建立通信连接的,为了方便,大多数用户都使用 WireGuard 来进行。
WireGuard 是 L3 层隧道,目前已经集成到了 Linux 内核中,它配置简单,占用资源少,安全性较高。
如果不是 OpenVZ 或者 LXC 虚拟化的话,其他应该都能用吧,不支持的话可能需要升级一下内核版本。
这里可以参考 官方 Wiki 的 howto/wireguard 来进行。
Wireguard is a Layer3 VPN. In theory it allows multiple peers to be served with one interface/port, but it does internal routing based on the peer’s public key. This means you will need one interface per peering on dn42 to allow your BGP daemon instead to do routing. This approach is comparable to OpenVPN p2p tunnels.
意思是 wg 内部的路由是基于公钥来进行的,于是和不同的网络进行 peer,对于每个 peer 都需要建立一个新的接口,也就相当于多一个虚拟网卡。不过这个接口的 IP 可以都一样,不受影响。
首先 生成一对公钥和私钥
wg genkey | tee privatekey | wg pubkey > publickey
不同于 Lan Tian 师祖的 sh 配置脚本,此处喵喵 直接使用 wg-quick
来配置。
这是我的配置模板。一般是放在 /etc/wireguard/xxx.conf
.
[Interface]
PrivateKey = <自己的私钥>
ListenPort = <自己监听的端口,一般是对方ASN后五位>
PostUp = ip addr add <你的DN42 IPv4>/32 peer <对方的DN42 IPv4>/32 dev %i
# 如果用 IPv6 ULA
# PostUp = ip addr add <你的DN42 IPv6>/128 peer <对方的DN42 IPv6>/128 dev %i
# 如果用 link-local(推荐)
PostUp = ip addr add <link-local>/64 dev %i
Table = off
[Peer]
PublicKey = <对方的公钥>
Endpoint = <对方的公网地址>:<对方的端口,一般是自己ASN后五位>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64
如果 [Interface]
里写了 Address
的话需要在 PostUp
里先删掉 addr 再加上 peer
,所以干脆就不配 Address
了。
注意这里 Table = off
要加上,不然所有的流量,包括公网上的流量就都转发给你的 peer 了,这样可能你就连自己的机器都连不上了。
然后喵喵配完 wg,一启动,SSH 连接断了,喵喵愣住了(还好服务商能起 VNC,然后上去把 wg 连接断了才重新连上 SSH…
这里一般推荐用 link-local 地址 进行配置,除非双方约定好是用 ULA。
这是链路本地地址, IPv6 定义在 fe80::/10 地址块。一般就是 fe80::<你的ASN后四位>
。
然后为了方便,参考 @moecast 大佬的配置脚本,一步配置 service。
$ cat /sbin/wgen
#!/bin/bash
filename="$(basename -- $1 .conf)"
systemctl enable wg-quick@$filename.service
service wg-quick@$filename start
这个脚本将启动隧道,并把配置注册到 service 中,实现开机自启。
把这个脚本放到 /sbin/wgen
,然后 chmod +x /sbin/wgen
赋予执行权限。
需要用的时候直接 wgen 文件名
就行了。
最后看看连接建立了没有。
wg show 文件名
# 或者直接 wg
看到 transfer
里发送接收都有数据了说明就能连上了。
当然也可以 ping 一下对方。
WireGuard 接口名就是你配置的文件名。
# ping 对方IP%WireGuard接口名
ping fe80::xxxx%wg_424242xxxx
当然了,也可以手写 systemd 来配 wg,参考 官方 Wiki 就好了。
20230201 Update:
将
AllowedIPs
由原来的0.0.0.0/0, ::/0
改成 DN42 所在的网段10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64
了,这样可以直接用 wireguard 自带的 IP 限制功能,防止数据包被转发到公网。如果你要把原来的配置文件都改了,可以执行下面的命令替换,记得改成你自己的路径
sed -i 's|0.0.0.0/0, ::/0|10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64|g' /etc/wireguard/wg_*.conf systemctl restart wg-quick@wg_*
然后咱发现有些 peer 的 wg 域名可能已经失效,于是起不来了(跑 路 了(摊手.jpg
0x06 建立 BGP 会话
BGP(Border Gateway Protocol,边界网关协议) 是一种路由协议,一般都使用这个来进行 peer。
路由的软件一般使用的是 BIRD Internet Routing Daemon (v2) 。
此处参考
bird.conf 与 ROA
这里要注意 一定按照教程先配好 /etc/bird/bird.conf
,或者 /etc/bird.conf
!
此处使用的是 wiki 上的模板,比如喵喵的 Variable header 如下。
OWNIP
和 OWNIPv6
是你本机要分配的地址,OWNNETSET
和 OWNNETSETv6
不用漏了结尾的 +
。
################################################
# Variable header #
################################################
define OWNAS = 4242422688;
define OWNIP = 172.23.6.6;
define OWNIPv6 = fd00:feed:ca7::6;
define OWNNET = 172.23.6.0/26;
define OWNNETv6 = fd00:feed:ca7::/48;
define OWNNETSET = [172.23.6.0/26+];
define OWNNETSETv6 = [fd00:feed:ca7::/48+];
################################################
# Header end #
################################################
然后把 ROA (Route Origin Authorization) 配好。
一般路径在 /etc/bird/roa_dn42{,_v6}.conf
可以写个 crontab 定期自动下载更新。注意 bird.conf
里的 roa
路径要配的一致。
# crontab -e
*/15 * * * * curl -sfSLR -o /etc/bird/roa_dn42.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf && curl -sfSLR -o /etc/bird/roa_dn42_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf && /usr/sbin/birdc configure 1> /dev/null
可以先执行一次让文件存在,不然后面启动 bird 的时候可能会有问题。
Peers 文件
mkdir -p /etc/bird/peers
每一个 peer 建一个文件 /etc/bird/peers/<NEIGHBOR_NAME>.conf
。
下面是 Lan Tian 师祖的模板。
protocol bgp dn42_[PEER_NAME]_v4 from dnpeers {
neighbor [YOUR_DN42_IP] as [YOUR_ASN];
direct;
# 下面这段是在 IPv4 BGP 中禁用 IPv6 路由传递,强烈推荐;查看下文以决定你要不要这样做(保留下面的内容)
ipv6 {
import none;
export none;
};
};
protocol bgp dn42_[PEER_NAME]_v6 from dnpeers {
neighbor [YOUR_LINK_LOCAL_IP] % 'dn42-[PEER_NAME]' as [YOUR_ASN];
direct;
# 下面这段是在 IPv6 BGP 中禁用 IPv4 路由传递;查看下文以决定你要不要这样做(保留下面的内容)
ipv4 {
import none;
export none;
};
};
- MY 指的是你自己,而 YOUR 指的是你将要 Peer 的那个人。
- BIRD 中配置的是 DN42 内的 IP 而非公网 IP。
- 相比 DN42 Wiki 上的配置,我加了一行
direct;
,原因是我发现如果缺少这行,路由信息有可能无法被正确的导入系统路由表。
- BIRD 默认会根据系统路由表查找要将数据包转发到哪个网络设备,以此设置系统路由表,但有时查找会失败(表现为
ip route
中出现大片unreachable
)。- 此时指定
direct
,让 BIRD 将数据包直接转发到 BGP 连接所在的网卡上。direct
的含义是连接双方直接连接(即中间没有间隔其它的路由器)。- PEER_NAME 是对方的昵称,这里设置的是 Linux 下的网络设备名,与隧道保持一致。注意整个网络设备名不能超过 15 个字符,否则会被截断。
- 在 IPv6 Peering 时,我推荐使用 Link-local IP。
- 直接使用对方整个节点的 IPv6 地址(指
fd00::/8
范围中的那个)时,部分系统不会自动添加到对端的路由,需要手动添加一条;见隧道搭建:WireGuard
一节。- 在 BIRDv2 中,强烈推荐在 IPv4 BGP 会话中禁用 IPv6 的路由传递,同时可以在 IPv6 BGP 中禁用 IPv4 路由传递。
- BIRDv2 支持在一个 BGP 会话中同时传递 IPv4 和 IPv6 的路由。
- 在 IPv4 BGP 会话中,BIRDv2 难以正确判断 IPv6 数据包转发目标的地址(Next Hop),会导致
ip -6 route
中出现大片unreachable
。
- 因此直接禁用就好了。
- 在 IPv6 BGP 会话中传递 IPv4 路由时,如果双方使用特定的 BGP 软件组合,一方或双方的日志中会出现大片
Invalid NEXT_HOP Attribute
,指 Next Hop 判断出错。
- 但 IPv6 BGP 中同时传递 IPv4 和 IPv6 路由的应用还比较广泛,因此一般建议不要禁用 IPv4 路由传递,除非出现了问题。
BIRD2 是支持 Multiprotocol BGP 的,也就是可以在单独一个 IPv4/IPv6 BGP session 里建立 v4 和 v6 两条 channel。(大概意思是这样,不知道说的准不准确
于是如果双方都支持 MP-BGP 的话,一般是用 link-local 建立一条 v6 的 BGP session 就好了。
由于 link-local 只是在连接双方的接口进行的,需要指定好接口。
可以参考 喵喵的模板。
protocol bgp dn42_424242xxxx_v6 from dnpeers {
neighbor fe80::xxxx % 'wg_424242xxxx' as 424242xxxx;
direct;
}
注意 fe80::xxxx
是对方的 link-local address,wg_424242xxxx
是你网络接口的名字。
之后启动 BIRD,或者重新加载配置。
service bird start # 如果没启动的话
birdc c # 即 birdc configure
然后可以看看连接状态了。
birdc s p # 即 birdc show protocol
如果显示的是 Established
,那么连接就建立好了。
Peer 成功!
当然还可以查看某条路由配置的详细信息。
birdc s p a dn42_424242xxxx_v6 # 即 birdc show protocol all dn42_424242xxxx_v6
然后就能 ping 一下 DN42 内的服务了,比如 172.20.0.53 之类的。
一点点扩展
2021.3.21 新发布的 BIRD v2.0.8 新增了许多特性。
其中有一个是支持了 extended next hop,可以实现 IPv4 流量在 IPv6-only 网络上的转发。(反正群友说的我也懒得考证了
参考 BIRD 文档里的 BGP extended next hop
在 dnpeers
里的 ipv4
中加入 extended next hop on;
即可使用这一特性。
于是和别人 peer 的时候,WireGuard 只需要 peer 一个 IPv6 link-local address 就完事了,连 DN42 IPv4 都不需要了。
也就是改成下面这样,这个 link-local
是你自己的,比如咱这里一般是 fe80::2688
[Interface]
PrivateKey = <自己的私钥>
ListenPort = <自己监听的端口,一般是对方ASN后五位>
PostUp = ip addr add <link-local>/64 dev %i
Table = off
[Peer]
PublicKey = <对方的公钥>
Endpoint = <对方的公网地址>:<对方的端口,一般是自己ASN后五位>
AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe80::/64
当然还需要加一个 dummy 接口来写本机的地址,类似于
ip link add dummy1 type dummy
ip addr add <你的DN42 IPv4>/32 dev dummy1
ip addr add <你的DN42 IPv6>/128 dev dummy1
不然路由表有可能写入不到内核中。
为了持久化,需要写到配置文件中。Ubuntu 下用的是 netplan。
在 /etc/netplan/
目录下新建一个文件,内容如下。
$ cat 01-dummy0.yaml
network:
version: 2
renderer: networkd
bridges:
dummy0:
dhcp4: no
dhcp6: no
accept-ra: no
interfaces: [ ]
addresses:
- <你的DN42 IPv4>/32
- <你的DN42 IPv6>/128
其他系统的话可以配置 /etc/network/interfaces
。
auto dummy0
iface dummy0 inet static
pre-up ip link del dummy0 || true
pre-up ip link add dummy0 type dummy || true
address <你的DN42 IPv4>/32
post-up ip addr add <你的DN42 IPv6>/128 dev dummy0
然后重启之后就能自动配上这个 dummy 接口了。
BTW,喵喵觉得一个一个手动配太麻烦了,于是自己用 Python 糊了个小脚本,只需要输入必要的信息,就能自动生成配置文件,并建立 WireGuard 连接,重新加载 BIRD 配置了,贼舒服!
(不过脚本太丑了而且是自己用的,就不放出来了吧
0x07 一些好玩的东西
大佬们给节点做了可视化,比如以下几个。
https://nixnodes.net/dn42/graph/
啊啊啊,毛线好多缠住喵喵了(大雾
当然还有很多 dn42 / NeoNetwork NOC 的 looking glass,比如:
以及 DN42 里的服务 internal/Internal Services
Burble 老师的服务 https://dn42.burble.com/services/public/
当然还可以绑定 .dn42 域名,设置反向解析 rDNS,当然还有 .dn42 的 CA 证书……
为了给自己的多个设备组网,还可以 iBGP、iGP、Babel、OSPF 等路由协议综合来使用。
反正还能慢慢玩呢(
0x08 Peer with MeowNet
什么?你想和我 Peer 了?快来 Peer!
AS4242422688
MeowNet
MiaoTony’s DN42 Network
DN42 IP:
172.23.6.0/26
fd00:feed:ca7::/48
Nodes:
- LAS1 - Las Vegas, US, BuyVM
- To be continued…
WireGuard and Multiprotocol BGP are preferred.
I prefer to use link-local IPv6 address to set up multiprotocol BGP session (with extended next hop enabled).
Welcome to peer with me!
Telegram: (Recommended) Just PM @meow_portal_bot and tell me you are from DN42.
Email: [email protected]
可以直接用中文来 peer,记得说一声来自 DN42(当然如果你想用英语都行
You should send me some info like follows.
Your ASN
Public IP
- IPv4 is preferred, but you can send v4/v6 both
DN42 IPv4 and IPv6
- Link-local address is preferred, usually
fe80::<Your last 4-digit ASN>
- Link-local address is preferred, usually
Your WireGuard Port
- 22688 by default
- I will use
2<Your last 4-digit ASN>
for you
Your WireGuard public key
Features
Is Multiprotocol BGP supported?
- If yes, I will just use the link-local IPv6 address to set up v4+v6 BGP session
- Yes by default
Is extended next hop enabled?
- If yes, I will omit DN42 IPv4 in WireGuard
- Yes by default
Something else you want to share with me
或者看下面也行。
0x09 小结
这篇文章对申请 ASN、IP、域名,搭建 VPN 通信隧道,配置 BGP 路由,完成和其他网络的 Peer 等内容进行了介绍。
但要注意的是本文并不是一篇完整的介绍,还需要参考其他教程来综合进行配置。
不过刚来玩 DN42,还有很多不熟悉的地方,还得感谢群里的大佬们 Orz。
如果有错误欢迎指出,喵!
0xFF References & Extensive Reading
- DN42 官方 Wiki howto/Getting Started
- Lan Tian 师祖的 DN42 实验网络介绍及注册教程(2020-10-01 更新)
- 接入 dn42 及 NeoNetwork
- 辣条①号 的 DN42 系列
- 什麼,透過BGP從小型網路到真正的網際網路!? 系列
- BIRD 与 BGP 的新手开场
- iBGP - BGP within AS4242423905
- etc.
喵呜!终于扯完这篇文章了!
好久没写技术文章了,喵喵累死了(
(溜了喵