dn42 入门指南
简介
本文是dn42入门指南,一般的步骤从简,重点描述BIRD的配置。
dn42 是一个大型的动态连接的虚拟专用网,其最核心的是使用BGP协议进行互联。我接入该网络的目的,主要就是探索BGP协议。
步骤
根据官方入门指南,初次接入的主要步骤如下
-
注册dn42账户
-
推荐配置ssh-agent
-
有好几种方式用于签名自己的提交,推荐使用维护到dn42 gitea的方法
-
Fork
dn42/registry代码库 -
提交注册文件,等待管理员Merge合并
-
mntnr
-
person
-
注册AS number
-
注册IPv6 prefix
-
注册IPv4 prefix
-
route
-
route6
-
dns
推荐把DNSSEC的ds-rdata一起搞了,省得以后麻烦
-
-
找到一些peers
接下来使用BIRD进行BGP配置
BIRD 配置分析
首先维护一个loopback interface,加上自己合法的dn42 ipv4和ipv6,维护好后网卡信息是像这样的
# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
......
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet6 fe80::abcd/64 scope link
valid_lft forever preferred_lft forever
4: lo1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 172.xxx.xxx.xxx/32 scope global lo1
valid_lft forever preferred_lft forever
inet6 fdxx:xxxx:xxx::1/128 scope global
valid_lft forever preferred_lft forever
然后进行/etc/bird.conf配置 基本抄至dn42官方指南BIRD2配置,但增加了一行extended next hop on;
################################################
# Variable header #
################################################
define OWNAS = <自己的AS>;
define OWNIP = <自己的IP 172开头>;
define OWNIPv6 = <自己的IPv6 fd开头>;
define OWNNET = <自己的网络 172开头 一般是/27>;
define OWNNETv6 = <自己的网络 fd开头 一般是/48>;
define OWNNETSET = [ <自己的网络 172开头 一般是/27>+ ];
define OWNNETSETv6 = [ <自己的网络 fd开头 一般是/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;
# 这行允许指定ipv4地址的下一跳是ipv6地址,很重要
extended next hop on;
};
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/roa_dn42.conf
# 需要使用crontab或systemd timer定时更新
route 172.23.35.0/26 max 29 as 4242423993;
route 172.23.101.192/27 max 29 as 4242422340;
route 10.40.0.0/16 max 24 as 65078;
...
/etc/bird/roa_dn42_v6.conf
# 使用crontab或systemd timer定时更新
route fdad:23e:f50::/48 max 48 as 4242421477;
route fddf:bf7:80::/48 max 64 as 64859;
route fdd3:84c3:cab::/48 max 48 as 4242420686;
...
/etc/bird/peers/uplink-ASxxxxxxxxxx配置
# 这里使用的是ipv6 local link address 配置对端
protocol bgp uplink_ASxxxxxxxxxx from dnpeers {
neighbor fe80::1234 % wg0 as xxxxxxxxxx;
}
重启BIRD使配置生效
systemctl restart bird
如果一切顺利的话,ip route显示
#ip route
10.37.0.0/16 via inet6 fe80::1234 dev wg0 proto bird src <自己的IP 172开头> metric 32
10.50.0.0/16 via inet6 fe80::1234 dev wg0 proto bird src <自己的IP 172开头> metric 32
10.56.0.0/16 via inet6 fe80::1234 dev wg0 proto bird src <自己的IP 172开头> metric 32
...
ip -6 route显示
#ip -6 route
fd00:bb:5bf3::/64 via fe80::1234 dev wg0 proto bird src <自己的IP fd开头> metric 32 pref medium
fd00:bb:5bf3:a::/64 via fe80::1234 dev wg0 proto bird src <自己的IP fd开头> metric 32 pref medium
fd00:bb:5bf3:1561::/64 via fe80::1234 dev wg0 proto bird src <自己的IP fd开头> metric 32 pref medium
...
这些都是通过BGP协议学习来的路由,一停BIRD就没有了
再找两个dn42的ipv4、ipv6测试地址ping一下,最好是你的neighbor所提供的,若能ping通则实验成功
最后可以利用常用birdc命令对BIRD状态、对端export给我们的路由、我们export给对端的路由、被filter掉的路由等进行检查
BIRD配置分析
- ROA只能像这样加载,或利用
protocol rpki加载,后者最终也是从ROA文件加载,并没有实际提高安全性,protocol rpki配置方法参考这里或这里 - 由于现在只有一个peer,还没有做BGP communities
- BIRD的每一行配置文件都要好好解读,可以参考这里逐行阅读
下一步
- 连接更多的外部peer,实验利用BGP communities选择更好的路径
- 建立更多的内部子网,实验IBGP和EBGP混搭
参考
- https://github.com/Mic92/bird-dn42/blob/master/bird.conf Mic92的bird配置
- https://wiki.skywolf.cloud/quickstart/idc.html 公网BGP bird配置
- https://kotori.net/tag/bgp/ 公网BGP bird配置
- https://bgplabs.net/policy/9-community-use/ 了解bgp community有什么用