接下来我们要接触到网络的另外一个基础设施了,没错,就是DNS!(我是因为想起要记录一下这个才发现自己咕咕咕了这么久)
结果展示
我重构了我的DNS系统,现在选的是TechnitiumDNS服务器,支持网页操作,新版同时支持集群部署,自动同步各实例,对于打算上Anycast的我非常友好,实际部署下来也确实比较舒爽。
先来设计一下整体的架构:

我在3个节点上各部署一个实例,然后3个实例之间组成集群,在每个节点上各绑定多了一个veth作为loopback接口,然后在每个节点上写静态路由。这样,无论DNS请求在哪个节点上收到,就会直接在同一个节点上回复,显著地降低了延迟。
没错,就是anycast!
最后的结果如下:

哎~到处都是很低的延迟,GoodJob。然后根据延迟,猜测到了3个节点的位置。(不过我也只有3个啦)

部署过程
部署单个节点
# 创建bridge,准备给容器接入
/interface/bridge add name=containers.dn42
/ip/vrf set dn42 interfaces=<之前有的接口>,containers.dn42
/ip/address add address=172.23.183.153/29 interface=containers.dn42
/ipv6 address add address=fd48:fa31:502b:8200::/64 advertise=no eui-64=no interface=containers.dn42
# 创建容器接口,一个互联接口,一个loopback接口
/interface veth add address=fd48:fa31:502b:8200:172:23:183:158/64,172.23.183.158/29 gateway=172.23.183.153 gateway6=fd48:fa31:502b:8200:: name=container.dn42.ns1
/interface veth add address=172.23.183.136/32,fd48:fa31:502b:100:172:23:183:136/128 name=containers.dn42.anycast.dns
# 创建容器
/container envs add key=DNS_SERVER_DOMAIN list=ns value=ns1.ferrets.dn42
/container mounts add dst=/etc/dns list=ns src=/containers/technitium/config
/container add envlists=ns interface=container.dn42.ns1,containers.dn42.anycast.dns mountlists=ns name=ns1.ferrets.dn42 remote-image=technitium/dns-server restart-policy=on-failure root-dir=/technitiumdns start-on-boot=yes
# 手动写静态路由
/ip route add check-gateway=arp comment=ns.ferrets.space-Anycast dst-address=172.23.183.136/32 gateway=fd48:fa31:502b:8200:172:23:183:158@dn42 vrf-interface=dn42
/ipv6 route add check-gateway=arp comment=ns.ferrets.space-Anycast dst-address=fd48:fa31:502b:100:172:23:183:136 gateway= fd48:fa31:502b:8200:172:23:183:158@dn42 vrf-interface=dn42
如此一来,一个节点就整好了,在其他节点重复多2次,3个节点就部署好了。
部署集群
集群化之后,就可以一次修改,全局生效了。去Administration-Cluster点击右上角的Initialize,下拉。第一个节点是New cluster,后面的节点是Join cluster。

创建集群这个没啥好说的,重点是加入集群:


Quick Add可以下拉,会列出节点可用的ip地址
Primary Node URL可以直接从主节点的状态页面上复制
Primary Node IP Address需要手动填,直接填创建集群的节点的ip地址就行
Certificate Validation这个配置起来有点麻烦,我们先忽略证书告警,反正几个节点之间没有经过其他人的网络,问题不大。
Primary Node Username 主节点的管理员账号
Primary Node Password 主节点的管理员密码
创建集群之后,用户账号会同步,使用相同的账号和密码,与此同时,集群中随便一个节点都能管理整个集群。
创建集群之后,会多一个叫做cluster-catalog的zone。其他zone会经过这个特殊的zone来选择是否同步。

反向DNS zone
反向DNS zone这个比较特殊,因为我们拿到的都不是整个的/24的地址块,所以,以我手里的地址快为例:172.23.183.128/26,我们拿不到183.23.172.in-addr.arpa的授权,这个域的授权在dn42的delegation-server上。查询delegation-server的时候,将会返回一个CNAME记录。会通过CNAME指向128/26.183.23.172.in-addr.arpa。
例如:查询172.23.183.128的PTR,delegation-server将会返回CNAME:128.128/26.183.23.172.in-addr.arpa。然后,递归查询服务器再查找128/26.183.23.172.in-addr.arpa的授权服务器,并向其查询128.128/26.183.23.172.in-addr.arpa。
DN42的相关文档都会教你创建一个128/26.183.23.172.in-addr.arpa的zone,但是我在用Technitium的时候遇到了一个问题:Technitium严格遵守规范,认为“/”是非法字符。于是我们只能通过一个间接的方法来处理:
- 创建一个
128-26.183.23.172.in-addr.arpa的zone
在APPS里面,安装一个叫做“Zone Alias”的插件
配置Zone Alias,通过映射,让服务器返回128/26.183.23.172.in-addr.arpa和128-26.183.23.172.in-addr.arpa一样的结果
如此一来,虽然我们配置的是128-26.183.23.172.in-addr.arpa,但是服务器同样能够相应128/26.183.23.172.in-addr.arpa的查询请求。
递归服务器
我们已经部署好授权服务器了,下一步是部署递归服务器,不然我们自己没法解析.dn42的域名,这就很不好了。
同样以TechnitumDNS为例。这次我们就不做集群了,单点就行,反正就我们自己用,炸了就先修嘛。
容器部署过程参考上面,我们从安装后的配置开始,一共需要配置7个zone:

dn42
d.f.ip6.arpa
20.172.in-addr.arpa
21.172.in-addr.arpa
22.172.in-addr.arpa
23.172.in-addr.arpa
delegation-servers.dn42
其中dn42和其他几个反向zone的类型都是stub,意味着如果有这种类型的查询,就跳过从根域名开始的查询,直接从这个域开始递归查询。
delegation-servers.dn42的类型是secondary,可以直接从各delegation-servers直接进行zone transfer。

为了保证能从delegation-servers拿到结果,避免鸡生蛋蛋生鸡的问题,需要写上Primary Name Server Addresses:
172.20.129.1
172.20.1.254
172.20.14.34
172.22.108.54
172.23.91.1
fd42:4242:2601:ac53::1
fd42:5d71:219:0:216:3eff:fe1e:22d6
fdcf:8538:9ad5:1111::2
fd86:bad:11b7:53::1
fd42:4242:2189::1
点击添加之后,可以直接从他们那边同步数据,然后得到结果。
接下来,你就可以用这个自建的递归服务器查询DN42网络上的域名啦~
另外,需要额外注意一下settings里面的ipv6 support,如果禁用了ipv6的话,会导致相当一部分域名无法解析。































