Files
claude-egress-guard/README.zh-CN.md
T
yinyues2 6af4f23d89 feat: one-stop safe deployment and operation skill
- add references/safe-operation.md: credentials, client settings, secrets,
  blast radius, monitoring, incident response, update discipline
- SKILL.md, READMEs, AGENTS.md, llms.txt now present four parts: deploy,
  egress, operate, respond — gate remains the enforcement core
- version 1.3.0, installer pin updated
2026-10-27 01:52:28 +08:00

15 KiB
Raw Blame History

claude-egress-guard(中文说明)

ci

一站式 skill + 一键安装:在 Linux 上安全地部署和运行 Claude Code——从裸机到可用、 可审计的客户端,以及出问题时知道怎么处置。

在 VPS 上跑 Claude Code,最容易出问题的不是安装,而是出口泄漏:写在 /etc/profile.d 里的 claude() 函数只覆盖交互式 shell,Python、sh -c、 cron、systemd 和任何直接调用 /usr/bin/claude 的路径都会绕过去;代理中途挂掉时, 客户端还会悄悄从机房 IP 直连出去。

所以项目分成四块,只有一个是强制核心:

部分 覆盖什么 入口
部署 资格判断、主机基线、代理先稳定、装客户端但不启动、首次登录走闸门 preflight、zero-to-deployed.md
出口 固定出口、注入代理、内核白名单、更新自愈、失败不回落 install、verify --deep、drill、set-exit
运行 凭据、客户端设置、密钥卫生、影响范围、备份、监控 safe-operation.md
处置 出口变化、被要求验证、凭据泄漏、怀疑绕过 safe-operation.md §6

强制核心仍然是二进制闸门:claude 命令本身核验代理的真实出口地址、注入代理变量, 可选地把整个进程树关进内核级 IP 白名单。任何异常都拒绝启动,没有回落。另外三块存在 的意义,是让这道闸门按正确顺序装上,并且在第一周之后仍然有意义。


给 agent:从这里开始

这个仓库是给 agent(Hermes、Codex、Claude Code 或任何支持 skill 的运行器)消费的, 不只是给人读的 README。

# 把 skill 装进 agent 的 skills 目录(不需要 root,不改主机)
curl -fsSL https://raw.githubusercontent.com/yinyues2/claude-egress-guard/main/install.sh \
  | bash -s -- --skill-only --dest ~/.hermes/skills

然后对 agent 说:

用 claude-egress-guard 这个 skill:先问我代理入口、预期出口地址、国家、额外网段, 然后安装、跑 verify --deep、做一次故障演练,最后把 PASS/FAIL 行贴给我。

skill 里写清的约束(SKILL.md):

  • 只问 4 个事实——代理入口、预期出口地址、国家、额外白名单;其余从主机自己读,不重复追问;
  • 三档授权——只读诊断直接做;安装/验证/演练/卸载整计划批一次;可能切断操作者自身访问的操作当场确认;
  • 证据而非形容词——每条结论都要贴对应的 PASS 行,演练结果要记录,没输出不算通过;
  • 硬性禁止——不停 ssh/tailscale/docker 单元,不把 ALLOW_IPS 放大到 0.0.0.0/0,不为通过检查而关闭某一层,不碰账号/付款/身份核验。

配套文件:AGENTS.md(机器入口)、 references/agent-playbook.md (带判断点的分步手册)、llms.txt(给 LLM 工具用的链接索引)、 references/troubleshooting.md。


从零开始:新机器、还没注册过

下面的内容默认 Claude Code 已经装好并登录过。如果是从零开始,顺序决定第一次 部署安不安全:references/zero-to-deployed.md 给了九个阶段,并标明每一阶段由谁执行。

0  资格与环境判断:一人一号、一个固定出口            操作者
1  主机基线:时钟、时区、磁盘、IPv6 决策              agent
2  先把代理跑通并确认稳定,再谈注册                   agent
3  安装 Claude Code,装完不要启动                     agent
4  装闸门,verify --deep + drill                      agent
5  第一次登录:走闸门,在你自己的浏览器完成           操作者
6  首次设置:客户端里不要再单独设代理                 操作者 + agent
7  留证:记录证据、打开拒绝日志                        agent
8  日常:升级后 verify,出口漂移用 set-exit           agent
claude-egress-guard preflight --proxy http://127.0.0.1:1080 --exit-ip 203.0.113.10 --country JP

preflight 只读:检查平台、systemd、bash、时钟、时区、IPv6、磁盘、Node、 Claude Code,给了代理还会实测出口,最后输出 PASS/WARN/FAIL 和阻塞项数量。 出现 FAIL 就不要继续。

注册账号、付款、身份核验故意不做自动化:skill 明确禁止 agent 代办,runbook 会 告诉操作者在什么情况下应当停下来,而不是硬凑材料。


一键安装

curl -fsSL https://raw.githubusercontent.com/yinyues2/claude-egress-guard/main/install.sh \
  | sudo bash -s -- --proxy http://127.0.0.1:1080 --exit-ip 203.0.113.10 --country JP

