fix(mcp): 开发期放行 0.0.0.0 Host 让 dx 代理可用
Some checks failed
CI / check (push) Has been cancelled
CI / build (push) Has been cancelled

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。
This commit is contained in:
xfy 2026-07-28 16:55:18 +08:00
parent 6d520c3d48
commit a24107ab33

View File

@ -10,6 +10,7 @@
//! 生产反代 `proxy_set_header Host $host` 会把真实域名转发进来,必须加入否则 rmcp 一律 403。 //! 生产反代 `proxy_set_header Host $host` 会把真实域名转发进来,必须加入否则 rmcp 一律 403。
//! //!
//! 未设置 `APP_BASE_URL` 则两者均空rmcp 对缺 Origin 放行Host 回退默认表仅本地可用)。 //! 未设置 `APP_BASE_URL` 则两者均空rmcp 对缺 Origin 放行Host 回退默认表仅本地可用)。
//! 开发期额外放行 `0.0.0.0`dx 代理改写 Host 的容错),生产域名态保持严格。
//! 生产部署 MUST 设置 `APP_BASE_URL`(见 docs/DEPLOYMENT.md //! 生产部署 MUST 设置 `APP_BASE_URL`(见 docs/DEPLOYMENT.md
//! 协议版本头、体积上限4MiB 默认)由 rmcp 内置,无需此处重复。 //! 协议版本头、体积上限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() let mut config = StreamableHttpServerConfig::default()
.with_legacy_session_mode(false) // 无状态SEP-2567 .with_legacy_session_mode(false) // 无状态SEP-2567
.with_json_response(true) // 简单工具用 application/json 直回 .with_json_response(true) // 简单工具用 application/json 直回