这是一个通用的 macOS Privileged Helper,用于让桌面应用安全地执行需要 root 权限的网络操作(代理管理、进程控制等)。
- 仅监听本地 Unix Socket (
/var/run/com.privileged-helper.sock) - Token 认证:所有 API 必须携带
X-Helper-Token - 调用方约束:读取 Unix Socket peer 的 uid/pid/path,仅允许策略文件中的调用方
- 命令白名单:仅允许 networksetup / route 的受限子命令与参数
- 参数收紧:代理地址仅允许 loopback(
127.0.0.1/::1/localhost)
- 失败回滚:修改代理前先读当前值,执行失败自动恢复
- 幂等语义:目标状态已满足时返回
ok=true, code=NOOP - 异常自愈:周期性比对并恢复 state.json 的目标状态
- 基线恢复:首次变更前保存 baseline.json,支持一键恢复
- 并发互斥:同一 network service 串行执行,避免竞态覆盖
- 防刷限速:按调用方做窗口限流(过载返回
RATE_LIMITED) - 失败熔断:连续失败触发临时封禁(返回
CIRCUIT_OPEN) - 漂移告警:自愈前记录 expected/current 差异到审计日志
- 安装原子升级:失败自动回滚到旧二进制与旧 plist
- 卸载安全:卸载前自动尝试恢复 baseline,避免残留代理
- 审计日志:记录调用方身份、动作、结果、状态快照
POST /v1/proxy/enable: 开启系统 HTTP/HTTPS/SOCKS 代理POST /v1/proxy/disable: 关闭系统 HTTP/HTTPS/SOCKS 代理GET /v1/proxy/status: 查询系统代理状态(HTTP/HTTPS/SOCKS/AutoDiscovery/PAC)GET /version: 获取 helper 版本信息(version/commit/buildTime/launchedAt)GET /health: 健康检查GET /v1/startup/check: 启动检查(路径、权限、策略等)
make build或直接运行:
bash scripts/build-helper.sh ./build/privileged-helpersudo bash scripts/install-helper.sh ./build/privileged-helper安装后:
- 二进制:
/Library/PrivilegedHelperTools/com.privileged-helper - 启动项:
/Library/LaunchDaemons/com.privileged-helper.plist - Socket:
/var/run/com.privileged-helper.sock - Token:
/Library/Application Support/PrivilegedHelper/token - 调用策略:
/Library/Application Support/PrivilegedHelper/policy.json - 期望状态:
/Library/Application Support/PrivilegedHelper/state.json - 基线状态:
/Library/Application Support/PrivilegedHelper/baseline.json - 版本信息:
/Library/Application Support/PrivilegedHelper/version.json - 运行日志:
/var/log/privileged-helper.log - 审计日志:
/var/log/privileged-helper-audit.log
sudo bash scripts/uninstall-helper.sh说明:卸载脚本会停止服务并删除已安装的二进制/plist。
TOKEN="$(cat '/Library/Application Support/PrivilegedHelper/token')"
# 开启系统代理(service 可省略,自动解析主网络服务)
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-X POST http://localhost/v1/proxy/enable \
-d '{"service":"Wi-Fi","host":"127.0.0.1","port":7890}'
# 可选:返回一次性状态快照,避免 GUI 再请求 /v1/proxy/status
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-X POST "http://localhost/v1/proxy/enable?withStatus=1" \
-d '{"service":"Wi-Fi","host":"127.0.0.1","port":7890}'
# 关闭系统代理
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-X POST http://localhost/v1/proxy/disable \
-d '{}'
# 查询系统代理状态(service 可选)
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-X GET "http://localhost/v1/proxy/status?service=Wi-Fi"
# 查询版本
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-X GET http://localhost/version
# 健康检查
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-X GET http://localhost/health
# 启动检查
curl --unix-socket /var/run/com.privileged-helper.sock \
-H "X-Helper-Token: ${TOKEN}" \
-X GET http://localhost/v1/startup/checkservice:网络服务名称(如 Wi-Fi、Ethernet),可省略(自动检测主网络服务)host:代理地址,仅允许 loopback(127.0.0.1/::1/localhost)port:HTTP 代理端口httpPort/httpsPort/socksPort:分别指定 HTTP/HTTPS/SOCKS 端口mixedPort:混合端口(三种代理都使用该端口)- 支持连字符写法:
http-port、https-port、socks-port、mixed-port
- 鉴权 token 使用常量时间比较,降低时序侧信道风险
- 默认策略仅放行当前用户 UID 的调用方
- token 与 unix socket 默认采用 root + ACL(按 allowedUIDs 下发最小权限)
- 启动前仅清理已有 Unix Socket;若路径存在但不是 socket 文件则拒绝启动(防误删/路径投毒)
- 请求调用方需可解析 peer pid(SO_PEERPID),不可解析则拒绝
全局配置文件,用于自定义 helper 的基础路径和标识。此文件需手动创建,优先级高于代码中的默认值。
配置项:
bundleId:Bundle ID(如com.privileged-helper)helperSystemBase:系统基础目录(如/Library/Application Support/PrivilegedHelper)socketPath:Unix Socket 路径(如/var/run/com.privileged-helper.sock)logPath:日志文件路径(如/var/log/privileged-helper.log)auditPath:审计日志路径(如/var/log/privileged-helper-audit.log)
示例配置:
{
"bundleId": "com.privileged-helper",
"helperSystemBase": "/Library/Application Support/PrivilegedHelper",
"socketPath": "/var/run/com.privileged-helper.sock",
"logPath": "/var/log/privileged-helper.log",
"auditPath": "/var/log/privileged-helper-audit.log"
}详细说明请参考 配置文档。
调用策略配置,包含:
allowedUIDs:允许调用该 helper 的用户 UID 列表allowedClientPathPrefixes:允许调用的客户端路径前缀列表enableCallerPathConstraint:是否启用调用方路径约束
期望状态配置,记录:
proxy:期望的代理配置(按服务名)dns:期望的 DNS 配置(按服务名,当前未实现)tun:期望的 TUN 配置(当前未实现)
基线状态配置,首次修改前自动保存,用于恢复。
调试配置,包含:
extraAllowedCoreBinaries:额外的允许二进制路径extraAllowedClientPathPrefixes:额外的允许客户端路径前缀enableConsoleCurl:是否允许控制台 curl 调试
- 若要对接 Apple 官方授权安装链路,建议使用
SMJobBless+ 签名校验(Team ID / Requirement)。 - 若 GUI 和 helper 分离,建议改为 NSXPC 并在 helper 侧加 audit token 校验调用方签名。
- 按实际 App 安装位置维护
policy.json中的allowedClientPathPrefixes,避免误拦截。 - 版本兼容测试建议包含 macOS 12/13/14/15(尤其
networksetup输出差异)。
本项目采用 GNU GPL v3.0(GPL-3.0-only)开源许可,详见仓库根目录 LICENSE。
编辑 scripts/install-helper.sh 和 scripts/uninstall-helper.sh,将 com.privileged-helper 替换为你的 bundle identifier。
本 helper 已预留扩展点:
state.json中的dns和tun字段- 新的 HTTP 路由在
main.go的routes()方法中添加 - 新的系统命令调用需在
allowedCommand()中添加白名单
查看日志:
tail -f /var/log/privileged-helper.log
tail -f /var/log/privileged-helper-audit.log启用调试模式,编辑 /Library/Application Support/PrivilegedHelper/debug-config.json:
{
"extraAllowedCoreBinaries": [],
"extraAllowedClientPathPrefixes": [],
"enableConsoleCurl": true
}