security: 配置 Provider 出站端口白名单 (#55)

This commit is contained in:
ila
2026-08-25 11:59:53 +08:00
parent 841d396cdf
commit b0ecbabdf0
10 changed files with 134 additions and 14 deletions
+3 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Architecture-and-Code-Map
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Architecture-and-Code-Map.-
wiki_revision: 47afee496f6d4105e51cddb47e9ba9dae7380293
synchronized_at: 2026-08-25T01:52:58Z
wiki_revision: 84986fd08a4814ac64fd61d7ab5c02a06d815dc8
synchronized_at: 2026-08-25T03:56:20Z
<!-- gitea-wiki-mirror:end -->
# 架构与代码地图
@@ -198,7 +198,7 @@ ClaimLease(只取得租约并记录 lease 事件)
| `images_edits` | OpenAI-compatible `/images/edits` multipart | image_edit;至少一张图且恰好一个 primary |
| `gemini` | 固定 `models/{url-escaped-model}:generateContent` | 按 capability 发送 text/inlineData,读取 text/inlineData;不接受配置覆盖 endpoint |
`auth_type` 只允许 `none`、`bearer`、`x-goog-api-key`,不允许管理员输入任意认证 header。`extra_body` 只合并白名单字段,不能覆盖 URL、认证、model、Prompt、输入、超时、输出数量或响应上限。四种协议的请求、重定向和结果下载全部复用 DNS 后、Dial 前 SSRF 拦截;Bearer 不跨 origin 转发,响应正文与密钥不写日志/attempt/audit。
`auth_type` 只允许 `none`、`bearer`、`x-goog-api-key`,不允许管理员输入任意认证 header。`extra_body` 只合并白名单字段,不能覆盖 URL、认证、model、Prompt、输入、超时、输出数量或响应上限。四种协议的请求、重定向和结果下载全部复用 DNS 后、Dial 前 SSRF 拦截;Bearer 不跨 origin 转发,响应正文与密钥不写日志/attempt/audit。出站端口由 `CHORUS_PROVIDER_ALLOWED_PORTS` 显式控制,默认仅 `80,443`;Portal worker 与管理端连通性探针使用同一白名单。扩展端口不会放宽 IP、DNS、重定向或结果 URL 校验。
#### 管理端契约
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Local-Development-and-Verification
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Local-Development-and-Verification.-
wiki_revision: 635183e2476eaa41109fd2b28886a89462b9ed81
synchronized_at: 2026-08-25T03:21:32Z
wiki_revision: 9931fb7acc36ebcbcc122bcbd528887b970efb10
synchronized_at: 2026-08-25T03:56:31Z
<!-- gitea-wiki-mirror:end -->
# 本地开发与验证
@@ -231,7 +231,7 @@ go run ./portal
| 成功但内容不对 | rendered_prompt 与 prompt template 版本 |
| 400/401 尝试多家 | retryable 实现错误 |
| 文件存在但页面 403/404 | 用户归属、原子落位、缩略图记录 |
| 上游连不上 | SSRF 日志、DNS/IPv6、redirect、proxy 和 base_url |
| 上游连不上 | SSRF 日志、DNS/IPv6、redirect、proxy、base_url 和 `CHORUS_PROVIDER_ALLOWED_PORTS` |
| 管理端生成异常 | 是否先迁移再导表,是否误把菜单脚本当业务 DDL |
| 样式丢失 | portal Tailwind 产物或 admin-ui pnpm/Vue CLI 构建 |
+3 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Troubleshooting
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Troubleshooting
wiki_revision: 343eedb7cb319e2de24725965817444454ef9b8d
synchronized_at: 2026-08-25T01:53:19Z
wiki_revision: 47ed912393c434b5547bff7ee4a3c488af03b749
synchronized_at: 2026-08-25T03:56:42Z
<!-- gitea-wiki-mirror:end -->
# 故障排查
@@ -62,7 +62,7 @@ LIMIT 10;
依次检查:
1. base_url scheme/host/port;
1. base_url scheme/host/port,并确认非标准公开端口已显式加入 `CHORUS_PROVIDER_ALLOWED_PORTS`;未设置时只允许 80/443;
2. DNS 的每个 IPv4/IPv6 结果;
3. DialContext 是否拒绝私网、回环、链路本地、组播和未指定地址;
4. 每次 redirect 是否重新校验并限制次数;
+3 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Deployment-and-Operations
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Deployment-and-Operations.-
wiki_revision: dca6da65b9f80b0278ce221847b671b4ecb86ba9
synchronized_at: 2026-08-25T01:12:36Z
wiki_revision: 62fb1a6eb027824fce0d4147e6afba7c06e68fcf
synchronized_at: 2026-08-25T03:57:04Z
<!-- gitea-wiki-mirror:end -->
# 部署与运维
@@ -127,6 +127,7 @@ portal 单二进制会同时启动 HTTP server 和内嵌 worker。生产除现
| `CHORUS_WORKER_POLL_MILLISECONDS` | 正整数;控制空队列轮询间隔 |
| `CHORUS_PROVIDER_HTTP_TIMEOUT_SECONDS` | 正整数;安全 HTTP client 总超时和响应头超时 |
| `CHORUS_PROVIDER_MAX_RESPONSE_BYTES` | 正整数;Provider JSON/Base64/下载响应读取上限 |
| `CHORUS_PROVIDER_ALLOWED_PORTS` | 可选的逗号分隔端口白名单;默认 `80,443`,仅在受控变更后加入所需公开端口 |
Provider API Key 由授权管理员通过管理端写入 `provider_credentials.api_key`。数据库、备份和管理员会话泄露会直接暴露完整 Key;必须限制数据库和管理端权限,列表/普通详情/日志/audit 禁止返回完整值,单条读取响应禁止缓存。部署环境不再需要 `CHORUS_MASTER_KEY`。