10 月 25 日,安全研究员 Erica Windisch(Cyberdione Labs)发布了针对 Tailscale 与 headscale 的安全评估报告 Tailworm,列出 11 项发现,其中最严重的一组落在 Tailscale SSH 的 Unix 套接字转发上:一台已获准接入 tailnet 的设备,可以越过策略分配给它的权限,对网络内其他服务器执行 root 级操作。三天后的 10 月 27 日,Tailscale 发布 v1.104.4,四份安全公告 TS-2026-014 至 TS-2026-017 随该版本落地。
三天时间线
- 10 月 25 日:Tailworm 报告公开发布,覆盖 tailscaled v1.104.2、自托管控制面 headscale v0.29.5、两者共同依赖的 gliderssh 库,以及实验性的 conn25 应用连接器特性。测试窗口为 10 月 22 日至 24 日,全部发现都在未修改的正式发布软件上以实验室复现验证。
- 10 月 26 日:Tailscale 在官方博客发布调查更新,确认「多数已识别的问题涉及提权」,同时说明这项调查基于此前已在进行的工作。官方未建议所有用户关闭 Tailscale SSH,目标是 10 月 27 日放出补丁版本。
- 10 月 27 日:v1.104.4 发布,修复落在 tailscale/tailscale 与 tailscale/gliderssh 两个公开仓库;工程副总裁 Mike Shaver 也在 Reddit 公开回应了报告与修复进展。
漏洞的土壤:以 root 运行的 tailscaled
理解这组漏洞需要先看 Tailscale SSH 的架构。传统 OpenSSH 采用特权分离:root 主进程监听端口,每个会话降权到对应的登录用户。Tailscale SSH 把 SSH 服务器直接嵌进 tailscaled 守护进程,而 tailscaled 以 root 运行。Tailworm 报告对这一设计的评价写在研究者笔记里:开源版 tailscale 和 headscale 的设计选择「用高特权进程取代了采用特权分离的守护进程(如 OpenSSH),移除了多层认证」。
认证模型同样特殊。Tailscale SSH 不做用户级认证,SSH 协议的认证阶段以 method none 直接通过:WireGuard 层已经用密码学方式识别了设备,策略评估的对象是设备身份,授权内容是一条「源设备到目标设备、含目标账号」的规则。报告总结了两个后果:攻击者不需要任何凭据材料,只需要在任意一台被策略允许的设备上立足;同一设备上任何用户的恶意软件,都以该设备的完整授权说话。
问题出在转发功能与 root 进程的组合上。SSH 的本地转发(ssh -L)和远程转发(ssh -R)可以携带 Unix 套接字目标,tailscaled 对套接字路径做词法校验,但校验之后的文件操作以 root 执行。TS-2026-014 的公告原文描述了后果:这三个问题叠加后,路径白名单不再构成安全边界,已认证的连接方获得了通往节点上 root 专属 Unix 套接字的通路,典型目标包括 /run/docker.sock 和 tailscaled 自己的本地 API 套接字。
攻击链三段拆解
第一段:ssh -L 以 root 拨号。 本地转发建立后,tailscaled 对目标 Unix 套接字的拨号以 root 身份完成。普通用户的 SSH 会话因此可以读写 root-only 套接字,直接触达系统内最敏感的本地接口。
第二段:ssh -R 替换 root 拥有的套接字。 远程转发的 BindUnlink 行为会先解除(unlink)已有套接字再绑定攻击者的监听器。tailscaled 以 root 执行这一操作,等于允许普通会话顶替 root 专属服务的套接字路径、冒充该服务。对以命令报文驱动的守护进程,报告验证了「一条构造消息即可拿到 uid=0」的直接 root 执行;对 Docker 套接字,验证内容包括明文注册表凭据捕获(观察到明文 POST),以及未固定标签的镜像拉取控制。
第三段:TOCTOU 竞态绕过路径白名单。 词法校验发生在检查时,而 unlink/bind 与拨号发生在使用时,内核在使用阶段会重新解析路径。报告在攻击者自己的 SSH 会话内运行了一个 rename(2) 竞态循环,路径状态翻转速度约每秒 17 万次,足以稳定赢得检查与使用之间的时间窗。竞态的两个方向都有实测结果:bind 侧把 root 拥有的在用控制套接字换成了攻击者的监听器;dial 侧以 root 凭据拨入目标套接字。

