From a24107ab333784be8523a663696b15dc10ac4ae4 Mon Sep 17 00:00:00 2001 From: xfy Date: Tue, 28 Jul 2026 16:55:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(mcp):=20=E5=BC=80=E5=8F=91=E6=9C=9F?= =?UTF-8?q?=E6=94=BE=E8=A1=8C=200.0.0.0=20Host=20=E8=AE=A9=20dx=20?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E5=8F=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dx serve --addr 0.0.0.0 转发到后端原生 server 时无条件把 Host 改写成 0.0.0.0:<随机端口>,rmcp 的 rebinding 防护据此一律 403,导致 MCP 在 dx 开发代理(:8080)下完全不可用。 仅当 APP_BASE_URL 未设或为 localhost 系(开发态)时把 0.0.0.0 加入 Host 白名单;生产域名态保持严格。直连原生端口始终可用(200)。 复现:8080 代理 →403,直连 56709 →200;显式发 Host:localhost 经 代理仍 403 证明 dx 无条件改写 Host。 --- src/mcp/router.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/mcp/router.rs b/src/mcp/router.rs index 0433508..9bdeefb 100644 --- a/src/mcp/router.rs +++ b/src/mcp/router.rs @@ -10,6 +10,7 @@ //! 生产反代 `proxy_set_header Host $host` 会把真实域名转发进来,必须加入否则 rmcp 一律 403。 //! //! 未设置 `APP_BASE_URL` 则两者均空(rmcp 对缺 Origin 放行;Host 回退默认表仅本地可用)。 +//! 开发期额外放行 `0.0.0.0`(dx 代理改写 Host 的容错),生产域名态保持严格。 //! 生产部署 MUST 设置 `APP_BASE_URL`(见 docs/DEPLOYMENT.md)。 //! 协议版本头、体积上限(4MiB 默认)由 rmcp 内置,无需此处重复。 @@ -52,6 +53,21 @@ pub fn mcp_route() -> Router { } } + // 开发期容错:APP_BASE_URL 未设或仍是 localhost 系(开发态)时,额外放行 0.0.0.0。 + // 原因:`dx serve --addr 0.0.0.0` 转发到后端原生 server 时会把 Host 头改写成 + // `0.0.0.0:<随机端口>`(原生 server 端口每次重编译变化),rmcp 据此判 rebinding 攻击 + // 一律 403——导致 MCP 在 dx 开发代理(:8080)下完全不可用。0.0.0.0 仅在本地开发无攻击 + // 价值,故仅在未配置生产域名时放行;生产域名态保持严格。 + let is_dev = base_url + .as_deref() + .and_then(|b| http::Uri::try_from(b).ok()) + .and_then(|u| u.authority().map(|a| a.host().to_lowercase())) + .map(|h| matches!(h.as_str(), "localhost" | "127.0.0.1" | "::1")) + .unwrap_or(true); // 未设 APP_BASE_URL 视为开发态 + if is_dev && !allowed_hosts.iter().any(|h| h == "0.0.0.0") { + allowed_hosts.push("0.0.0.0".into()); + } + let mut config = StreamableHttpServerConfig::default() .with_legacy_session_mode(false) // 无状态(SEP-2567) .with_json_response(true) // 简单工具用 application/json 直回