feat(linux): 提权 helper(systemd + 降权拉核 root 受管核)根治 TUN/更新反复输密码#247
Merged
Conversation
Linux TUN 此前每次开 TUN、每次软件更新后开 TUN 都弹 pkexec。根因:setcap 把 CAP_NET_ADMIN 挂在会被换核/更新替换的二进制 inode 上(security.capability xattr 随 inode 蒸发),故换核必重新提权。 方案(对齐 macOS launchd / Windows Service 的常驻 helper 模型): - helper-linux/:root systemd system service。SO_PEERCRED 鉴权 + 授权 uid 列表; start 时 setuid 回登录用户 + AmbientCaps=CAP_NET_ADMIN(+RAW/+BIND) 拉核 —— 能力挂 进程 ambient set 不挂文件,换核/软件更新天然免密。纯标准库。 - 核放 root 受管目录(/usr/local/lib/flowz/core),安装播种 + install-core(sha256 校验、socket 免密)更新,路径锁只跑锁定核 —— 不可篡改、一份共享、根除“任意自有 二进制白拿 CAP_NET_ADMIN”提权面。 - LinuxServiceHelper 实现 IPrivilegedHelper(socket 客户端 + pkexec 一次授权装/卸 systemd 服务 + installCore);ProxyManager 启/停接入 helper 分支(未装回退现有 setcap,零回归);CoreUpdateService install-core 泛化 Linux;ResourceManager root 受管核路径优先;设置页卡片 + promptHelperGate Linux 分支 + i18n 5 语。 - 安全:SO_PEERCRED 唯一鉴权 + 授权列表;config 属主==对端 uid;freeport/cleanup 限 对端 uid;IP 转发随核复位;SIGTERM 收割等在途;setuid 保留补充组。 验证:Ubuntu 26.04 VM 真机全链路通过 —— 非 root 经 helper setuid+ambient (CapAmb=cap_net_admin,cap_net_raw,cap_net_bind_service) 起核、auto_route 接管出网、 install-core 运行中原子热换、停核路由复位、卸载零残留。gate 全绿(tsc / eslint / go build+vet+test / jest 2352)。
承 root 受管核模型补齐两处(原始需求「避免软件更新反复输密码」的软件更新侧): 1. 应用更新后受管核自愈(§5 最低版本守卫接通 Linux root 核模型): ensureWritableCore(force) Linux 分支在「helper 就绪 + 受管核在位」时经 LinuxServiceHelper.installCore 免密刷新 root 受管核(镜像 darwin 受保护目录腿); 无 helper / 受管核不在位 → 退化刷 userData 兜底核(setcap 零回归);失败 warn 不抛 (版本闸门兜底)。修「探测 userData 核、实跑受管核」错位:getSingBoxPath / 刷新腿 / 路径锁三点共用 linuxManagedCoreUsable() 谓词,Linux 返回值恒解析 getSingBoxPath(), 使 §5 探测 / 诚实校验 / 实跑对准同一核(否则 install-core 失败会谎报成功、换核后版本记录读旧值)。 2. deb 更新一次授权说明框:deb 装 /opt 需 root、pkexec 弹 polkit 通用框(文案不可改) → installUpdate 顶部(停代理之前 = 取消真 no-op)对 deb 形态先弹 app 内说明框 (confirmDebElevation + i18n 五语),讲清「装软件一次授权 ≠ 每次开 TUN;helper 装一次 永久免密;想更新也免密改用 AppImage」。仅 deb 形态,AppImage / mac / win 零影响。 单测:core-reseed-linux-helper(受管核刷新 5 例)+ update-deb-confirm(门控/映射/取消 no-op 7 例) + linux-service-helper installCore 协议。gate 全绿(tsc 0 / eslint 0 / jest 2365 / go 未改)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
Linux TUN 模式此前每次开 TUN、每次软件更新后开 TUN 都弹 pkexec 授权框。
根因:
ensureCapabilities用setcap把CAP_NET_ADMIN挂在 sing-box 二进制 inode 的security.capabilityxattr 上,而换核 / 软件更新(ensureWritableCore的rename覆盖)换了 inode → caps 蒸发 → 必须重新提权。能力绑在“会被替换的文件”上是病根。方案
对齐 macOS(launchd daemon) / Windows(Service) 的常驻 helper 模型,把能力从“易变 inode”搬到“常驻进程 + 稳定 root 目录”:
helper-linux/(Go,纯标准库):root systemd system service。SO_PEERCRED鉴权 + 授权 uid 列表;start时setuid回登录用户 +AmbientCapabilities=CAP_NET_ADMIN(+RAW/+BIND)拉核 —— 能力挂进程 ambient set 不挂文件,换核/软件更新天然免密;核仍以登录用户跑,userData 的 config/cache/log 属主天然对。/usr/local/lib/flowz/core):安装播种 +install-core(sha256 校验、socket 免密)更新,helper 路径锁只跑锁定核 → 不可篡改、一份共享、根除“借 helper 给任意自有二进制赋 cap”的提权面。与 macOS 受保护目录同构。LinuxServiceHelper implements IPrivilegedHelper(socket 客户端 +pkexec一次授权装/卸 systemd 服务 +installCore);ProxyManager启/停接入 helper 分支,未装 helper 回退现有 setcap+pkexec,零回归;CoreUpdateServiceinstall-core 泛化 Linux;ResourceManagerroot 受管核路径优先;设置页 helper 卡片 +promptHelperGateLinux 分支 + i18n 5 语。安全
SO_PEERCRED为唯一鉴权(内核背书 uid)+ 授权 uid 列表(堵任意本地用户白拿 cap);config属主必须 == 对端 uid;freeport/cleanup限对端 uid(不跨用户杀);IP 转发随核 start/stop 复位;SIGTERM收割等在途(无孤儿);setuid 保留补充组。helper 本体CapabilityBoundingSet收窄留后续(P2)。验证
tsc0 错 /eslint0 问题 /go build+vet+test/jest2352 通过。setuid+ambient(CapAmb=cap_net_admin,cap_net_raw,cap_net_bind_service)起核 →auto_route接管出网 →install-core运行中原子热换(sha 匹配)→ 停核路由复位 → 卸载零残留。待办(不阻塞本 PR 的运行时正确性)
pkexec图形授权框 / 设置卡片 UX 手动点验(GUI 层,headless 未覆盖)。CapabilityBoundingSet/NoNewPrivileges收窄(P2)。