Skip to content

docs(usage): cliproxy-modes + cliproxy-egress-proxy#182

Merged
g1331 merged 5 commits into
masterfrom
docs/phase2-usage-cliproxy-modes-egress
May 23, 2026
Merged

docs(usage): cliproxy-modes + cliproxy-egress-proxy#182
g1331 merged 5 commits into
masterfrom
docs/phase2-usage-cliproxy-modes-egress

Conversation

@g1331
Copy link
Copy Markdown
Owner

@g1331 g1331 commented May 23, 2026

Summary

承接 #181,补齐 CLIProxyAPI 使用侧两篇姊妹文档:

  • docs/guide/usage/cliproxy-modes.md(外部 vs sidecar 选择)

    • cliproxy-instance-crud.ts:105-128validateInstanceAddress 分支为依据,阐明 managed / external 的真实差异(仅 external 走 SSRF 校验、managed 允许私有/loopback/元数据端点)。
    • 纠正 enabled 字段的常见误解——schema 与 UI 都有但任何路由 / 调度代码都不读它,关掉 enabled 不会停掉池上游流量。
    • 说明删除实例时 cliproxyInstanceId onDelete: set null 的副作用:上游记录保留,仍按 base_url 直发,不是优雅停机方式。
    • 模式切换的方向性约束。
  • docs/guide/usage/cliproxy-egress-proxy.md(CPA 出站代理)

    • 拆清三方责任:AutoRouter 自身不支持出站代理(proxy-client.ts:139 用 Node 原生 fetch,不读 HTTP_PROXY),CPA 容器是出站代理的唯一消费者。
    • 全局 CLIPROXY_PROXY_URL 完整配置链路:.envdocker-compose.cliproxy.yml:25cliproxy/docker-entrypoint.sh:34,67cliproxy/config.yaml.template:32-34;仅 managed 模式有效,external 模式下 AR .env 字段无作用。
    • 账号粒度 proxy_urlPATCH /api/admin/cliproxy/.../auth-accounts/:accountName,最终透传到 CPA PATCH /v0/management/auth-files/fields;立即生效,不需要重启。
    • 两者优先级、生效时机、校验方法、常见症状速查表。

Phase 2 使用侧进度:4/9 → 6/9(剩余 logs-stats / request-recording / troubleshooting)。

Test plan

  • pnpm exec vitepress build docs 本地构建通过,仅有 env 语言无 highlighter / 与本 PR 无关的 vueuse 注释告警。
  • pre-commit prettier hook 通过。
  • Pages 部署任务在 master 合入后自动触发,等待 GitHub Actions 校验。
  • 文档正文引用的所有源码路径与行号已基于当前 master 的 schema-pg.ts / cliproxy-instance-crud.ts / cliproxy-auth-account-service.ts / cliproxy-management-client.ts / proxy-client.ts 校对。

g1331 added 5 commits May 23, 2026 21:30
承接 PR #181 的 CLIProxyAPI 首批文档,补齐两篇姊妹篇:

- cliproxy-modes:以源码事实(cliproxy-instance-crud.ts 的 validateInstanceAddress
  分支)阐明 managed/external 的真实差异(SSRF 校验、URL 校验、地址填法),
  纠正 enabled 字段「关闭即停摆」的误印象(实际任何调度代码都不读 enabled),
  说明删除实例时上游记录 onDelete:set null 的副作用。
- cliproxy-egress-proxy:拆清三方责任——AutoRouter 自身不支持出站代理
  (proxy-client.ts 直接用 Node fetch),全局 CLIPROXY_PROXY_URL 通过
  docker-compose env → docker-entrypoint.sh → config.yaml.template 注入
  CPA 容器,账号粒度 proxy_url 经管理 API PATCH /v0/management/auth-files/fields
  下发;并说明两者优先级、生效时机差异、external 模式下 .env 失效。

Phase 2 使用侧进度 4/9 → 6/9,剩余:logs-stats、request-recording、troubleshooting。
P2 cliproxy-modes 删除行为:原文档说删除实例时外键 set null 会让上游记录
保留并继续按 base_url 直发;实际上 deleteCliproxyInstance
(cliproxy-instance-crud.ts:290-320) 在 SQL 删除前会先校验缓存账号与上游引用,
任一存在即抛 CliproxyInstanceInUseError,路由层返 HTTP 409。
onDelete: set null 仅在数据被绕过应用层删除时兜底。改为给出正确的三步
删除顺序(先上游、再账号、最后实例),并强调没有强制删除开关。

