杏泉网络:新节点,以及SmartDNS
系列文章:杏泉网络 专题页
最近,杏泉网络迎来了第三个节点。虽然说同属香港节点,但至少也能多多少少提供一些冗余性。不确定会加入多久,反正既来之则安之,就塞进去吧,反正就当作备用节点来使用了。
折腾完之后,发现自己又学会了新东西,比如ifupdown里面up配置的作用,netplan如何配置网络,以及SmartDNS如何分流——所以折腾总能学到点什么,就很舒服。
1. 前言
杏泉网络是笔者搭建的一个类似DN42的VPN网络,名字来源于笔者暂未写完也暂未公布的小说主人公『乌林杏泉』。关于这个网络的具体介绍和架构,在上面的前情提要中已有提及,此处不再赘述。
一直以来,网内都有两个笔者常用的服务,一个是自己做的在线笔记本,另一个就是上面提到的Vaultwarden。虽然这些东西可以很轻松地在隔壁杂物间的NAS上跑起来,但是考虑到家里没有稳定的连接环境(CGNAT,打洞经常变,上行多了怕封宽带),即使是采用Tailscale之类的服务,移动端访问也是个问题(主要是移动端一般只能开一个VPN接口),因此不如在公网上虚拟一个内网,然后集成到几乎常开的加密代理上,实现无感访问。
2. 新节点的由来
其实具体说来,整件事并不是『买新节点-接入网络』这么简单,主要还是有点幺蛾子在里头:本来杏泉网络有两个节点,us-1和hk-1,其中us-1部署服务,hk-1做接入点,但因为hk-1偶尔出现不稳定的情况(怀疑是价格过低,被同行打了),就导致hk-1体验会出现偶尔的不佳,但也还能接受。
前几天,看到另外一个VPS供应商出售年付价几十块钱的超低价香港VPS,大喜,觉得这个价格没啥所谓了,于是买回来一台,测了一下双栈网络通(以及在有使用经验的朋友的帮助下规避了一些坑),就打算接入杏泉网络。当时考虑到原来hk-1不太好用,因此一开始其实是打算用这台新VPS去成为新的hk-1,老hk-1就不续费了。所以当时就停掉了老hk-1上的杏泉网络接入措施,复制配置到新机器上重新开了起来,于是网络正常运行。
不出意外的话,是要出意外了。今天中午,不知道是笔者运气不好还是怎么的,新hk-1炸掉了....

