免费开始|联系销售 The Cloudflare Blog

The Cloudflare Blog

订阅以接收新帖子的通知: 订阅 magnifier iconhamburger menu Developers AI Radar Product News Security Policy & Legal Zero Trust Speed & Reliability Life at Cloudflare Partners Developers AI Radar Product News Security Policy & Legal Zero Trust Speed & Reliability Life at Cloudflare Partners magnifier icon

抛弃 IP 地址:使用密码学验证 Bot 和 Agent 流量

2025-05-15

10 分钟阅读 随着来自 AI agent 的流量增加,什么才算是 bot 已经不再明确。有些是明显的恶意 bot,比如那些对你的网站进行 DoS 攻击或进行 credential stuffing 的 bot,还有一些是大多数网站所有者希望与之互动的 bot,比如为搜索引擎索引你的网站的 bot,或者获取 RSS feed 的 bot。

过去,Cloudflare 依赖两个主要信号来验证来自其他类型自动化流量的合法网络爬虫:用户代理 header 和 IP 地址。[_User-Agent_ header](https://blog.cloudflare.com/web-bot-auth/https:/developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent) 允许 bot 开发者识别自己,例如 MyBotCrawler/1.1。但是,单独的用户代理 header 很容易被欺骗,因此不足以进行可靠的识别。为了解决这个问题,用户代理检查通常辅以 IP 地址验证,即检查已发布的 IP 地址范围以确认爬虫的真实性。然而,围绕 IP 地址范围代表产品或用户群体的逻辑是脆弱的——来自爬取服务的连接可能被多个用户共享,例如在 privacy proxies 和 VPN 的情况下,并且这些范围通常由云提供商维护,并且会随时间变化。

Cloudflare 将始终尝试阻止恶意 bot,但我们认为我们在这里的角色也是提供一种肯定的机制来验证理想的 bot 流量。通过使用完善的密码学技术,我们提出了一种更好的机制,供合法的 agent 和 bot 声明自己的身份,并为网站所有者提供更清晰的信号来决定允许哪些流量。

今天,我们推出了两个提案——HTTP message signatures 和 request mTLS——用于friendly bots验证自己的身份,以及客户源站识别它们。 在这篇博文中,我们将分享这些认证机制是如何工作的,我们是如何实现它们的,以及你如何参与我们的封闭测试。

现有的 Bot 验证机制已失效

从历史上看,如果你在 ChatGPT、Claude、Gemini 或任何其他 agent 上工作过,你可能有几个选项来识别你的 HTTP 流量到其他服务:

  1. 你定义一个 user agent,一个在 RFC 9110 中描述的 HTTP header。这里的问题是,这个 header 很容易被欺骗,并且 agent 没有明确的方法将自己识别为半自动化的浏览器——agent 通常为此使用 Chrome user agent,这是不鼓励的。该 RFC states"如果 user agent 伪装成不同的 user agent,接收者可以假定用户有意希望看到为该标识的 user agent 定制的响应,即使它们对于正在使用的实际 user agent 可能无法很好地工作。"
  2. 你发布你的 IP 地址范围。这有限制,因为同一个 IP 地址可能被同一公司内的多个用户或多个服务共享,甚至当托管基础设施共享时(例如 Cloudflare Workers)被多个公司共享。此外,由于底层基础设施的变化,IP 地址容易发生变化,导致服务使用临时的共享机制,如 CIDR lists
  3. 你访问每个网站并共享一个密钥,例如一个 Bearer token。这在规模上是不切实际的,因为它要求开发者为他们的 bot 将访问的每个网站维护单独的 token。

我们可以做得更好!我们建议 bot 和 agent 的开发者以加密方式对来自其服务的请求进行签名,而不是采用这些繁琐的方法。在保护源站时,像 Cloudflare 这样的反向代理可以验证这些签名,从而代表网站所有者自信地识别请求来源,从而允许他们采取他们认为合适的行动。 一个典型的系统有三个参与者:

在下一节中,我们将深入探讨 HTTP Message Signatures 和 request mTLS,浏览器 agent 可以实现这两种机制来对传出请求进行签名,对于源站来说,采用的难易程度不同。

介绍 HTTP Message Signatures

HTTP Message Signatures 是一个定义请求发送者密码学身份验证的标准。它本质上是一种密码学上可靠的方式来说“嘿,是我!”。这不是开发者可以对其基础设施发出的请求进行签名的唯一方法——例如,AWS 已经使用了 Signature v4,Stripe 有一个用于 authenticating webhooks 的框架——但 Message Signatures 是一个已发布的标准,并且是最干净、对开发者最友好的请求签名方式。

我们正在与更广泛的行业密切合作,以支持这些基于标准的方法。例如,OpenAI 已经开始对他们的请求进行签名。用他们自己的话说:

"确保 Operator 流量的真实性至关重要。通过 HTTP Message Signatures(RFC 9421 ),OpenAI 对所有 Operator 请求进行签名,因此网站所有者可以验证它们是否真正源自 Operator 并且没有被篡改”——Eugenio,工程师,OpenAI

事不宜迟,让我们深入了解 HTTP Messages Signatures 如何识别 bot 流量。

将标准范围限定于 Bot 认证

生成 message signature 的工作方式如下:在发送请求之前,agent 使用公钥对目标源站进行签名。当获取 https://example.com/path/to/resource 时,它会对 example.com 进行签名。此公钥为源站所知,要么是因为 agent 是众所周知的,要么是因为它先前已注册,或者任何其他方法。然后,agent 写入一个 Signature-Input header,其中包含以下参数:

  1. 有效窗口(createdexpires 时间戳)
  2. 唯一标识签名中使用的密钥的密钥 ID。这是一个 JSON Web Key Thumbprint
  3. 一个 tag,向网站显示签名的目的和验证方法,例如 web-bot-auth 用于 bot 认证。

此外,Signature-Agent header 指示源站可以在哪里找到 agent 在对请求进行签名时使用的公钥,例如在 signer.example.com 托管的目录中。此 header 也是签名内容的一部分。

这是一个例子:

GET /path/to/resource HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 Chrome/113.0.0 MyBotCrawler/1.1
Signature-Agent: signer.example.com
Signature-Input: sig=("@authority" "signature-agent");\
       	 created=1700000000;\
       	 expires=1700011111;\
       	 keyid="ba3e64==";\
       	 tag="web-bot-auth"
Signature: sig=abc==

对于构建 bot 的人,我们建议 对目标 URI 的 authority 进行签名,例如 Google Search 的 crawler.search.google.com 、OpenAI Operator 的 operator.openai.com、 Cloudflare Workers 的 workers.dev,以及以 signature-agent 形式检索 bot 公钥的方式(如果存在)。

上面示例中的 User-Agent 表明发出请求的软件是 Chrome,因为它是一个使用精心设计的 Chrome 浏览器浏览网页的 agent。你应该注意,MyBotCrawler/1.1 仍然存在。 User-Agent header 实际上可以包含多个产品,重要性递减。如果我们的 agent 通过 Chrome 发出请求,那是最重要的产品,因此排在第一位。

在 Internet 级别的规模上,这些签名可能会给请求处理增加显着的开销。然而,有了正确的密码学套件,并且与现有 bot 缓解措施(包括技术和社会成本)相比,这似乎是一个简单的权衡。这是一个我们将密切关注的指标,并将随着采用率的增长而报告。

生成请求签名

我们正在为 bot 和 agent 生成 Message Signatures 的几个示例 available on Github (虽然我们鼓励其他实现!),所有这些都符合标准,以最大限度地提高互操作性。

假设你正在使用托管的 Chromium 浏览器构建一个 agent,并且想要对所有传出请求进行签名。为了实现这一点,webextensions standard 提供了 chrome.webRequest.onBeforeSendHeaders,你可以在其中修改 HTTP header,然后再由浏览器发送它们。该事件在发送任何 HTTP 数据之前以及 header 可用时 triggered

以下是代码的样子:

chrome.webRequest.onBeforeSendHeaders.addListener(
 function (details) {
	// Signature and header assignment logic goes here
   // <CODE>
 },
 { urls: ["<all_urls>"] },
 ["blocking", "requestHeaders"] // requires "installation_mode": "force_installed"
);

Cloudflare 在 npm 上提供了一个 web-bot-auth 助手包,可帮助你使用正确的参数生成请求签名。 onBeforeSendHeaders 是一个 Chrome 扩展 hook,需要同步实现。为此,我们 import {signatureHeadersSync} from “web-bot-auth”。签名完成后,将分配 SignatureSignature-Input header。然后,请求流可以继续。

const request = new URL(details.url);
const created = new Date();
const expired = new Date(created.getTime() + 300_000)

// Perform request signature
const headers = signatureHeadersSync(
 request,
 new Ed25519Signer(jwk),
 { created, expires }
);
// `headers` object now contains `Signature` and `Signature-Input` headers that can be used

此扩展代码可在 GitHub 上获得,以及一个调试服务器,部署在 https://http-message-signatures-example.research.cloudflare.com

验证请求签名

使用我们的 debug server,我们现在可以从我们将要访问的网站的角度检查和验证我们的请求签名。我们现在应该看到 Signature 和 Signature-Input header: 在此示例中,调试服务器的主页验证来自 RFC 9421 Ed25519 验证密钥的签名,该扩展用于签名。

上面的演示和代码演练已完全用 TypeScript 编写:验证网站在 Cloudflare Workers 上,客户端是 Chrome 浏览器扩展。我们知道这并不适合 Web 上的所有客户端和服务器。为了证明该提案在更多环境中有效,我们还使用 pluginCaddy server 在 Go 中实现了 bot 签名验证。

实验 Request mTLS

HTTP 不是传递签名的唯一方法。例如,过去用于针对安全端点验证自动化流量的一种机制是 mTLS ,即 TLS 证书的“相互”呈现。正如我们的 knowledge base 中所述:

Mutual TLS,或简称 mTLS,是一种mutual authentication 的方法。mTLS 通过验证它们是否都具有正确的 privatekey 来确保网络连接每一端的各方是他们声称的那个人。他们各自TLS certificates 中的信息提供了额外的验证。

虽然 mTLS 似乎很适合 Web 上的 bot 身份验证,但它有限制。如果用户被要求通过 mTLS 协议进行身份验证,但没有证书可提供,他们将收到一个难以理解且无法跳过的错误。源站点需要一种有条件地向客户端发出信号的方式,表明它们接受或需要 mTLS 身份验证,以便只有启用 mTLS 的客户端才使用它。

用于 Bot 身份验证的 TLS Flag

TLS Flag 是一种描述源站点是否支持某项功能(如 mTLS)的有效方法。在 IETF 中,我们提出了一个新的 TLS Flag,称为 [_req mTLS_](https://blog.cloudflare.com/web-bot-auth/https:/datatracker.ietf.org/doc/draft-jhoyla-req-mtls-flag/),在建立连接期间由客户端发送,该标志表明支持通过客户端证书进行身份验证。

该提案利用了 IETF 中正在讨论的 tls-flags 提案。 TLS Flag 草案允许客户端和服务器相互发送一个单比特标志数组,而不是为他们想要共享的每一条信息创建一个新的扩展(及其相关的开销)。这是该扩展程序的首批用途之一,我们希望通过在此处使用它,我们可以帮助推动采用。

当客户端将 [_req mTLS_](https://blog.cloudflare.com/web-bot-auth/https:/datatracker.ietf.org/doc/draft-jhoyla-req-mtls-flag/) flag 发送到服务器时,它们会向服务器发出信号,表明如果请求,它们能够响应证书。然后,服务器可以安全地请求证书,而不会冒阻止普通用户流量的风险,因为普通用户永远不会设置此 flag。

让我们看一下 req mTLS 在网络协议分析器 Wireshark 中的一个例子。你可以在数据包捕获 here 中进行跟踪。

Extension: req mTLS (len=12)
	Type: req mTLS (65025)
	Length: 12
	Data: 0b0000000000000000000001

扩展号为 65025 或 0xfe01。这对应于可以用来试验 TLS Flag 的 TLS extensions 的未分配块。一旦该标准被 IETF 采用并发布,该数字将被固定。要使用 req mTLS flag,客户端需要将第 80 位设置为 true,因此对于我们的 12 字节块长度,它应包含数据 0b0000000000000000000001,此处即为这种情况。然后,服务器响应证书请求,并且该请求继续进行。

实际操作中的 Request mTLS

本节的代码可在 GitHub 上的cloudflareresearch/req-mtls 中找到。

由于 TLS 库中已广泛支持相互 TLS,因此我们需要引入到客户端和服务器的部分是:

  1. 发送/解析 TLS-flag
  2. req mTLS flag 的特定支持

据我们所知,没有这两种方案的公开实施。使用它进行 bot 身份验证可能会提供这样做的动机。

使用 our experimental fork of Go,TLS 客户端可以按如下方式支持 req mTLS:

config := &tls.Config{
  	TLSFlagsSupported: []tls.TLSFlag{0x50},
  	RootCAs:    	rootPool,
  	Certificates: 	certs,
  	NextProtos:  	[]string{"h2"},
}
trans := http.Transport{TLSClientConfig: config, ForceAttemptHTTP2: true}

这个示例库允许你配置 Go 以在 TLS Flags 扩展中发送 req mTLS 0xfe01 字节。如果你想测试你的实施,你可以使用 Cloudflare Research 客户端 cloudflareresearch/req-mtls 针对 req-mtls.research.cloudflare.com 提示你的客户端提供证书。对于客户端,一旦他们设置了与 req mTLS 关联的 TLS Flags,他们就完成了。处理普通 mTLS 的代码部分将在此时接管,无需实施任何新内容。

两种方法,一个目标

我们认为,agent 和 bot 的开发者应该有一种公开的标准方式,无论他们使用的技术或选择的提供商如何,都可以向 CDN 和网站托管平台验证自己的身份。从高层次上讲,HTTP Message Signatures 和 request mTLS 都实现了类似的目标:它们允许服务的所有者以真实的方式向网站识别自己。这就是我们参与 IETF 上这两种协议的标准化工作的原因,我们在那里讨论的许多其他身份验证机制(从 TLS 到 OAuth Bearer token)都是由不同的利益相关者开发的,并标准化为 RFC。

将这两种提案相互评估,我们优先考虑 HTTP Message Signatures for Bots,因为它依赖于先前采用的 RFC 9421 以及几个 reference implementations,并在 HTTP 层工作,使采用更简单。 request mTLS 可能更适合对额外带宽有顾虑的网站所有者,但 TLS Flags 的实现较少,仍在等待 IETF 采用,并且升级 TLS 堆栈已被证明比 HTTP 具有更大的挑战。正如 IETF 的 glossary 草案中所强调的那样,这两种方法都共享类似的发现和密钥管理问题。我们正在积极探索这两种选择,并希望 hear 来自网站所有者和 bot 开发者的信息,了解你们如何评估它们各自的权衡。

更大的图景

总之,我们认为请求签名和 mTLS 是 bot 所有者和 AI agent 开发者以防篡改的方式验证自己的身份的有前途的机制,从而开辟了一条不依赖于不断变化的 IP 地址范围或可欺骗的 header(如 User-Agent )的道路。当 Cloudflare 充当反向代理时,或者直接由网站所有者在其自己的基础设施上使用时,都可以使用此身份验证。这意味着作为 bot 所有者,你现在可以与内容创建者联系并讨论爬网协议,其粒度与你拥有的 bot 数量一样多。你可以立即开始实施这些解决方案,并针对我们在本文中提供的研究网站对其进行测试。

Bot 身份验证还使大大小小的网站所有者能够更好地控制他们允许的流量,从而使他们能够继续在公共 Internet 上提供内容,同时监控自动化请求。从长远来看,我们将这些身份验证机制集成到我们的 AI AuditBot Management 产品中,以更好地了解愿意识别自己的 bot 和 agent。

能够解决源站和客户端的问题是帮助构建更好的 Internet 的关键,我们认为识别自动化流量是朝着这个方向迈出的一步。如果你希望我们开始验证你的 message signatures 或客户端证书,有希望我们考虑的引人注目的用例,或者有任何问题,请 reach out

Cloudflare 的 connectivity cloud 保护 entire corporate networks, helps customers build Internet-scale applications efficiently, accelerates any website or Internet application, wards off DDoS attacks, keeps hackers at bay, and can help you on your journey to Zero Trust.Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions. 在 Hacker News 上讨论 ResearchBotsBot ManagementAI BotsCryptography 在 X 上关注 Thibault Meunier|@thibmeu Mari Galicer|@mmvri Cloudflare|@cloudflare 相关帖子 2025 年 4 月 11 日下午 1:00

[基于 Cloudflare Workers 构建的下一代 Certificate Transparency log](https://blog.cloudflare.com/web