From 39e480a362eec7abb54359e10c5cfa78b145f29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=83=E9=AD=84?= Date: Fri, 14 Aug 2026 12:04:52 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix(#IK49NP):=20tRPC=20=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=2017778=20=E4=BB=85=E7=BB=91=E5=AE=9A=20127.0.0.1=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=A4=96=E9=83=A8=E7=9B=B4=E8=BF=9E=E7=BB=95?= =?UTF-8?q?=E8=BF=87=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit footstone 的 tRPC 服务(端口 17778)filter 链被 AllowTrpc 放过(纯 tRPC 请求无 HTTP head 即返回 true),原 docker-compose 将该端口直接映射到 宿主机 0.0.0.0,外部网络可通过 tRPC 客户端直连 17778 调用任意 RPC(含 QueryJWTSecret 等敏感接口),绕过 tm-userpassword/tm-permission 鉴权。 修复: - docker-compose.yml: footstone 的 17778 端口映射改为 127.0.0.1:PORT:17778, 仅本机可达;容器间内部调用仍走 docker 网络 ip://footstone:17778,不受影响。 - plugin.go: 在 AllowTrpc 增加安全说明注释,阐明 tRPC 绕过鉴权的设计前提 与网络层隔离要求,并指出后续对 tRPC 鉴权需引入服务间身份机制 (mTLS / 服务账号 token)并改造 verifyToken/GetPath。 说明:本 PR 聚焦于关闭「外部直连 17778」这一攻击面(issue 修复建议 #3)。 AllowTrpc 行为未改动,以避免破坏 sysdiagnose 等内部服务间 tRPC 调用; issue 建议 #1/#2(为 tRPC 加 filter 并改 AllowTrpc)需配合服务间身份机制 协同改造,建议作为后续 follow-up。 关联 issue #IK49NP --- manager/backend/pkg/plugin/permission/plugin.go | 7 +++++++ manager/deployments/compose/docker-compose.yml | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/manager/backend/pkg/plugin/permission/plugin.go b/manager/backend/pkg/plugin/permission/plugin.go index 5ed49b7..daf3f29 100644 --- a/manager/backend/pkg/plugin/permission/plugin.go +++ b/manager/backend/pkg/plugin/permission/plugin.go @@ -305,6 +305,13 @@ func (c *Config) PullAllowPath() error { } // AllowTrpc @Description: 放过trpc请求 +// +// 安全说明(issue #IK49NP):纯 tRPC 协议请求(无 HTTP head)会绕过 +// tm-userpassword / tm-permission 过滤器。这是当前内部服务间调用的设计前提 +// (如 sysdiagnose -> footstone,无用户 JWT)。因此 tRPC 端口(17778)必须 +// 仅在受信网络内可达,不得对外暴露——见 docker-compose.yml 中 127.0.0.1 绑定。 +// 后续若要对 tRPC 也做鉴权,需引入服务间身份机制(mTLS / 服务账号 token), +// 并改造 verifyToken 与 GetPath 以支持从 tRPC metadata 取 token 与 RPC 名。 func AllowTrpc(ctx context.Context) bool { var head *trpcHttp.Header if head = trpcHttp.Head(ctx); head == nil { diff --git a/manager/deployments/compose/docker-compose.yml b/manager/deployments/compose/docker-compose.yml index 12de095..91c62e0 100644 --- a/manager/deployments/compose/docker-compose.yml +++ b/manager/deployments/compose/docker-compose.yml @@ -65,7 +65,11 @@ services: ports: # 宿主机端口由 .env 控制;容器内部端口固定,与 nginx.docker.conf 保持一致 - "${FOOTSTONE_HTTP_PORT:-21000}:20000" - - "${FOOTSTONE_TRPC_PORT:-17778}:17778" + # 安全(issue #IK49NP):tRPC 端口 17778 的 filter 链被 AllowTrpc 放过, + # 直接暴露到宿主机/外部网络会绕过所有鉴权。这里仅绑定到 127.0.0.1, + # 供本机调试;容器间内部调用走 docker 网络 ip://footstone:17778,不受影响。 + # 如需跨机访问 tRPC,请通过带鉴权的前置网关代理,切勿直接对外暴露。 + - "127.0.0.1:${FOOTSTONE_TRPC_PORT:-17778}:17778" volumes: - ${LOG_DIR:-./logs}/footstone:/app/logs # 存活探针走独立 no-protocol 端口,避免被业务 tRPC/HTTP 路由解析。 -- Gitee From 4f6bcef38c5e58dd251fbb639c1f2091b03e7bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=83=E9=AD=84?= Date: Mon, 17 Aug 2026 12:44:18 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs(#IK49NP):=20=E5=90=8C=E6=AD=A5=2017778?= =?UTF-8?q?=20=E7=AB=AF=E5=8F=A3=E4=BB=85=E6=9C=AC=E6=9C=BA=E5=9B=9E?= =?UTF-8?q?=E7=8E=AF=E7=9A=84=E9=83=A8=E7=BD=B2=E7=BA=A6=E6=9D=9F=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=96=87=E6=A1=A3/env=20=E8=AF=AF=E5=AF=BC?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E6=9A=B4=E9=9C=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 针对评审意见(shop271):compose 已将 17778 绑到 127.0.0.1,但 README/env 仍按对外暴露写,部署会按文档把端口打出去,与代码不一致。本次按建议补齐: - config/env.example:在 FOOTSTONE_TRPC_PORT 旁补充安全说明,明确 17778 仅 绑定 127.0.0.1、不对外暴露,管理面外部访问走 HTTP 网关(FOOTSTONE_HTTP_PORT =21000)并由 tm-userpassword/tm-permission 鉴权后再转发到内部 tRPC。 - manager/deployments/compose/README.md:默认端口表标注 17778 仅 127.0.0.1, 并新增安全提示段,阐明 AllowTrpc 放过 tRPC 链的前提与网关鉴权要求。 - docs/QUICKSTART.md:在端口表后补充 17778 仅本机可达、外部管理请求走 HTTP 网关的说明,本地二进制运行需显式绑定 127.0.0.1。 - docs/reference/env-variables.md:补齐 FOOTSTONE_HTTP_PORT / FOOTSTONE_TRPC_PORT 的安全与鉴权说明。 不改动 plugin.go 行为(与原 PR 一致),仅补文档使部署与代码一致。 --- config/env.example | 4 ++++ docs/QUICKSTART.md | 6 ++++++ docs/reference/env-variables.md | 4 ++-- manager/deployments/compose/README.md | 9 ++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/config/env.example b/config/env.example index 8cddffc..278bf3d 100644 --- a/config/env.example +++ b/config/env.example @@ -173,6 +173,10 @@ MSG_ETL=ip://127.0.0.1:7779 # footstone 服务端口(宿主机映射端口,容器内实际监听端口由 trpc_go.yaml.template 决定) # 默认使用非标准端口以避免与宿主机已有服务(20000/7778/20001)冲突 +# 安全(issue #IK49NP):FOOTSTONE_TRPC_PORT 对应的 17778 端口仅绑定 127.0.0.1, +# 不对外暴露;tRPC filter 链被 AllowTrpc 放过,外部网络若可达 17778 即可绕过 +# tm-userpassword/tm-permission 鉴权调用任意 RPC。管理面所有外部访问请走 HTTP 网关 +# (FOOTSTONE_HTTP_PORT=21000),由网关统一鉴权后再转发到内部 tRPC。 FOOTSTONE_HTTP_PORT=21000 FOOTSTONE_TRPC_PORT=17778 FOOTSTONE_WS_PORT=21001 diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index 37a0aaf..5ec5a53 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -257,6 +257,12 @@ cd manager/backend/services/sysdiagnose/bin > 通过 Docker 内部网络访问。本地二进制运行没有这层映射,`trpc_go.yaml` 直接 > 按 `.env` 中的值监听,即上表数值。 +> **安全(issue #IK49NP)**:footstone tRPC `17778` 的 filter 链被 `AllowTrpc` +> 放过,外部网络若可达即可绕过 `tm-userpassword`/`tm-permission` 鉴权调用任意 +> RPC。`docker-compose.yml` 已将其宿主机映射改为 `127.0.0.1:17778:17778`, +> **仅本机可达,不对外暴露**;外部管理请求请走 HTTP 网关(`21000`)。本地二进制 +> 运行若监听到非回环地址,请通过 `trpc_go.yaml` 显式绑定 `127.0.0.1`。 + ### 步骤 6:启动前端开发服务器 ```bash diff --git a/docs/reference/env-variables.md b/docs/reference/env-variables.md index 4f30ac5..ade8326 100644 --- a/docs/reference/env-variables.md +++ b/docs/reference/env-variables.md @@ -64,8 +64,8 @@ | 变量 | 默认 | 消费者 | 说明 | |------|------|--------|------| -| `FOOTSTONE_HTTP_PORT` | `21000` | docker-compose | footstone HTTP 网关映射 | -| `FOOTSTONE_TRPC_PORT` | `17778` | docker-compose | footstone tRPC | +| `FOOTSTONE_HTTP_PORT` | `21000` | docker-compose | footstone HTTP 网关映射(外部管理面入口,由 `tm-userpassword`/`tm-permission` 鉴权) | +| `FOOTSTONE_TRPC_PORT` | `17778` | docker-compose | footstone tRPC(**仅绑定 `127.0.0.1`,不对外暴露**,issue #IK49NP) | | `FOOTSTONE_WS_PORT` | `21001` | docker-compose | footstone WebSocket | | `SYSDIAGNOSE_HTTP_PORT` | `21006` | docker-compose | sysdiagnose HTTP 网关 | | `FRONTEND_PORT` | `13070` | docker-compose | 前端 nginx | diff --git a/manager/deployments/compose/README.md b/manager/deployments/compose/README.md index 4f66e7f..61dc732 100644 --- a/manager/deployments/compose/README.md +++ b/manager/deployments/compose/README.md @@ -33,12 +33,19 @@ bash scripts/deploy.sh | ClickHouse HTTP | 8123 | **18123** | `CLICKHOUSE_HTTP_PORT` | | ClickHouse TCP | 9000 | **19000** | `CLICKHOUSE_TCP_PORT` | | footstone HTTP | — | **21000** | `FOOTSTONE_HTTP_PORT` | -| footstone tRPC | — | **17778** | `FOOTSTONE_TRPC_PORT` | +| footstone tRPC | — | **17778**(仅 `127.0.0.1`,不对外) | `FOOTSTONE_TRPC_PORT` | | sysdiagnose HTTP | — | **21006** | `SYSDIAGNOSE_HTTP_PORT` | | 前端 | 80 | **13070** | `FRONTEND_PORT` | > 如仍有冲突,修改 `config/.env` 对应的 `*_PORT` 变量即可,容器内端口无需改动。 +> **安全(issue #IK49NP)**:`FOOTSTONE_TRPC_PORT=17778` 的 filter 链被 `AllowTrpc` +> 放过(纯 tRPC 请求无 HTTP head 即返回 true),`docker-compose.yml` 已将宿主机 +> 映射改为 `127.0.0.1:17778:17778`,**仅本机可达,不对外暴露**。容器间内部调用 +> 仍走 Docker 网络 `ip://footstone:17778`,不受影响。管理面所有外部访问请走 +> footstone HTTP 网关(`FOOTSTONE_HTTP_PORT=21000`),由 `tm-userpassword` / +> `tm-permission` 鉴权后再转发到内部 tRPC。 + ## 全量部署常用命令 ```bash -- Gitee