背景和需求

目前主力的组网工具Tailscale使用了100.64.0.0/10的网段作为虚拟网段,并通过Cloudflare将我的主要域名arenadruid.top和它的子域名 *.arenadruid.top 解析为我的NAS的Tailscale地址。

但是,Tailscale 由于其发现服务器位于国外,导致 P2P 发现成功率较低,尤其是其他人通过 P2P 连接到我的服务器的概率比预期更低。后来又使用了星空组网作为备用方案,然后就遇上一个问题,我的Jellyfin服务设置了服务地址media.arenadruid.top并部署了强制HTTPS,而media.arenadruid.top已经如前文所述解析为tailscale地址了,导致别人通过星空组网无法访问我的Jellyfin服务。

综上所述,我的需求是:让大家无论使用tailscale还是星空组网都能正常访问我的Jellyfin服务

第一次探索:Split DNS

我将这个问题发给了Deepseek,它先后两次同时给出同一个方案,准备额外的DNS服务器,让使用不同SD-WAN工具的用户在访问arenadruid.top时能够从额外DNS服务器获得特定的解析信息。也就是说,让使用星空组网的用户通过一个DNS服务器获得我的NAS在星空组网的虚拟IP;让使用Tailscale的用户通过另一个DNS服务器获得我的NAS在Tailscale的虚拟IP。

这个方案是可行的,尽管星空组网不能设置自定义DNS,但是Tailscale是可以设置Split DNS的,因此理论上我只要部署一个DNS来让Tailscale针对arenadruid.top作解析,而将Cloudflare的公共解析设定为我的NAS在星空组网的虚拟IP就可以实现类似的效果。

调整了方案之后,我就开始直接往我的NAS部署Bind9,但是设置完之后发现 DNS 服务器的默认端口(53号端口)已经被 Ubuntu 系统自带的 Systemd-resolved 占用了,无奈之下我只能尝试不使用默认端口,但是 Tailscale 又提示无法将非默认端口的 DNS 服务作为 Split DNS 的目标服务器。

COMMAND    PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd-r  532 systemd-resolve   13u  IPv4  10356      0t0  UDP localhost:domain
systemd-r  532 systemd-resolve   14u  IPv4  10357      0t0  TCP localhost:domain (LISTEN)
nginx     4370            root   49u  IPv4  23325      0t0  UDP localhost:52982->localhost:domain
nginx     4371            root   47u  IPv4  74146      0t0  UDP localhost:38791->localhost:domain
nginx     4373            root   47u  IPv4  50688      0t0  UDP localhost:53772->localhost:domain
nginx     4374            root   47u  IPv4  59131      0t0  UDP localhost:59994->localhost:domain
nginx     4375            root   42u  IPv4  60272      0t0  UDP localhost:51528->localhost:domain
nginx     4376            root   41u  IPv4  82372      0t0  UDP localhost:37989->localhost:domain
nginx     4377            root   39u  IPv4 109364      0t0  UDP localhost:47137->localhost:domain
nginx     4378            root   37u  IPv4  82287      0t0  UDP localhost:57131->localhost:domain

图注

53号端口的占用情况

Tailscale拒绝了我使用非正式端口的服务作为名称服务器的操作

“这下一根筋变两头堵了”,我思考了一下,“也就是说,如果我想要实现这个方案,要不就得多弄一个服务器专门用来解析,要不就得对这个systemd-resovled服务下刀了。”无论哪个我都觉得麻烦。因此这个方案就搁浅了。

另一条路:子网路由

理论

我突然想到了自己以前研究过的一个Tailscale功能:子网路由1。这个功能原本是让一个Tailscale设备作为一个路由,将设备所在的局域网加入到Tailscale网络中。2 而任意SD-WAN工具(无论星空组网还是Tailscale抑或是Zerotier)其机制上都是安装一个虚拟网卡,并将计算机加入到其虚拟网络之中去。因此子网路由的范围是可以设置为星空组网的网段的。

实践

首先,根据子网路由文档的说明,我在服务器命令行终端运行了以下命令。

sudo tailscale up --advertise-routes="192.168.188.3/32"

随后登陆Tailscale管理控制台,定位NAS所在位置,在额外选项中点击 “Edit route settings”,并给设置的192.168.188.3/32网段打勾。 给NAS端申请的网段打勾批准

此外还需要为客户端的Tailscale打开 “Use Tailscale subnets” 功能。

打开客户端Tailscale的”Use Tailscale subnets”功能

效果图

图注

效果图,随后将Cloudflare的域名解析为星空组网的ip即可

总结

本文提供了一个让域名能同时被不同SD-WAN访问的一个方法,这个方法理论上有比Split DNS更加方便快捷的部署方式,且理论上只要SD-WAN支持子网路由或者局域网的端口转发功能都能够使用类似的方法来通过统一ip,尽管工具不支持自定义虚拟网段3

但是,本文的实践依旧是有隐患的,由于星空组网需要升级专业版才能实现端口转发,导致必须将Tailscale的子网路由设置星空组网的虚拟IP,一旦 NAS 的星空组网未启动,192.168.188.3 将不存在于其局域网环境中,此时 Tailscale 也无法通过 arenadruid.top 域名正常访问服务器(虽然可以通过Tailscale提供的虚拟ip继续访问),甚至有可能导致Tailscale的报错和不稳定;此外,这相当于流量先从Tailscale传到星空组网再传到服务中,虽然没有实验支撑,但是理论上增加了系统的复杂度和性能开销。

而在后续的使用中,我发现这个方案有一个严重的问题,Tailscale是可以分享机器的到别人的账户的,但是分享时不能将子网路由设置一共分享出去4,这就导致接受了分享的他人账户是无法通过星空组网的路由访问服务。


版权页

Copyright © 2025 arenadruid.top | CC BY 4.0

Footnotes

  1. 理论上,专业版星空组网的端口转发功能也能实现类似效果。

  2. 关于Tailscale子网路由的更详细信息,可以参阅这篇文章Subnet routers · Tailscale Docs

  3. 本文中Tailscale强制虚拟网段为100.64.0.0/10,而星空组网需要升级专业版来自定义虚拟网段,而且即使可以自定义虚拟网段,不同SD-WAN的虚拟网段重合只会导致网段冲突和网络问题

  4. 红迪Share subnet with other user : r/Tailscale上也聊到了这个问题