Cloudflare WAF と Turnstile のタッグで fetch() にチャレンジする
API 呼び出しのようなブラウザからの fetch() に対しても WAF(Custom Rules)で Cloudflare チャレンジをあてることができるようになった、ということで上記 Blog のサンプルを試してみました。
Pre-Clearance を有効にした Turnstile の力を借りる形になります。
課題
Blog のサンプルでは、ボタン押下で fetch() リクエストされる特定の API エンドポイントに WAF(Custom Rules)で Managed Challenge をかけようとします。が、最初はうまくいきません。
WAF のルール
フローは下記のとおりです。
- ボタン押下で fetch()
/your-api
-
/your-api
が WAF ルール(action: managed challenge)に当たる - チャレンジが戻る(主なレスポンスヘッダ)
- レスポンスステータス 403
- content-type: text/html; charset=UTF-8
- cf-mitigated: challenge
- 無反応…
対策
Cloudflare チャレンジでは、チャレンジに成功したクライアントにレスポンスを返す際に cf_clearance cookie をセットし、以降のリクエストが一定期間チャレンジを受けることなく cookie で検証されるようになります。
このチャレンジパス用の cookie をあらかじめ入手し、fetch() に付与できれば、WAF の Managed Challenge を通過することができます。
これに対応するため、Turnstile を通じて cf_clearance cookie を取得できる Pre-Clearance 機能が追加されました。
例えば Blog では下記の点で変更された対策済みのサンプルが提示しています。
- アプリケーション側は fetch() を Turnstile 対応に上書き
- Turnstile に当該ドメインを 追加、 Pre-Clearance も有効化
結果
サンプルの変更を適用すると、フローが下記のように変わりました。
3 までは同じです。fetch() が上書きされている点を除く。
- ボタン押下で fetch()(上書きされてる)
/your-api
-
/your-api
が WAF ルール(action: managed challenge)に当たる - チャレンジが戻る(主なレスポンスヘッダ)
- レスポンスステータス 403
- content-type: text/html; charset=UTF-8
- cf-mitigated: challenge
- cf-mitigated: challenge ヘッダーをトリガーに Turnstile へチャレンジを要求
- チャレンジが解けると Turnstile 経由で cf_clearance cookie を発行
- cf_clearance cookie を伴い、再度 fetch()
- WAF は cookie を検証し Allow
- レスポンスを得る
特定の API エンドポイントにチャレンジをかけられるようになるので、Bot Management との併用など、WAF Custom Rules 内で重ねることのできるアプリケーションの多層保護の手が一つ増えました。
Discussion