这条命令会下载固定版本的发布包、打印安装计划、安装闸门、备份被替换的文件,最后自动跑 verify --deep。任何一层失败就停下并指出是哪一层,不会把装了一半的闸门当成功。

参数 含义
--proxy URL 本地 HTTP/mixed 代理入口(必填)
--exit-ip ADDR 代理出口的公网 IPv4(必填)
--country CC 要强制的两位国家码(可选)
--allow LIST 内核白名单里额外放行的网段,逗号分隔
--strict-net on|off 是否给进程树加内核白名单(默认 on)
--dry-run 只打印计划,不写任何东西
--yes 跳过确认提示(自动化用)
--ref REF 指定 tag 或分支(默认固定 tag)
--uninstall 移除闸门并从备份恢复
--skill-only 只把 skill 复制到 skills 目录

203.0.113.10 是文档专用地址(RFC 5737),请换成你代理实际报告的地址。回环和主机 IPv4 DNS 解析器会自动放行;代理上游、Tailscale 网段、内网 API 用 --allow 显式加。

给 root 之前先读一遍。 install.sh 是不混淆的纯 shell 脚本,下载的是固定 tag 的 压缩包,不是移动的分支。也可以先 clone 再 sudo ./install.sh ...。

卸载走同一条通道:

curl -fsSL https://raw.githubusercontent.com/yinyues2/claude-egress-guard/main/install.sh \
  | sudo bash -s -- --uninstall

装好之后是什么样

$ sudo claude-egress-guard verify --deep
PASS   config present: /etc/claude-egress-guard.conf
PASS   real binary executable
PASS   gate installed: /usr/local/bin/claude
PASS   gate mirrored: /usr/bin/claude
PASS   egress check: ok exit=203.0.113.10 country=JP
PASS   kernel jail enabled, allow list: 127.0.0.0/8 ::1/128 192.0.2.53/32
PASS   systemd-run available
PASS   IPv6 disabled system-wide
PASS   jail blocks direct egress
PASS   jail still allows the proxy path
---- 0 check(s) failed

每一行都是实测观察,不是「配置里写了」:最后两行是真的在白名单里发请求验证的。

claude(任意入口:shell、Python、cron、systemd、绝对路径)
  └─ /usr/local/bin/claude          闸门:核验出口 -> 注入代理 -> 内核白名单
       ├─ /usr/bin/claude           同一份闸门(npm 更新会改回符号链接,闸门自愈)
       └─ /opt/claude-real/claude   真身(符号链接,跟随包更新)
            └─ 你的代理          127.0.0.1:1080 -> 预期出口地址

每次启动的顺序:

  1. 读 /etc/claude-egress-guard.conf,缺失或不可读 → 拒绝(77);
  2. 如果包更新把 /usr/bin/claude 改回符号链接,先补回闸门;
  3. 问代理要真实出口地址和国家,不符/超时/HTTP 错误 → 拒绝(77),不重试、不回落直连;
  4. 把 ALL_PROXY/http_proxy/https_proxy(大小写)导出给客户端和所有子进程,NO_PROXY 只留回环;
  5. STRICT_NET=1 时,在临时 systemd scope 里以 IPAddressDeny=any + 白名单 exec, 子进程继承的是内核级限制,不是口头承诺。

诊断路径不碰网络:--version、--help、--ceg-check 在探测之前就短路返回。


保证什么

层 行为
出口核验 每次启动前核验地址和国家;不符、超时、报错一律退出码 77
代理环境 六个代理变量导出给客户端和全部子进程
内核白名单 整个进程树 IPAddressDeny=any,只放行回环、白名单和显式允许的网段
入口覆盖 /usr/local/bin/claude 和 /usr/bin/claude 都是闸门,真身放在 /opt/claude-real
自愈 包自更新改写的 /usr/bin/claude 会在下一次调用时补回
fail-closed 配置缺失、检查器缺失、代理不通、出口不符、国家不符、没有 systemd-run、非 root 且 STRICT_NET=1:全部拒绝
审计线索 LOG_REFUSALS=1 时每次拒绝写入 journald,tag claude-egress-guard
可回滚 被替换的文件都在 /var/lib/claude-egress-guard/backup/<时间戳>/,uninstall 恢复

环境要求与兼容性

项目 要求
系统 Linux + systemd 235+(IPAddressDeny= 需要)
Shell bash 4.3+
工具 curl、install、readlink、mktemp、awk、sed
权限 正式安装要 root;--prefix 可做无特权沙箱
Claude Code 已安装,npm 全局或官方安装器均可
代理 本地 HTTP 或 mixed 入口(只有 SOCKS 的话,客户端代理变量用不了)

已实测:Debian 13 / systemd 257 / Claude Code 2.1.296(npm 全局),代理在回环上的 住宅 HTTP 入口。CI 在 Ubuntu 24.04 上跑全套。

未验证、不支持:macOS/BSD、WSL、systemd 235 以下、非 root 用户 scope 下开 STRICT_NET=1、容器内的 Claude。

