Cloudflare 如何检测 MCP 流量并增强安全性

发布于

大多数公司在设计资源权限时,是以人类用户为中心的。例如,一位高级工程师可以部署到生产环境、查询敏感数据库,或撤销其他用户的访问权限。这些特权固然伴随着风险,但传统上风险受限于两个假设:工程师会使用人类的判断,且工程师只能以人类的速度进行操作。

当工程师看到意外结果时,通常会停止并重新考虑他们的行动。任何人每天只能点击、输入和审核有限的内容。人工智能代理的引入改变了这两个门槛。它们的决策具有非决定性,并且可以无限期地执行相同的操作或调用相同的工具,而不会感到疲惫或停下来吃午餐。一个看似合理——但实际上是错误的——决定在人工干预之前可能导致成千上万次的错误动作。

今天,我们宣布推出新的 [Cloudflare One](https://developers.cloudflare.com/cloudflare-one/) 功能,以识别经过检查的 MCP 流量,显示哪些用户和服务器正在生成该流量,并控制在受管理网络路径上的直接连接。结合 [MCP 服务器门户](https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/),这些控制功能帮助管理员查看代理是否使用了批准的路径,或者以某种方式绕过了它。

[模型上下文协议](https://www.cloudflare.com/learning/ai/what-is-model-context-protocol-mcp/)(MCP)服务器为代理提供了一个公共的方式来发现并调用由第三方 SaaS 产品、内部应用和 API 支持的工具。基本权限可能是众所周知的;改变的是决策的制定者以及糟糕决策传播的速度。

将代理连接到这些工具通常只需要一行配置。一名雇员可以直接指向 Claude Code、Codex、Cursor、OpenCode、VS Code 或任何 AI 工具,而无须检查其是否已获批准。所产生的流量没有明显的形状。模型上下文协议不使用强制主机名,也不需要在路径中包含 /mcp,因此直接连接可能看起来像任何其他 HTTPS API 调用。

为了说明这些控制如何结合在一起,我们将先从工具调用的结构及其所暴露的信息开始。然后,我们将比较安全团队可以采取行动的三个地方:客户端内、网络中,以及 MCP 服务器上。接下来,我们将展示 [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/) 如何利用协议信号找到隐形的 MCP 流量,并强制为经过验证的 MCP 服务器提供仅限门户的访问。

## MCP 工具调用的结构

同一 MCP 工具调用在系统中有三种形式。当它在客户端内时,它是调用工具的决策,附带一组参数。在网络上,它是一个携带 [JSON-RPC](https://www.jsonrpc.org/specification) 消息的 HTTP 事务。在服务器上,它变成对工具处理程序的调用,该处理程序可能会读取数据、改变状态或完成其他操作。

考虑一个代理想知道奥斯丁的天气。一个远程的 MCP 请求可能看起来像这样:

这条请求中包含几个有用的信号。主机名和路径标识了目标。授权头部携带了用于在服务器需要时验证调用者的凭证。头部中的 `MCP-Protocol-Version` 标识协议版本,同时 `Mcp-Method` 和 `Mcp-Name` 暴露了新无状态协议中的操作和工具。JSON-RPC 信封重复了方法,为请求分配一个 `id`,客户端可以根据这个 `id` 匹配响应,并在 `params` 中携带工具参数。

参数是最敏感的部分。它们可以包含搜索查询、源代码、客户数据,或某种操作的指令,例如创建工单或更改基础设施。工具名称表明代理打算调用的内容;参数则说明了它将发送何种数据以及希望服务器执行的操作。

如果调用成功,服务器将返回一条与请求相同的 `id` 和工具结果的 JSON-RPC 响应。该响应还可能包含敏感数据。请求检查可以在执行之前停止不安全的操作,而响应检查和记录则显示了工具返回给代理的内容。

## 控制 MCP 请求的三个地方

该请求为安全团队提供了三个观察或控制调用的地方。

### 在 MCP 客户端内部

一个 [客户端钩子](https://code.claude.com/docs/en/hooks) 可以在模型选择工具之后但在客户端序列化请求之前运行。从那里,它可以看到目标服务器、工具名称和参数,而无需解密网络流量。

这是请求链中施加控制的最早阶段。客户端可以拒绝未在允许列表上的服务器,需要用户确认敏感操作,或在请求离开设备之前从参数中移除数据。它还可以覆盖本地 `stdio`(即本地)MCP 服务器,这些服务器从未产生网络流量。

这带来了标准化的挑战。为了让安全团队受益,他们需要在员工使用的每个客户端上复制其控制。客户端侧控制效果最好是在组织同时管理客户端和设备的情况下,但单个客户端的遥测从来不是 MCP 使用的完整清单。

### 在设备的网络边界

一个 [安全网页网关](https://www.cloudflare.com/learning/access-management/what-is-a-secure-web-gateway/) 可以在HTTP请求离开客户端后观察该请求。使用 [TLS 解密](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/tls-decryption/),它可以将请求与用户及设备关联,检查目标和协议头,并在不依赖特定 MCP 客户端的情况下应用策略。

网络层具有最广泛的视角,能够检测受管理路径上的远程 MCP 流量。它可以识别指向未在批准门户外的服务器的直接连接,并在请求到达目标之前阻止它们。当 [数据丢失防护](https://developers.cloudflare.com/cloudflare-one/data-loss-prevention/) 扫描得到支持时,代理还可以检查 JSON-RPC 方法及参数中的敏感数据。然而,代理无法看到本地 `stdio` 调用或离线流量。

### 在 MCP 服务器调用工具之前

服务器拥有最丰富的执行上下文。它已经验证了调用者、解析了 MCP 消息、解析了 `get_weather` 到处理程序,并根据工具的输入模式校验所提供的参数。这是请求在工具运行之前可以被拒绝的最后一个点。

一个 [Agents SDK](https://developers.cloudflare.com/agents/model-context-protocol/) 处理程序或类似的服务器中间件可以授权该工具的调用者,应用速率限制,检查参数,并记录结果。服务器应在调用处理程序之前执行这些检查,尤其是对于会写入数据或触发外部操作的工具。仅在执行后记录结果可以解释发生了什么,但无法阻止它。

Cloudflare 的 [WriteGuard](https://blog.cloudflare.com/mcp-portal-writeguard-private-beta/) 在我们的内部 MCP 服务器中使用这种模式。每个工具都有一个风险等级和启用或禁用的状态。WriteGuard 可以通过不变地传递读取来处理允许的写入,增加代理归因和审核事件,或在处理程序运行之前阻止关键操作。由于控制存在于服务器上,最终用户无法通过更换客户端或禁用本地钩子来绕过它。

虽然服务器端控制只保护实施它们的服务器,但客户端和服务器具有最佳的请求深度。网络可以看到最广泛的一组远程连接。将这些控制结合使用,可以在敏感数据离开设备之前阻止它,发现未管理的 MCP 流量,并在工具执行之前拒绝未经授权的操作。

网络控制点具有最广泛的覆盖范围,但它首先必须区分 MCP 和普通 HTTPS 流量,用户必须运行代理,并且 MCP 服务器(或门户)必须验证该代理是否在连接中被使用。

Cloudflare One 提供了该链条的网络部分。[Cloudflare One 客户端](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) 将来自管理设备的流量通过 Gateway 发送。Gateway 可以在协议层上划分 MCP 请求,并区分流量是从 MCP 门户发起的,还是超出了批准的控制。然后,管理员可以报告或阻止未经批准路径的连接。该过程首先从可靠识别请求开始。

## URL 并不能告诉你请求是否使用了 MCP

我们最初寻找 MCP 流量的方法是使用 GraphQL Analytics API 搜索 [Gateway HTTP 日志](https://developers.cloudflare.com/cloudflare-one/insights/logs/dashboard-logs/gateway-logs/) 中的主机名,查找包含 `mcp` 和常见路径如 `/mcp` 或 `/sse` 的内容。我们的 [MCP 流量检测教程](https://developers.cloudflare.com/cloudflare-one/tutorials/detect-mcp-traffic-gateway-logs/#2-build-the-mcp-detection-query) 包括该查询。它还解释了如何创建 [数据丢失防护模式用于MCP JSON-RPC 方法](https://developers.cloudflare.com/cloudflare-one/tutorials/detect-mcp-traffic-gateway-logs/#4-create-dlp-profiles-for-mcp-json-rpc-detection),例如请求内容中的 `initialize`、`tools/call` 和 `resources/read`。

这些信号对于查找来自旧客户端的流量和提供历史可见性依然有用,但它们非常基础。它们可能会错过一个普通 URL 中的 MCP 服务器,像 [https://tools.example.com/api](https://tools.example.com/api) 这样的情况并不少见。

而且,它们还可能匹配一个无关的服务,恰好在主机名或路径中使用 `mcp`(虽然不太可能,但我们确实见过)。对于符合的可流式 HTTP 客户端,协议头是一个更具体的信号。 [MCP 2025-11-25 规范](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#protocol-version-header) 要求客户端在初始化后,每个 HTTP 请求中 **必须** 包含 `MCP-Protocol-Version`。而 [MCP 2026-07-28 规范](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#protocol-version-header) 更进一步,要求它在每个 POST 请求中也必须包含。

这并不意味着该头部是一个完整的探测器。来自旧客户端的初始请求可能不包含它,2025-06-18 之前的协议版本未定义该头部,而本地 `stdio`、自定义传输或非合规流量也可能永远不携带它。尽管有该头部是 MCP 的一个强标志,但缺少它并不证明请求不是 MCP。

## 协议在网络上变得更易识别

旧 MCP 流程以不包含 `MCP-Protocol-Version` HTTP 头部的 `initialize` 请求开始,因此仅凭该头部网络控制可能无法对来自先前未知端点的第一次请求进行分类。信号在客户端和服务器完成初始化后出现。

后续的工具调用可能看起来像这样:

[MCP 2026-07-28 规范](https://modelcontextprotocol.io/specification/2026-07-28) 使该模型发生了重大变化。核心协议是无状态的;它移除了 `initialize` 握手,并将协议版本和操作放在每个请求上。

`Mcp-Method` 和 `Mcp-Name` 头部允许普通 HTTP 基础设施在不解析主体的情况下识别操作。负载均衡器可以路由请求,速率限制器可以将 `tools/list` 与 `tools/call` 分开,安全产品可以获得每个请求的更多信息。

这些协议信号为 Cloudflare Gateway 提供了具体的评估依据,而不需要依赖一系列看起来像 MCP 的 URL。

## 隐形 MCP 和批准路径绕过是两个独立问题

一旦 Gateway 能够识别 MCP 流量,你就可以评估特定连接对安全态势的影响。

隐形 MCP 是指连接到组织未批准的服务器。员工在某个代码库、产品指南或同事的消息中发现该服务器,并直接添加到他们的 MCP 客户端。安全团队对其暴露的工具或员工发送给它的数据一无所知。

门户绕过则有所不同:它始于组织已放置在 MCP 门户中的批准服务器,但员工直接连接到其上游 URL,跳过门户的访问策略、策划的工具目录、数据丢失防护和工具级审核路径。

Gateway 是受管理网络路径上隐形 MCP 的主要控制方法;它识别 TLS 检查的 MCP 流量,显示目的地和用户,并可以应用策略。门户绕过需要网络控制,以及一个可以拒绝直接请求的来源,这可能意味着访问策略、源 IP 限制,或由 MCP 服务器本身启动的企业授权机制。

## 在 Gateway 中检测 MCP 流量

对于已经采用 Cloudflare Gateway 并开启 TLS 检查的客户,我们正在添加一种检测启发式,解答每个经过检查的请求的简单问题:**这是否是 MCP 流量?**

对于基于会话的可流式 HTTP 连接,MCP 客户端在初始化后发送一个 `MCP-Protocol-Version` 头。Gateway 检查在每个经过 TLS 检查的请求中的该头,根据我们在 Cloudflare 网络上每天天川的数百万个请求中观察到的模式对流量进行分类。该分类能够识别 MCP 协商和代理,无需提前了解特定主机或 URL。

**从今天开始,所有 Cloudflare Zero Trust 客户都可以在其 Gateway HTTP 日志中看到 MCP 流量的迹象,并可以使用新的 Gateway 选择器明确阻止或允许该流量:**

`experimental.is_mcp == true`

该选择器是一个布尔值。如果 Gateway 在 TLS 检查的请求中检测到 `MCP-Protocol-Version` 头,则该值为 `true`,管理员可以在允许或阻止策略中使用它,而无需维护自己的 MCP 类域名单。

直接的加密流量必须通过 [TLS 解密](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/tls-decryption/) 后,Gateway 才能检查这些头,并且本地 `stdio` 服务器、离线连接、[不检查](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/#do-not-inspect) 的流量和未经过 Gateway 的请求将保持在此视距之外。

## 了解网络中 MCP 流量的可见性

今天,我们推出了一个专门的 MCP 流量仪表板,展示了在您的网络中哪些主机正在服务 MCP 流量,哪些用户正在生成该流量,以及请求是否正在通过您的 Cloudflare MCP 门户传输或完全绕过它。

仪表板展示:

- 在可配置时间窗口内的总 MCP 请求、独特用户和独特服务器
- 随时间变化的 MCP 服务器及每台服务器的请求计数
- 按入口路由的流量划分,将 MCP 门户流量与直接设备客户端连接分开
- 在您的门户外看到的前几大 MCP 服务器,也就是最重要的隐形 MCP 流量
- 按 MCP 请求量排名的前几名用户

管理员可以按特定服务器、用户或入口类型过滤,并直接导航到 Gateway HTTP 日志,以相关主机或用户的过滤条件进行深入调查。

## 将发现的服务器导入 MCP 门户

MCP 发现将未知流量转变为管理员可以调查的列表。当组织批准了其中一个服务器时,可以将该服务器放置在 Cloudflare MCP 服务器门户之后。门户为员工提供了一个管理的端点,并将 [Access](https://developers.cloudflare.com/cloudflare-one/access-controls/) 身份、策划的工具目录和日志放在上游服务器之前。管理员可以 [通过 Gateway 路由兼容的上游调用](https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/#route-portal-traffic-through-gateway) 进行 HTTP 策略、可预测的出口和数据丢失防护,无论是针对门户还是特定服务器。工具活动也可以通过 [Logpush 导出](https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/#export-logs-with-logpush)。发现仪表板可以区分使用门户的请求与直接连接到同一服务器的请求。

这创建了一个从发现到治理的路径:找出服务器、决定是否批准、将批准的使用迁移到门户后面,调查继续绕过门户的流量。最后一步非常重要,因为未获批准的服务器和绕过批准服务器是两个不同的问题。

## 强制仅限门户的访问

我们正在向 [Gateway 网络](https://developers.cloudflare.com/cloudflare-one/traffic-policies/network-policies/) 和 [HTTP 策略](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/) 添加流量源选择器,让管理员能够根据流量是否源于 MCP 门户来编写规则,以控制 MCP 流量。

当 MCP 门户流量通过 Gateway 路由时,它携带 `mcp_portal` 流量源,这使得策略能够区分门户代理的请求

---

原文链接:[点击查看](https://blog.cloudflare.com/mcp-security-updates/)

评论

暂无评论。

0.048978s