登录到供应商后台,提示宿主机异常,正在联系上游解决,大概修了七八个小时吧,才修好。因为笔者曾经提过,杏泉网络内的节点也兼做笔者的加密代理的出口节点,所以机器下线期间为了保证同时能继续访问谷歌和杏泉网络,接入端临时改为从us-1接入,出公网延迟就瞬间大了很多。
思来想去,既然老hk-1暂时还没有到期,而且两台低价VPS加起来价格也不会负担太大,反正多一台便宜VPS不嫌多,于是就有了今天的计划:
- 老hk-1(原来的VPS) => 新hk-2
- 新hk-1(新买的VPS) => 不变
换句话说,只要更新老hk-1的配置,就能变成hk-2了
3. 地址分配
业务地址没什么好说的,198.18.5.0/24,这么点地址还是给的起的,用完了再去找10网段要。至于IPv6,自然就是fd04:17:01:0002::/48,前面加那么多0纯粹只是表明要修改哪个地方罢了,实际用的话不加也可以
互联地址比较有趣,每台机器和另外的机器对接的时候都需要一对互联地址(想象成一个虚拟的网口占用一个单独的IP),按照每台机器与两个上游连接的原则(网内只有三台机器,其实也就是全互联了),需要如下分配:
| 本端 | 远端 |
|---|---|
| us-1:198.18.0.0 | hk-1:198.18.0.1 |
| us-1:198.18.0.2 | hk-2:198.18.0.3 |
| hk-1:198.18.0.4 | hk-2:198.18.0.5 |
掩码均为/31。
IPv6配置与此类似,只是在fd04:17:0000::到fd04:17:0001::之间选取,掩码/127,限于篇幅不再列出。
最后是本地链路地址,OSPFv3需要这个东西才能正确与远端交换v6信息,每个接口一个,简单设置为fe80::3/64和fe80::4/64即可
4. 给VPS分配IP
Debian 12的网络管理工具,可谓是复杂,经常能碰到如下情况:
- 无GUI就是ifupdown
- 有GUI就是NetworkManager
- 手册示例是systemd-networkd
- 部分机器会使用netplan
笔者碰到的情况就是这样,两台香港机器,新hk-1使用ifupdown,老机器改成的hk-2使用netplan,现在要分别对这两台机器分配IP,所需要的配置文件和操作步骤也是不一样的
4.1 ifupdown
编辑/etc/network/interfaces(或其中引用的文件),找到iface lo inet loopback这一项,修改为(IP地址做对应修改):
iface lo inet loopback
up ip addr add 198.18.4.1/32 dev lo
up ip -6 addr add fd04:17:1:0001::1/128 dev lo
down ip addr del 198.18.4.1/32 dev lo
down ip -6 addr del fd04:17:1:0001::1/128 dev lo通过其中的up和down命令,在接口开关的时候自动添加删除对应的IP地址。当然部分读者可能更熟悉多个iface lo inet static的配置方式,其道理也是一样的。
编辑完成后保存,执行ifdown lo && ifup lo即可应用。
4.2 netplan
在/etc/netplan/下新建一个新的配置文件,比如60-loopback.yaml,然后写入如下配置(IP地址做对应修改):
network:
version: 2
ethernets:
lo:
addresses:
- 127.0.0.1/8
- ::1/128
- 198.18.5.1/32
- fd04:17:1:0002::1/128
match:
name: lo保存,然后执行netplan try,系统会检查并应用配置文件,如果没有看到错误提示,SSH也没有断开,那么直接按回车应用配置即可,否则,等待两分钟,配置自动回滚,不必担心失联。
注意,部分提供商可能会在开机的时候使用cloud-init初始化环境,此时就需要注意一下命名有cloud-init字样的文件,然后根据文件里面的提示,关闭这个初始化功能,以避免修改被覆盖。一般而言,都是让你在某个文件里面添加一行network: {config: disabled}就能解决问题。
5. WireGuard配置
因为我们是在WireGuard上配置点对点链路,然后使用外部程序通过OSPF配置路由,因此对于每一个接口来说,就需要一份单独的WireGuard配置文件。视作一条全新的链路,而不能在文件里的[peer]上加节点。
具体配置文件的内容,在前情提要的第一篇文章中已有涉及,此处不再赘述,只需复制粘贴后更换地址,端口,密钥即可。要注意的点是:链路两端接口的MTU必须设置为同样的值,否则后面OSPF无法成功进入Full状态。
6. OSPF建立
6.1 基本配置
又到了敲命令的时间了,因为之前已有基础配置(详见前情提要),添加新节点的操作就比较简单,无非就是OSPF用network命令宣告接口,OSPFv3直接在接口上设置area和接口类型
# 下面命令包含大量简写
# 如:ipv6 ospf6 n p
# 扩展开来应该是 ipv6 ospf6 network point-to-point
root@us-1:~# vtysh
Hello, this is FRRouting (version 8.4.4).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
us-1# conf t
us-1(config)# int wgxqnet-hk-2
us-1(config-if)# ipv6 ospf6 a 0
us-1(config-if)# ipv6 ospf6 n p
us-1(config-if)# no ip ospf pass
us-1(config-if)# q
us-1(config)# rou ospf
us-1(config-router)# n 198.18.0.2/31 a 0
us-1(config-router)# q
us-1(config)# q
us-1#
hk-2上也做类似配置。
配好之后,在us-1上,即可查看到新加入的hk-2,和原来的hk-1,都已经成功进入Full状态:
us-1# show ip ospf nei
Neighbor ID Pri State Address Interface
198.18.4.1 1 Full/- 198.18.0.1 wgxqnet-hk-1:198.18.0.0
198.18.5.1 1 Full/- 198.18.0.3 wgxqnet-hk-2:198.18.0.2
us-1# show ipv6 ospf6 nei
Neighbor ID Pri State/IfState I/F[State]
198.18.4.1 1 Full/PointToPoint wgxqnet-hk-1[PointToPoint]
198.18.5.1 1 Full/PointToPoint wgxqnet-hk-2[PointToPoint]
# 输出部分省去了一些列
同时,回到hk-2机器上执行ping命令,已经可以ping通另外两台机器了。比如说,我们ping一下hk-1:
root@hk-2:~# ping -n 198.18.4.1
PING 198.18.4.1 (198.18.4.1) 56(84) bytes of data.
64 bytes from 198.18.4.1: icmp_seq=1 ttl=63 time=302 ms
64 bytes from 198.18.4.1: icmp_seq=2 ttl=63 time=299 ms
root@hk-2:~# traceroute -n 198.18.4.1
traceroute to 198.18.4.1 (198.18.4.1), 30 hops max, 60 byte packets
1 198.18.0.0 141.805 ms 141.722 ms 141.647 ms
2 198.18.4.1 303.276 ms 303.230 ms 303.185 ms
虽然两台机器近在咫尺,但是依然出现了300多毫秒的延迟,原因就在于,对于hk-2而言,从目前的OSPF配置来说,去往hk-1的最佳路由是通过us-1转发,因为只有这一条路由是被宣告了,别的路径他都不知道。所以下一步,就是在两台香港机之间互相添加接口,宣告路由。操作方法和上面的类似,这里不再赘述。
添加之后,在vtysh控制台里面执行show ip route ospf,即可看到正常推送过来的路由:
hk-2# show ip route ospf
.....
O 198.18.0.4/31 [110/10] is directly connected, wgxqnet-hk-1, weight 1, 00:09:16
O>* 198.18.4.1/32 [110/20] via 198.18.0.4, wgxqnet-hk-1, weight 1, 00:09:15
# 可以看到,更优路由(directly connected)已经被系统选中
# 执行ping命令也能看到优化的结果:
hk-2# ping 198.18.4.1
PING 198.18.4.1 (198.18.4.1) 56(84) bytes of data.
64 bytes from 198.18.4.1: icmp_seq=1 ttl=64 time=0.967 ms
64 bytes from 198.18.4.1: icmp_seq=2 ttl=64 time=1.08 ms
6.2 模拟链路断线
在hk-2上手动执行wg-quick down wgxqnet-hk-1停掉接口,模拟链路断线(当然因为此时是系统关闭接口,上层是能立刻感知的),再进入vtysh查看路由,会发现路由迂回到了通过us-1转发,延迟也明显上升:
hk-2# show ip route ospf
.....
O>* 198.18.0.4/31 [110/30] via 198.18.0.2, wgxqnet-us-1, weight 1, 00:00:08
O>* 198.18.4.1/32 [110/20] via 198.18.0.2, wgxqnet-us-1, weight 1, 00:00:07
# 原本的直连变成了via wgxqnet-us-1
hk-2# ping 198.18.4.1
PING 198.18.4.1 (198.18.4.1) 56(84) bytes of data.
64 bytes from 198.18.4.1: icmp_seq=1 ttl=63 time=298 ms
64 bytes from 198.18.4.1: icmp_seq=2 ttl=63 time=298 ms
当然,这样的迂回有种聊胜于无的感觉,因为目前两台香港机器并没有托管业务,也就没有互联的需求,所有请求都要在us-1上终结,所以如果香港机断线了,本地也只能切换到另外一个机器上的加密代理继续接入而已。倘若是香港到美国的海缆断了,同样也没有什么作用,底层链路都断了,上层链路自然也就不复存在。
7. DNS 配置
7.1 主DNS配置
根据之前配置,打开/etc/bind/db.xq,添加如下内容:
2.hk IN A 198.18.5.1
*.2.hk IN A 198.18.5.1
2.hk IN AAAA fd04:17:1:2::1
*.2.hk IN AAAA fd04:17:1:2::1保存,然后打开/etc/bind/db.198.18,添加反向解析:
1.4 IN PTR 1.hk.xq.保存,然后执行rndc reload让配置生效,即可。
7.2 接入点DNS分流
读过之前文章的朋友应该还记得,当时笔者对于网内域名解析分流,使用的是DNSMasq。虽然本来迁移hk-1机器的时候,新VPS上也可以继续用DNSMasq,但是上面提到,笔者刚拿到机器的时候进行了一些基本测试,于是就发现了很有趣的现象:
root@hk-1:~# ping google.com
ping: google.com: Address family for hostname not supported
root@hk-1:~# dig +short google.com aaaa
root@hk-1:~#
root@hk-1:~# dig +short google.com a
6.6.6.6
root@hk-1:~# cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 1.1.1.1
root@hk-1:~#也就是说,一台双栈网络正常的机器,居然无法解析出来IPv6域名,而且解析出来的IPv4地址明显也不正确,说明上层可能存在DNS拦截,而DNS拦截的目的一般都是为了配合SNI Proxy解锁流媒体。为了验证这个猜想,继续进行以下实验:
root@hk-1:~# dig +short @1.1.1.1 netflix.com
6.6.6.6
root@hk-1:~# dig +short @8.8.8.8 netflix.com
6.6.6.6
root@hk-1:~# dig +short +tcp @1.1.1.1 netflix.com
3.230.129.93
54.237.226.164
52.3.144.142
root@hk-1:~# dig +short @9.9.9.9 netflix.com
3.230.129.93
54.237.226.164
52.3.144.142很显然,上游至少针对1.1.1.1和8.8.8.8这两个常用DNS的UDP 53有重定向,以便于针对指定域名进行分流处理。虽然正常来说不影响使用,但是笔者不是很愿意让他帮我处理这一块(尤其是考虑到SNI Proxy可能会过载,以及无法解析AAAA),因此需要做修改处理。
从上面实验可以知道,TCP 53不会被拦截,而且显然,DoH和DoT也不会被拦截,因此只需要一个支持上述几种DNS类型的转发器即可,DNSMasq不支持,那么就干脆换用SmartDNS算了。
SmartDNS的安装方式可参照官网描述来进行,这里重点说一下配置文件:
# 只监听内网地址
bind 127.0.0.1:53
bind 198.18.4.1:53
bind [::1]:53
# 缓存设置
cache-size 32768
cache-checkpoint-time 86400
# 乐观缓存
serve-expired yes
serve-expired-reply-ttl 3
# 不被拦截的上游服务器
# 用作一般域名解析
server 9.9.9.9
server-tcp 1.1.1.1
server-tcp 8.8.8.8
# 杏泉网络域名解析设置
server 198.18.3.1 -group xq -exclude-default-group
# 对应的正向和反向(PTR)解析设置
nameserver /xq/xq
nameserver /18.198.in-addr.arpa/xq按照这样设置,就可以让节点拥有DNS分流功能,并正常使用。
8. 写在最后
反正多少学到了点东西是真的。
以后有闲钱,可能会买一台JP或者SG的VPS,作为中间节点使用,让杏泉网络更具备一定的故障转移功能。但就目前而言,先这样吧,也许有时间还可以继续发掘一下这玩意的用途。
(完)