每次启动成本:一次经代理的 HTTPS 往返(视距离约 100-400 ms);--version/--help 不探测。


命令

命令 用途
preflight [--proxy URL --exit-ip ADDR --country CC] 新机器只读体检,含实时出口探测;--json 给工具用
install ... 打印计划、备份、安装(支持 --dry-run)
verify 静态检查 + 实时出口核验
verify --deep 额外证明「白名单挡住直连、仍放行代理」
status 查看当前策略(代理凭据打码)
set-exit --ip ADDR [--country CC] 跟随变化的出口:先探测,代理确实在该地址才改策略,再自动 verify
drill --service UNIT 停代理单元,证明闸门拒绝,再拉起并等待恢复
show <guard|check|config> 打印已安装的闸门/检查器/策略,便于审计
uninstall 从最新备份恢复并移除闸门

退出码:0 成功,1 校验失败,2 用法错误,77 闸门拒绝启动。


出口变了怎么办

住宅出口会漂。别手改配置,让闸门跟着走:

sudo claude-egress-guard set-exit --ip 198.51.100.23 --country JP

它先用候选地址探测代理,代理确实在该地址才原子改写 EXPECTED_IP/EXPECTED_COUNTRY (权限保持 0600),然后自动跑 verify;不爆料就拒绝,不会把没验证过的地址写进策略。

不知道新地址时先看一眼:

curl -4 -fsS --max-time 8 -x http://127.0.0.1:1080 https://www.cloudflare.com/cdn-cgi/trace

取输出里的 ip= 和 loc=。


拒绝日志

拒绝默认只出现在终端,没人盯着就看不见。开一次 journald 记录:

sudo sed -i 's/^LOG_REFUSALS=0/LOG_REFUSALS=1/' /etc/claude-egress-guard.conf

之后:

journalctl -t claude-egress-guard --since -24h

每条是 refused: <原因>。这决定了你是「我觉得没拒绝过」还是「它拒绝过 11 次,都在这」。


日常维护

事件 动作
npm i -g 或 Claude Code 自更新 sudo claude-egress-guard verify --deep(备用路径会自动补回)
代理出口变了 sudo claude-egress-guard set-exit --ip 新地址 --country CC
代理改走远程中转 用 --allow 加中转地址,再 verify --deep
不要内核白名单 设 STRICT_NET=0 再 verify(会出现 WARN),进程树出口不再强制
怀疑有绕过 status,然后看 /proc/<pid>/cgroup 里有没有 run-r...scope

不做什么

  • 不创建、不管理代理。 入口要你自己提供并保持存活。
  • 只闸一个二进制。 npx @anthropic-ai/claude-code 不经过 /usr/local/bin/claude, 因此不受保护;要么别这么用,要么自己再包一层。另一份装在别的前缀里的 Claude 同样不受保护。
  • 不是 VPN。 主机上其他服务、包管理器、其他用户不受影响,白名单只管 Claude 进程树。
  • 挡不住 root。 有 root 就能设 STRICT_NET=0、改配置或直接跑 /opt/claude-real/claude。 这是护栏,不是强制访问控制边界。
  • 不覆盖容器。 Docker/Kubernetes 的流量不经过主机的出口路径。
  • 不保证账号安全。 注册、付款、身份核验和平台判定都由账号本人承担;这个项目不用于规避服务商条款。

完整威胁模型见 SECURITY.md。


从源码手动安装

git clone https://github.com/yinyues2/claude-egress-guard.git
cd claude-egress-guard

# 一条命令,参数和 curl 版一致
sudo ./install.sh --proxy http://127.0.0.1:1080 --exit-ip 203.0.113.10 --country JP

# 或者直接驱动 CLI
sudo skills/claude-egress-guard/scripts/claude-egress-guard install \
  --proxy http://127.0.0.1:1080 --exit-ip 203.0.113.10 --country JP --dry-run

开发与测试

make check        # shellcheck + 44 项自测 + 泄漏扫描
make test         # 只跑沙箱自测(不需要 root,不联网)
make lint
make scan

自测在临时前缀里用假的 curl/id/logger/systemd-run 跑,不碰主机。


仓库结构

install.sh                  一键安装(下载固定 tag)
AGENTS.md                   agent 运行器的机器入口
llms.txt                    给 LLM 工具的链接索引
skills/claude-egress-guard/
  SKILL.md                  部署 skill 本体
  references/               playbook 与故障排查
  scripts/claude-egress-guard   安装/验证/演练/卸载 CLI
  scripts/guard-claude.sh   闸门本体(安装为 `claude`)
  scripts/egress-check.sh   出口检查器(可单独运行)
  scripts/selftest.sh       44 项沙箱断言
  templates/                策略文件示例
tools/leak-scan.py          拦截凭据、个人标识和非文档网段

许可、安全、隐私

Apache-2.0,见 LICENSE。安全模型与漏洞报告见 SECURITY.md, 数据收集见 PRIVACY.md(简短版:不收集任何东西,只探测你自己的代理)。