这次要解决的不是“能不能连上”,而是“在复杂网络环境里,能不能稳定、快速、单向、安全地连上”。
场景很常见:几台 Mac 和 iPad 已经通过 Tailscale 组成了一个私有网络。在同一个局域网里访问很快,但只要其中一台设备在外网,访问家里或办公室里的其他设备就明显变慢。与此同时,主力 Mac 上还开着 Surge,并且启用了全局系统代理和增强模式,结果 Tailscale 启动后,命令行工具的网络请求也开始异常。
最后的方案可以拆成三层:
- 用一台近源云服务器做 Tailscale 中继,减少跨境或远距离 relay 带来的时延。
- 用 Tailscale ACL 做单向访问控制,只允许主控设备访问被控设备。
- 在 Surge 里显式放行 Tailscale 相关流量,让增强模式不要抢走 Tailscale 的路由、DNS 和 relay endpoint。
下面的配置都已经脱敏。示例里的 IP、域名、用户名、主机名、配置文件名、目录路径都用占位符表示,不对应真实环境。
背景
Tailscale 的理想路径是点对点直连:两台设备都在同一个 tailnet 里,流量尽量直接走 UDP 打洞后的路径。
但实际网络里经常会遇到几类问题:
- 两端 NAT 类型复杂,直连不稳定。
- 一端在移动网络、校园网、公司网络或跨运营商环境里。
- 直连失败后,流量退回 relay。
- 默认 relay 节点不一定离两端都近,跨区域时延会明显变高。
这就是“局域网内很快,外网访问变慢”的根本原因:不是 Tailscale 本身慢,而是路径不理想。
一个务实的改法是:放一台地理位置和线路都更接近自己的云服务器,让它承担中继角色。云服务器的 CPU 和内存压力通常不大,重点反而是:
- 地域是否靠近主要使用地点。
- 公网带宽是否够。
- 流量计费是否可接受。
- 是否有稳定公网 IP。
- 云防火墙是否能只放行必要端口。
目标
这套方案的目标不是把所有设备互相打通,而是建立一个受控的远程维护通道:
- 主控 Mac 可以远程操作被控 Mac A 和被控 Mac B。
- 主控 Mac 可以通过 SSH 连接被控 Mac A 和被控 Mac B。
- 被控 Mac A/B 不能反向连接或控制主控 Mac。
- 被控 Mac A/B 之间也不能互相连接。
- 被控 Mac 只开启必要服务:远程登录和屏幕共享。
- Surge 开启全局代理和增强模式时,不影响 Tailscale 和命令行工具。
这类目标要靠两层控制一起完成:
- Tailscale ACL 控制网络层“谁能连谁、能连哪些端口”。
- macOS 自身控制服务层“哪些远程能力真的开启、由哪个系统账号认证”。
整体拓扑
可以把设备分成三个角色:
主控 Mac ├─ SSH / Screen Sharing -> 被控 Mac A ├─ SSH / Screen Sharing -> 被控 Mac B └─ SSH 管理 -> 云中继服务器
被控 Mac A └─ 只接受主控 Mac 访问指定端口
被控 Mac B └─ 只接受主控 Mac 访问指定端口
云中继服务器 └─ 只做 Tailscale 中继和必要 SSH 管理上面这段如果画成访问关系,就是:
图里橙色实线表示显式允许的访问,蓝色路径表示必要时经近源 relay 改善链路,红色虚线表示 ACL 应该拒绝的方向。这样读后面的 ACL JSON 时,就能直接对应到“允许主控访问被控,禁止反向和互访”这件事。
关键点是:中继服务器不是业务服务器,也不应该暴露被控 Mac 的 SSH 或屏幕共享到公网。被控设备仍然只在 Tailscale 私有网络内被访问。
云服务器怎么选
这类云服务器不需要很强的计算性能。更重要的是网络条件。
推荐优先级:
- 地域:选离自己主要使用地点近的区域。
- 带宽:中继节点的上下行会影响远程桌面体验,屏幕共享比纯 SSH 更吃带宽。
- 线路:同地域不等于同体验,运营商和云厂商线路会影响延迟与丢包。
- 公网 IP:需要稳定公网入口给 Tailscale relay 使用。
- 安全组:只放行 SSH 管理端口和 Tailscale relay 需要的 UDP 端口。
规格上,入门级 CPU/内存通常够用。真正需要留余量的是带宽和流量包。
中继服务器配置
中继服务器上只做几件事:
- 安装 Tailscale。
- 加入同一个 tailnet。
- 在 Tailscale 管理后台或对应配置里启用中继能力。
- 固定使用一个 UDP 端口作为 relay 入口。
- 在云防火墙里放行这个 UDP 端口。
- 保留 SSH 管理入口,但禁止密码登录。
示意配置:
cloud firewall: allow tcp <SSH_PORT> from <TRUSTED_SOURCE> allow udp <RELAY_UDP_PORT> from internet deny everything else
ssh server: PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes PermitRootLogin no这里有两个安全边界:
- 云服务器公网只暴露必要入口。
- 真正访问 Mac 的 SSH 和屏幕共享仍然走 Tailscale 私网,不暴露到公网。
Tailscale ACL:只允许单向控制
Tailscale 的 ACL 是这套方案的核心。不要依赖“我不告诉别人地址”这种弱假设,而是直接把允许关系写死。
下面是脱敏后的示意:
{ "hosts": { "mac1": "<MAC1_TAILSCALE_IP>", "mac2": "<MAC2_TAILSCALE_IP>", "mac3": "<MAC3_TAILSCALE_IP>", "relay": "<RELAY_TAILSCALE_IP>" }, "acls": [ { "action": "accept", "src": ["mac1"], "dst": ["mac2:22,5900", "mac3:22,5900", "relay:<SSH_PORT>"] }, { "action": "accept", "src": ["mac1", "mac2", "mac3"], "dst": ["relay:<RELAY_UDP_PORT>"] } ]}这个 ACL 表达的是:
- 主控 Mac 可以 SSH 到被控 Mac。
- 主控 Mac 可以用屏幕共享访问被控 Mac。
- 主控 Mac 可以 SSH 管理中继服务器。
- 被控 Mac 不具备访问主控 Mac 的授权。
- 被控 Mac 之间没有互相访问的授权。
如果环境更复杂,可以用 tag 或 group 代替具体 host,但原则不变:显式允许最小集合,不写宽泛的互通规则。
macOS 上应该开什么
被控 Mac 上建议只开启两个服务:
- 远程登录:用于 SSH。
- 屏幕共享:用于图形界面远程控制。
其他不需要的共享能力建议关闭:
- 远程管理。
- 文件共享。
- 远程 Apple 事件。
- 内容缓存。
- 蓝牙共享。
如果只需要命令行,甚至可以先不开屏幕共享。图形界面远程控制是更高权限的入口,应该在确实需要时再开启。
SSH 侧建议:
- 优先使用密钥登录。
- 不使用弱密码。
- 限制可登录用户。
- 保持 macOS 用户账号本身有强密码。
屏幕共享侧建议:
- 使用系统账号认证。
- 不把 VNC 密码当成唯一保护。
- 不把 5900 端口暴露到公网。
SSH alias:让日常使用简单
ACL 和系统服务配置好以后,可以在本机 SSH 配置里加 alias,避免每次输入长地址。
示意:
Host remote-mac-a HostName <MAC2_TAILSCALE_IP> User <REMOTE_USER> IdentityFile <PRIVATE_KEY_PATH> IdentitiesOnly yes
Host remote-mac-b HostName <MAC3_TAILSCALE_IP> User <REMOTE_USER> IdentityFile <PRIVATE_KEY_PATH> IdentitiesOnly yes
Host tailscale-relay HostName <RELAY_PUBLIC_IP> User <RELAY_USER> IdentityFile <PRIVATE_KEY_PATH> IdentitiesOnly yes之后日常命令会变成:
ssh remote-mac-assh remote-mac-bssh tailscale-relayalias 只是易用性配置,不是安全边界。真正的安全边界仍然是云防火墙、SSH 服务配置、Tailscale ACL 和 macOS 本机服务权限。
Surge 为什么会和 Tailscale 冲突
Surge 的系统代理通常只影响显式走代理的应用;增强模式则更进一步,会接管更多系统流量,包括部分命令行工具、DNS、虚拟网卡路径。
这时 Tailscale 需要的几类流量可能被误伤:
- Tailscale 私网地址段。
- Tailscale 的 MagicDNS 解析。
- 到自建 relay 公网入口的 UDP 流量。
- Tailscale IPv6 ULA 地址段,如果启用了 IPv6。
结果就是:Tailscale 本来应该直连或走 relay 的流量,被 Surge 当成普通外网流量处理,进而导致 SSH、屏幕共享、命令行请求出现异常。
解决思路不是关掉 Surge,而是给 Tailscale 留出直连通道。
Surge 配置:给 Tailscale 留出直连通道
需要在主配置里处理三类规则。
第一,skip-proxy 里加入 Tailscale 相关地址、MagicDNS 后缀和中继公网入口:
[General]skip-proxy = <LAN_CIDRS>, <TAILSCALE_CGNAT_CIDR>, <TAILSCALE_DNS_IP>, <TAILSCALE_MAGICDNS_SUFFIX>, <RELAY_PUBLIC_IP>第二,增强模式下要排除 Tailscale 路由:
[General]tun-excluded-routes = <LAN_CIDRS>, <TAILSCALE_CGNAT_CIDR>, <TAILSCALE_DNS_IP>/32, <RELAY_PUBLIC_IP>/32, <TAILSCALE_IPV6_ULA_CIDR>第三,在 [Rule] 顶部放直接规则,让它们优先于更宽泛的代理规则:
[Rule]# Tailscale directIP-CIDR,<TAILSCALE_CGNAT_CIDR>,DIRECT,no-resolveIP-CIDR,<TAILSCALE_DNS_IP>/32,DIRECT,no-resolveIP-CIDR,<RELAY_PUBLIC_IP>/32,DIRECT,no-resolveIP-CIDR6,<TAILSCALE_IPV6_ULA_CIDR>,DIRECT,no-resolveDOMAIN-SUFFIX,<TAILSCALE_MAGICDNS_SUFFIX>,DIRECT规则顺序很重要。Surge 通常是按顺序匹配,Tailscale 直连规则应该放在 AI、流媒体、国外代理、默认代理等宽泛规则之前。
如果配置来自远程订阅,还要注意订阅刷新可能覆盖本地修改。更稳妥的做法是使用本地主配置或 wrapper,把订阅节点和自定义规则分开管理。
修改配置前后的操作顺序
这类网络配置最怕“边改边猜”。推荐固定流程:
- 确认当前正在使用的 Surge 主配置。
- 备份原配置。
- 只修改 Tailscale 相关行,避免碰代理节点和已有分组。
- 用 Surge CLI 或 GUI 校验配置。
- reload 配置。
- 清理 DNS 缓存。
- 分别验证命令行外网、SSH、屏幕共享。
示意命令:
surge-cli --check <SURGE_PROFILE_PATH>surge-cli reloadsurge-cli flush dns连接性验证:
curl -I <CONNECTIVITY_TEST_URL>ssh <REMOTE_MAC_ALIAS> hostnamenc -vz <REMOTE_MAC_TAILSCALE_IP> 5900测试时不要只看“能不能打开网页”。这个场景至少要验证四件事:
- 命令行请求能正常出网。
- SSH 能连上被控 Mac。
- 屏幕共享端口能连上被控 Mac。
- ACL 期望禁止的反向连接仍然不能连。
安全边界
这套方案里有几个容易混淆的边界。
第一,云服务器不是跳板机。它的主要职责是改善 Tailscale relay 路径,不应该成为所有设备的公开入口。
第二,Tailscale ACL 不是替代系统权限。ACL 允许访问 22 或 5900,只代表网络层可达;是否真的能登录,还要看 SSH key、系统账号、屏幕共享权限。
第三,Surge 的 DIRECT 不等于“不安全”。这里的 DIRECT 是让 Tailscale 私网流量回到 Tailscale 自己的网卡和 relay 机制,而不是绕过安全控制。
第四,配置里不要写真实秘密。SSH key、代理节点密码、真实域名、真实主机名、真实 IP、真实本机路径都不应该出现在可分享的文档里。
取舍
这个方案的收益很明确:
- 外网远程访问路径更近,延迟更稳定。
- macOS 远程登录和屏幕共享都可以保留在私网里。
- 主控和被控之间是单向授权。
- Surge 增强模式可以继续使用,不必为了 Tailscale 关掉全局代理。
代价也存在:
- 多了一台云服务器,需要维护安全补丁和密钥。
- relay 带宽和流量会产生成本。
- 云厂商线路质量会直接影响体验。
- Surge 订阅刷新可能覆盖本地规则,需要把自定义规则放在稳定位置。
所以这不是“所有人都应该上云中继”的方案,而是适合下面这种情况:
- 经常从外网远程访问自己的多台设备。
- 默认 Tailscale 路径延迟较高。
- 希望远程桌面和 SSH 都走私网。
- 本机同时长期运行 Surge、Clash、VPN 或其他代理工具。
最终清单
可以用这份清单复盘一次配置是否完整:
- 云服务器已加入 tailnet。
- 云服务器只放行 SSH 管理端口和 relay UDP 端口。
- 云服务器禁用了 SSH 密码登录。
- Tailscale ACL 只允许主控 Mac 访问被控 Mac 的 22 和 5900。
- 被控 Mac 之间没有互访权限。
- 被控 Mac 不能反向访问主控 Mac。
- 被控 Mac 只开启远程登录和屏幕共享。
- 主控 Mac 配好了 SSH alias。
- Surge 主配置已备份。
- Surge 已排除 Tailscale 私网、MagicDNS 和 relay 公网入口。
- Surge 直连规则位于
[Rule]顶部。 - 配置校验通过。
- 配置 reload 后清理了 DNS 缓存。
- 命令行出网、SSH、屏幕共享都通过验证。
远程访问的稳定性,通常不是靠单个工具解决的。Tailscale 负责身份和私网,云中继负责路径质量,ACL 负责最小授权,Surge 则需要明确让出 Tailscale 的网络空间。把这四件事分清楚,整个系统才会既快又可控。