我想要的效果很简单:手机只运行一个 Stash,平时照常用机场代理,需要访问家里的 NAS、OpenWrt 或其他 Tailscale 设备时,直接打开它们的 100.x.x.x 地址。官方 Tailscale App 可以做到,但它和 Stash 都会占用 iOS 的 VPN 通道,我不想来回切换。
最后调通的方案是把 Tailscale 节点放进 Stash 的远程代理集,再用 Override 保存自定义配置。这样服务商订阅更新时,自己的 Tailscale 配置不会被覆盖。
GitHub 里只放节点文件#
我在 GitHub 私有仓库里放了一个 tailscale.yaml:
proxies:
- name: ts-main
type: tailscale
hostname: iphone-stash
control-url: https://controlplane.tailscale.com
ephemeral: falseyaml首次认证时可以临时填写 auth-key。节点在 Tailscale 后台上线后,我把密钥从文件里删掉,避免长期把它放在订阅内容中。
这里的 hostname 是 Stash 这台 Tailscale 客户端的设备名,不是 NAS 或 OpenWrt 的名字。
为什么不用直接改订阅#
服务商配置一更新,手工改过的主配置就可能被重新下载的文件覆盖。所以我没有把 proxy-providers 和规则直接塞进订阅,而是单独建了 tailscale.stoverride:
name: Tailscale
desc: Tailscale 远程节点和分流规则
proxy-providers:
private-tailscale:
url: https://api.github.com/repos/你的用户名/你的私有仓库/contents/tailscale.yaml?ref=main
path: ./providers/private-tailscale.yaml
interval: 3600
headers:
Authorization: Bearer github_pat_你的只读Token
Accept: application/vnd.github.raw+json
X-GitHub-Api-Version: "2022-11-28"
proxy-groups:
- name: Tailscale
type: select
use:
- private-tailscale
proxies:
- DIRECT
rules:
- IP-CIDR,100.64.0.0/10,Tailscale,no-resolveyamlToken 用 Fine-grained 类型,只给这个私有仓库的 Contents: Read-only 权限。示例里的 Token 都是占位符,真实密钥不要提交到公开仓库,也不要发到聊天记录里。
如果 GitHub 直连不稳定,还要让更新请求走已有的代理组:
rules:
- DOMAIN,api.github.com,Proxies
- DOMAIN,raw.githubusercontent.com,Proxies
- DOMAIN-SUFFIX,githubusercontent.com,Proxies
- DOMAIN-SUFFIX,github.com,Proxies
- IP-CIDR,100.64.0.0/10,Tailscale,no-resolveyaml第一次更新成功后,Stash 会把远程代理集写入 path 指定的缓存。之后 GitHub 临时打不开,也不至于马上丢掉节点。
真正卡住我的地方#
一开始我以为是 Auth Key、GitHub 或 DERP 中继的问题。节点在 Tailscale 后台明明显示在线,Stash 里却访问不了这些地址,实时日志也没有对应请求。
后来才发现,Stash 默认的“跳过代理”和“跳过路由”列表里包含了 Tailscale 使用的网段:
100.64.0.0/10text请求在进入规则引擎之前就被排除了,所以我写的这条规则根本没有机会匹配:
- IP-CIDR,100.64.0.0/10,Tailscale,no-resolveyaml把默认配置中针对 100.64.0.0/10 的跳过项移除后,访问才真正进入 Tailscale 策略组。这个坑很容易漏掉:配置看起来没问题,节点也在线,结果浏览器就是打不开。
如果使用 MagicDNS,也可以按域名分流:
- DOMAIN-SUFFIX,你的网络名.ts.net,Tailscaleyaml不过我最终仍保留了 IP 网段规则,因为家里的服务有些是直接通过 Tailscale IP 访问的。
怎么确认配置真的生效#
不要用 Stash 的公网节点测速来判断 Tailscale。没有 Exit Node 时,测试 Google 或其他公网地址会报 no available exit node,这是另一件事。
我用实际服务测试,例如:
http://100.103.59.75/cgi-bin/luci
http://100.77.176.88:5000text然后看 Stash 的连接日志。正确的链路应该能看到请求命中 Tailscale,并使用 ts-main。如果完全没有日志,先检查跳过代理和跳过路由;如果已经命中 ts-main 仍然超时,再去查目标端口、防火墙和 Tailscale ACL。
官方 Tailscale App 和 Stash 内置的 Tailscale 还是两个独立节点,连接路径也可能不同。一个显示 Direct connection,另一个显示 DERP-relayed connection,速度自然会有差异。但 GitHub 只负责下载 YAML,不会参与后续的内网数据传输。
现在的使用方式#
服务商订阅继续按原来的方式更新。Tailscale 的节点、策略组和规则则由 Override 管理。访问 100.x.x.x 时走 Tailscale,其他流量继续按照原订阅分流。
这样我只需要开着 Stash,就能访问 Tailscale 隧道里的设备,也不用在 iOS 上同时维护两个 VPN 连接。对我来说,这比每次在 Stash 和官方 Tailscale App 之间切换省事多了。