P2 cliproxy-modes SSRF 校验:原文档暗示 external 模式能拦截所有指向私有
地址的请求;实际上 isUrlSafe (upstream-ssrf-validator.ts:69-94) 在 hostname
不是 IP 字面量时直接 safe: true、不查 DNS。补一个 warning 说明 SSRF 防护
只对 IP 字面量生效,对 cpa.internal 这种内网域名即使解析到 192.168.x.x
也会通过;同时把校验差异表加一列「域名解析到私有 IP」以体现该限制。

P3 cliproxy-egress-proxy 配置路径:docker-entrypoint.sh:12 默认把渲染后的
config.yaml 写到 /CLIProxyAPI/config.yaml,而非原文档写的 /app/config/config.yaml。
更新校验命令路径,并提醒可以被 CLIPROXY_CONFIG_TARGET 覆盖。
「一图看懂」框图里仍写「external 拒绝私有/内网/loopback/元数据」,与下文的
SSRF 仅在 IP 字面量生效的 warning 矛盾。改为「拒绝私有/loopback IP 字面量」
以避免误导读者认为 cpa.internal 也会被拦。
P2 IPv6 SSRF:原 warning 把限制描述为「只对 IP 字面量生效」,但实测
new URL("http://[::1]/").hostname === "[::1]"(保留方括号),正则
/^[\d.:]+$/ 不匹配,IPv6 字面量同样走「普通域名」分支被 safe: true。
也就是说仅 IPv4 字面量会被拦,IPv6 字面量 + 域名都通过。修正 warning、
表格列分拆为「IPv4 字面量 / IPv6 字面量 / 域名解析到私有 IP」三列,明确
external 模式无法挡住 [::1] / [fc00::1] / [fe80::1] 等。

P2 账号删除步骤:原文档让用户去管理后台账号列表点「删除按钮」,但当前账号
子路由([accountName]/route.ts + status + upstream)都没导出 DELETE,
UI 也只有启停/编辑字段/映射上游三个动作,没有删除账号的 AutoRouter 操作。
改为说明唯一可行路径:在 CPA 侧删 auth-file → 触发 sync → 同步逻辑
(cliproxy-auth-account-service.ts:189-197)会把本地 cliproxy_auth_accounts
中 CPA 侧已不存在的行 db.delete 清掉;并补 CPA 不可达时直接操作表的兜底。

P3 cliproxy-first-time enabled 描述:first-time 文档字段表里仍写
「关闭后所有依赖该实例的池上游不可用」,与 modes 章节里「任何调度代码都
不读 enabled」直接矛盾。同步纠正为「仅作管理后台标识,不参与路由 / 调度」,
并引用 modes 文档作为详细说明。
P2 docker compose restart:原文档建议 `docker compose restart cliproxyapi`
让 CPA 重新读 .env,但实际上 restart 只是重启已有容器,env 仍是容器创建
时捕获的旧值。改为推荐用叠加文件再次 up -d(compose 检测到 env 变化会
自动重建容器),并给出显式 --force-recreate 的替代写法;同时同步「校验
方法」一节的引用文案。

P3 managed→external 校验:原文档说切到 external 时「内网地址」会被校验
失败。这与已经修正过的 SSRF 限制矛盾——isUrlSafe 不查 DNS、不拦 IPv6
字面量、不拦域名,只有 IPv4 字面量为私有/loopback/链路本地时才被拦。
http://cliproxyapi:8317 这种服务名能通过校验。改为:只有内网 IPv4 字面量
会被拦,但服务名/域名虽能通过校验,切到 external 后仍不可达,因此切 mode
时仍应同步改地址,「校验通过」不是判定能切的依据。
@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.14%. Comparing base (38186c3) to head (6c6e8bf).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #182   +/-   ##
=======================================
  Coverage   74.13%   74.14%           
=======================================
  Files         145      145           
  Lines       11043    11043           
  Branches     3832     3832           
=======================================
+ Hits         8187     8188    +1     
  Misses       1657     1657           
+ Partials     1199     1198    -1     
Flag Coverage Δ
verify 74.14% <ø> (+<0.01%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@g1331 g1331 merged commit 9ccf6d3 into master May 23, 2026
14 checks passed
@g1331 g1331 deleted the docs/phase2-usage-cliproxy-modes-egress branch May 23, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant