通过127.0.0.1:8931访问playwright-mcp服务被拒绝,但通过localhost:8931访问却被允许的原因
原因在于playwright-mcp为了防止DNS 重绑定攻击,默认只允许通过 Host:localhost访问,即使是127.0.0.1也不行
实现原理在函数installHttpTransport(httpServer, serverBackendFactory, allowedHosts?: string[])
const url = addressToString(httpServer.address(), { protocol: 'http', normalizeLoopback: true });
const host = new URL(url).host;
allowedHosts = (allowedHosts || [host]).map(h => h.toLowerCase());
上面的代码在不传入参数allowedHosts的默认情况下,最终的allowedHosts列表中会只有http://localhost:8931,
在后续的请求处理中:
if (!allowAnyHost) {
const host = req.headers.host?.toLowerCase(); //获取你发送的请求的host,
if (!allowedHosts.includes(host)) { //验证host是否在allowedHosts列表中,
res.statusCode = 403; //如果你的请求是127.0.0.1:8931,host就是127.0.0.1:8931,
return res.end('Access is only allowed at ' + allowedHosts.join(', ')); //返回 Access is only allowed at localhost:8931
}
}
官方的Playwright MCP 服务器支持的启动参数中有--allowed-hosts <hosts...>,可以通过设置这个参数手动传入 allowedHosts
不传入 allowedHosts(默认行为)
// 调用函数时不传第三个参数
await installHttpTransport(httpServer, backendFactory);
// 此时:
// host = "localhost:8931"
// allowedHosts = (undefined || ["localhost:3000"]) = ["localhost:3000"]
// 最终 allowedHosts = ["localhost:3000"]
手动传入 allowedHosts
// 调用时指定白名单
await installHttpTransport(httpServer, backendFactory, ['example.com', 'api.example.com']);
// 此时:
// host = "localhost:8931" (仍然会被计算,但不使用)
// allowedHosts = (['example.com', 'api.example.com'] || ["localhost:8931"])
// = ['example.com', 'api.example.com']
// 最终 allowedHosts = ['example.com', 'api.example.com']
这种设计特别适合本地开发服务器,默认情况下只允许本地访问,但可以显式配置允许外部域名访问。

浙公网安备 33010602011771号