实验室里的完整演示
报告的分量来自端到端复现,而非停留在理论推导:
- Docker 链路(GAP-A1):通过 ssh -L 连向 /run/docker.sock 的一条竞态保活连接,在未经修改、由 systemd 管理的 Docker 守护进程上完成了容器创建(Binds=/:/host)、启动与执行,容器内 uid=0 且宿主根文件系统已挂载。在启用 SELinux 强制模式的测试发行版上,宿主文件读取被 MLS 策略拦截;没有等效约束的发行版允许完整的宿主读写。
- Kubelet 可达性(GAP-A2):向 kubelet 套接字桩发起 111 次竞态拨号,每个被接受的连接都以 uid=0、comm=tailscaled 出现。报告评价:向 kubelet API 交付 root 凭据是机械性操作,实际滥用未执行。
- 控制面 CLI 捕获(GAP-A3):预认证崩溃循环加套接字重绑,劫持的套接字以明文 h2c 捕获了 headscale 管理 CLI 的全部流量。
- 完整入网链路:实验室虚拟机内演示了持续至少 4 分钟的套接字重绑、HTTP 感知中间人、authkey 的字节级捕获,随后在另一台节点上使用该 authkey,以受害者身份把一个恶意节点加入了 tailnet。对启用 Tailnet Lock 的场景,禁用密钥与签名密钥材料同样在传输中被捕获,实际禁用操作未执行。
初始立足点的来源报告也写得很克制:被利用的 Web 应用、恶意构建依赖、钓鱼植入、供应链污染或被盗的身份凭据。Tailscale 不制造立足点;报告的判定在于,mesh 网络会把一个普通立足点以机器速度转化成全网的特权访问,因为设备间的通路由「假定端点可信」的策略授予,而特权进程的操作可以从无特权会话触达。
四份公告与修复边界
四份公告都指向 1.104.4:
- TS-2026-014:Unix 套接字转发提权(对应发现 1 至 3)。修复方式是从根上换掉执行身份:转发相关的拨号、绑定、解除操作改以会话认证用户的身份执行。
- TS-2026-015:会话内存耗尽。持续发送窗口变更消息和追加环境变量可让 tailscaled 内存无界增长,连接断开后也不释放,最终 OOM。tailscaled 承载节点全部网络状态,它被杀等于该节点所有 Tailscale 连接中断。
- TS-2026-016:tailscale serve 的 Unix 后端。TCP 转发到 Unix 套接字缺少 HTTP 路径上的守卫并以 root 拨号,官方对影响的描述是「完整的节点接管」;另一子项是符号链接守卫只在配置重载时执行,配置后替换路径即可绕过。修复后 serve 限制了对 tailscaled 套接字的 TCP 转发,并在每次拨号时重新校验后端目标。
- TS-2026-017:HTTP/2 共享 serve 上下文的竞态。同一 TLS 连接上的并发流共享一个上下文,能力字段跨 mount 渗漏,可能导致 A 应用的授权判定读到 B 应用的能力头。修复改为按请求派生能力上下文。

