← Решения Cloudflare по борьбе с ботами / bots / reference / bot-verification
Web Bot Auth
Web Bot Auth представляет собой метод аутентификации, который использует криптографические подписи в HTTP-сообщениях для подтверждения того, что запрос исходит от автоматизированного бота. Web Bot Auth применяется как метод проверки для проверенные боты и агенты.
Это основано на черновиках IETF: черновик Directory ↗ который позволяет краулеру публиковать свои открытые ключи, и черновик протокола ↗ определяющий, как эти ключи должны использоваться для присоединения идентичности краулера к HTTP-запросам.
Этот раздел документации рассматривает конкретную интеграцию в рамках Cloudflare.
1. Сгенерируйте действительный ключ подписи
Вам нужно сгенерировать ключ подписи, который будет использоваться для аутентификации запросов вашего бота.
-
Создайте уникальный Ed25519 ↗ закрытый ключ для подписи запросов. В этом примере используется OpenSSL ↗
genpkeyкоманда:openssl genpkey -algorithm ed25519 -out private-key.pem -
Извлеките свой открытый ключ.
openssl pkey -in private-key.pem -pubout -out public-key.pem -
Преобразуйте открытый ключ в формат JSON Web Key (JWK) с помощью любого удобного инструмента. В этом примере используется
jwker↗ приложение командной строки.go install github.com/jphastings/jwker/cmd/jwker@latest jwker public-key.pem public-key.jwk
Выполнив эти шаги, вы сгенерировали закрытый и открытый ключи, а затем преобразовали открытый ключ в JWK.
2. Разместите каталог ключей
Вам нужно разместить каталог ключей, который позволит вашему боту аутентифицировать свои запросы к Cloudflare. Этот каталог должен соответствовать определению из draft-meunier-http-message-signatures-directory-03 ↗.
-
Разместите каталог ключей по адресу
/.well-known/http-message-signatures-directory(учтите, что это обязательное требование). Этот каталог ключей должен предоставлять набор JSON Web Key Set (JWKS), включающий открытый ключ, полученный из вашего ключа подписи. -
Обслуживайте веб-страницу по протоколу HTTPS (не HTTP).
-
Вычислите отпечаток JWK в кодировке base64 URL ↗ связанный с вашим открытым ключом Ed25519.
-
Подписывайте свой HTTP-ответ в соответствии со спецификацией HTTP Message Signature, добавляя по одной подписи для каждого ключа в каталоге ключей. Это гарантирует, что никто другой не сможет скопировать ваш каталог и попытаться зарегистрироваться от вашего имени. Ваш ответ должен содержать следующие заголовки:
Content-Type: Значение этого заголовка должно бытьapplication/http-message-signatures-directory+json.Signature: СоставьтеSignatureзаголовок ↗ над выбранными вами компонентами.Signature-Input: СоставьтеSignature-Inputзаголовок ↗ над выбранными вами компонентами. Заголовок должен соответствовать следующим требованиям.Обязательный компонент / параметр Требование tagЭто значение должно совпадать с http-message-signatures-directory.keyidОтпечаток JWK соответствующего ключа в вашем каталоге. createdЭто значение должно совпадать с Unixвременную метку, связанную с моментом отправки сообщения вашим приложением.expiresЭто значение должно совпадать с Unixвременную метку, связанную с моментом, после которого Cloudflare больше не должен пытаться проверить сообщение.@authorityЭто значение должно совпадать со значением заголовка Host, отправленного в запросе. Необходимо задать reqпараметр компонента ↗.
В следующем примере показаны аннотированные запрос и ответ с обязательными заголовками для
https://example.com. ЗначениеSignatureздесь приведена исключительно в иллюстративных целях и не является фактически сгенерированной подписью.GET /.well-known/http-message-signatures-directory HTTP/1.1 Host: example.com Accept: application/http-message-signatures-directory+json HTTP/1.1 200 OK Content-Type: application/http-message-signatures-directory+json Signature: sig1=:TD5arhV1ved6xtx63cUIFCMONT248cpDeVUAljLgkdozbjMNpJGr/WAx4PzHj+WeG0xMHQF1BOdFLDsfjdjvBA==: Signature-Input: sig1=("@authority";req);alg="ed25519";keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U";nonce="ZO3/XMEZjrvSnLtAP9M7jK0WGQf3J+pbmQRUpKDhF9/jsNCWqUh2sq+TH4WTX3/GpNoSZUa8eNWMKqxWp2/c2g==";tag="http-message-signatures-directory";created=1750105829;expires=1750105839 Cache-Control: max-age=86400 { "keys": [{ "kty": "OKP", "crv": "Ed25519", "x": "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs", // Base64 URL-encoded public key, with no padding }] }
Вы можете использовать разработанный Cloudflare http-signature-directory инструмент CLI ↗ чтобы помочь вам проверить ваш каталог.
3. Зарегистрируйте своего бота и каталог ключей
Чтобы добавить вашего бота в список проверенных ботов, необходимо зарегистрировать бота и его каталог ключей.
- Войдите в Панель управления Cloudflare ↗, и выберите свой аккаунт и домен.
- Перейдите в Manage Account > Конфигурации.
- Перейдите в Bot Submission Form на вкладке.
- Для Метод проверки: выберите Подпись запроса.
- Для Инструкции по проверке: укажите URL каталога ключей. Дополнительно можно указать значения User Agents (и шаблоны их соответствия), которые будет отправлять ваш бот.
- Выберите Отправить.
Cloudflare принимает все действительные ключи Ed25519, найденные в вашем каталоге ключей. Если ключ уже зарегистрирован в базе Cloudflare, компания поможет вам получить новый ключ или заменить существующий.
После успешной проверки вы сможете отправлять проверенные запросы.
4. (После проверки) Подписывайте свои запросы
После того как ваш бот успешно пройдёт проверку, он будет готов подписывать свои запросы. Протокол подписи описан в draft-meunier-web-bot-auth-architecture-02 ↗
4.1. Выберите набор компонентов для подписи
Выберите набор компонентов для подписи.
Компонентом является либо HTTP-заголовок, либо любой производные компоненты ↗ в спецификации HTTP Message Signatures. Cloudflare рекомендует следующее:
- Выберите как минимум
@authorityпроизводный компонент, который представляет домен, на который вы отправляете запросы. Например, запрос кhttps://example.comбудет интерпретирован как имеющий@authorityexample.com. - Используйте компоненты, содержащие только значения ASCII. Спецификация HTTP Message Signature запрещает символы, не входящие в ASCII, из-за чего проверка запросов вашего бота завершится ошибкой.
4.2. Вычислите отпечаток JWK
Вычислите отпечаток JWK в кодировке base64 URL ↗ из открытого ключа, который вы зарегистрировали в Cloudflare.
4.3. Сформируйте необходимые заголовки
Сформируйте три обязательных заголовка для Web Bot Auth.
Signature-Input заголовок
Сформируйте Signature-Input заголовок ↗ над выбранными вами компонентами. Заголовок должен соответствовать следующим требованиям.
| Параметр обязательного компонента | Требование |
|---|---|
tag |
Это значение должно совпадать с web-bot-auth. |
keyid |
Это значение должно совпадать с отпечатком, вычисленным на шаге 2. |
created |
Это значение должно совпадать с Unix временную метку, связанную с моментом отправки сообщения вашим приложением. |
expires |
Это значение должно совпадать с Unix временную метку, связанную с моментом, после которого Cloudflare больше не должен пытаться проверить сообщение. Короткий expires снижает вероятность повторных атак, поэтому Cloudflare рекомендует выбирать подходящие короткие интервалы. |
Signature заголовок
Сформируйте Signature заголовок ↗ над выбранными вами компонентами.
Signature-Agent заголовок
Сформируйте Signature-Agent заголовок ↗ который указывает на каталог ваших ключей. Cloudflare реализует Signature-Agent формат из draft-meunier-http-message-signatures-directory-03, где значение заголовка представляет собой структурированную строку, например "https://signature-agent.test".
Cloudflare не сможет проверить сообщение, если:
- Сообщение включает
Signature-Agentзаголовок, который не являетсяhttps://. - Сообщение включает действительный URI, но не заключает его в двойные кавычки. Это связано с тем, что Signature-Agent является структурированным полем.
- Сообщение использует форму словаря из более поздних черновиков, например
sig2="https://signature-agent.test". - Сообщение имеет действительный
Signature-Agentзаголовок, но не включает его в список компонентов вSignature-Input.
4.4. Добавьте заголовки к запросам вашего бота
Добавьте эти три заголовка к запросам вашего бота.
Пример запроса может выглядеть так:
Signature-Agent: "https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent")
;created=1735689600
;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"
;alg="ed25519"
;expires=1735693200
;nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg=="
;tag="web-bot-auth"
Signature: sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:Транзитивное доверие и Forwarded заголовок
Агент, который обращается к вашему сайту, часто управляется не той компанией, которая его создала. Платформа может выполнять автоматизированные действия от имени множества разных конечных пользователей, поэтому оператор и конечный пользователь не всегда совпадают. Cloudflare называет эту цепочку: владелец сайта → оператор бота → конечный пользователь, термином транзитивное доверие.
Чтобы передавать идентичность оператора по этой цепочке, Cloudflare экспериментирует с Forwarded заголовок, определённый в RFC 7239 ↗. Это работает как X-Forwarded-For делает для IP-адресов: предпочтение «разрешить» в отношении оператора действует независимо от того, обращается ли этот оператор к вам напрямую или через посредников, которым доверяет Cloudflare.
Оператор определяется с помощью for параметр:
Forwarded: for="openai"Заголовок также может содержать content-use значение, которое оператор фиксирует для контента, к которому он обращается:
Forwarded: for="openai";use="reference"Ограничения
Реализация Web Bot Auth от Cloudflare поддерживает не все компоненты и параметры, определенные в IETF RFC 9421. Если вы включите что-либо из перечисленного ниже в заголовок Signature-Input вашего запроса, проверка завершится ошибкой.
@query-params: Cloudflare рекомендует подписывать весь запрос с помощью@queryкомпонент вместо подписания отдельного параметра.@status: Это невозможно включить в путь запроса.
Следующие параметры компонентов, определённые в IETF RFC 9421, не поддерживаются, и если они включены, Cloudflare не сможет верифицировать сообщение:
sf(для полей заголовков HTTP)bs(для полей заголовков HTTP)key(для полей заголовков HTTP)req(для полей заголовков HTTP или производных компонентов)name(для@query-paramподдержку, для этого требуется@query-paramподдержка)
Устранение неполадок
Неудачная проверка сообщения
Если ваше сообщение не проходит проверку, причинами могут быть:
- Убедитесь, что у вас есть
Signature-Agentзаголовок, и что его значение указано в двойных кавычках. - Убедитесь, что ваш
Signature-Agentзаголовок использует структурированную строку, а не словарь. - Убедитесь, что вы включили
signature-agentв список компонентов в вашемSignature-Inputзаголовок. - Убедитесь, что ваш
expiresвременная метка не слишком короткая, иначе к моменту прибытия на серверы Cloudflare срок её действия уже истечёт. Обычно достаточно одной минуты. - Убедитесь, что вы не подписываете компоненты, содержащие значения не в кодировке ASCII, или компоненты из списка неподдерживаемых.
Используйте HTTP message signatures/Web Bot Auth в зоне без верификации Cloudflare
Если вы хотите использовать HTTP Message Signatures (Web Bot Auth) для обработки на собственном origin-сервере и не хотите, чтобы проверка Cloudflare вмешивалась или заполняла cf.bot_management.verified_bot поле, вы можете запросить отключение функции проверки Cloudflare для вашей зоны.
Чтобы отключить верификацию Web Bot Auth, обратитесь в Служба поддержки Cloudflare.
При отключении этой функции Cloudflare перестанет проверять входящие подписи. В этом случае проверенные боты будут определять легитимность трафика другими способами, например с помощью обратной проверки DNS.
Дополнительные ресурсы
Вы можете обратиться к следующим ресурсам.
- Блог Cloudflare: Message Signatures теперь входят в программу Verified Bots Program ↗.
- Блог Cloudflare: Забудьте про IP-адреса: проверка трафика ботов и агентов с помощью криптографии ↗.
- Cloudflare
web-bot-authбиблиотека на Rust ↗. - Cloudflare
web-bot-authnpm-пакет на Typescript ↗.