修复边界需要单独核对。按 Tailworm 报告 10 月 28 日快照的缓解矩阵:发现 1 至 3、5、7、8、11 已随 v1.104.4 修复;发现 4(conn25 连接器的出口选择问题)的修复还是开放状态的 PR #22003,局域网与互联网出口不受限;发现 6 的客户端侧已修,headscale 服务端侧的修复待定;发现 9(funnel 授权执行)属威胁模型层面的发现,快照时无修复;发现 10 是配置开关的文档化说明,官方无变更计划。启用 conn25 实验特性或依赖 funnel 权限位的部署,需要单独跟进。
headscale 用户
漏洞组件是 tailscaled 客户端守护进程,与控制面无关,自托管 headscale 的用户同样暴露在发现 1 至 3 之下。headscale v0.29.5 有一点加重因素:SSH 转发在该环境下是自动授权的;安全社区的分析还指出该版本缺少关闭转发的开关。客户端升级到 v1.104.4 可以拿到发现 1 至 3 的修复;headscale 自身的资源耗尽类问题(发现 6)等待服务端侧修复。
行动清单
- 升级。所有启用 Tailscale SSH 的节点升级到 v1.104.4 或更新版本。
- 关掉不需要的转发。在 tailscaled 的服务环境里设置 TS_SSH_DISABLE_FORWARDING=1 并重启服务,不关闭 Tailscale SSH 本身也能切断这组最严重的通路。systemd 部署可用 drop-in 配置:
# /etc/systemd/system/tailscaled.service.d/no-forwarding.conf
[Service]
Environment=TS_SSH_DISABLE_FORWARDING=1执行 systemctl daemon-reload 与 systemctl restart tailscaled 生效。
- 收紧 SSH 策略。复查 ACL 里的 SSH 规则,只保留必要的源设备与目标账号;暂时无法升级的节点,先收窄可连接的用户与设备范围。
- 清理连接器授权。conn25 的出口选择问题修复未落地,移除不必要的连接器授权,出口方向按目的地加白或默认拒绝。
检测与事后处置
补丁前的检测手段报告给出了可部署的清单:对套接字 unlink、bind、chmod 做对象级 auditd 审计;对候选目录的持续 rename 循环(报告实测约每秒 10 的 5 次方量级)做速率告警;一个本应为 0600 权限的套接字若出现 0755,是竞态获胜绑定的取证签名;对 authkey 的签发与使用做窗口外告警;headscale 侧监控常驻内存与注册延迟。
事后处置的要点容易被忽略:在控制面删除设备,重装系统不构成处置。节点身份是状态文件里的密钥材料,报告演示了把状态文件复制到其他硬件即可重建该节点的身份,控制面照单接受。重装只清掉了被攻陷主机上的一份拷贝,被盗的密钥在设备被删除或密钥过期前始终有效。root 失陷之后应按已外泄处理:删除设备(同时吊销机器密钥与节点密钥)、轮换该主机可触及的 authkey 与凭据;若 Tailnet Lock 的签名节点被攻陷,轮换锁本身,并用 GitOps 历史核查路由、DERP 映射与审批人的未授权变更。
披露节奏与设计教训
Tailworm 公开发布与补丁发布只隔了两天,披露窗口短得罕见。研究者在报告里给出了理由:「快速让这些缺陷被知晓,将加速受影响设备的修复。这些漏洞并非研究者引入,它们只是被发现了,而且是被低成本地发现的。」Hacker News 的讨论中也有评论者对公开发布前仅约两小时的预告窗口提出异议,Tailscale 工程师则在同一线程里邀请持有未公开发现的研究者走 [email protected] 通道。Tailscale 的调查更新把这次修复描述为「基于已在进行的工作加速推进」,双方的说法都保留在了公开记录里。
对使用者的教训落在三件具体的事上:版本号是不是 1.104.4 以上、转发开关是否已按需关闭、SSH 策略里是否还留着多余的授权。工具选型层面的分歧也已写在公开记录里:研究者认为以 root 单进程承担 SSH、serve、funnel 多重职能的设计放弃了纵深防御;v1.104.4 的修复方向与这份批评指向同一处,转发相关的拨号、绑定、解除操作回归认证用户身份执行,路径白名单重新成为边界。
来源:
- Tailworm 安全评估报告:https://tailworm.com/
- Tailscale 官方调查更新:https://tailscale.com/ssh-investigation-update
- Tailscale 安全公告 TS-2026-014 至 TS-2026-017:https://tailscale.com/security-bulletins
- Hacker News 讨论:https://news.ycombinator.com/item?id=50264857