
ダッシュボードに Cloudflare Trace(Beta)とあったので、試してみます。
Blog 記事がありました。
記事にあるように、13年にわたりこれまで何人ものお客様や Cloudflare 従業員がチャレンジしてきた The life of a Cloudflare request
の可視化 … いくら素晴らしい絵を書いても、Cloudflare のプロダクトが早い進化ですぐ陳腐化してしまうのが課題でした。
Cloudflare サポートチームの意見を取り入れたこのプロダクトは、ダッシュボードでそれを実現する第一歩となる気がします。
具体的には、あるリクエストに対して、Cloudflare Proxy の Ruleset でどんな処理が行われるのかトレースできます。設定が期待通りに動いているか自分で確認できます(サポートやコミュニティに問い合わせる前に)。
なお、API では以前から使えてました。利用例はこちらが参考になります。
実行
Trace したい宛先と付与したい情報をいれてリクエストを発行します。
- 今回はお試しのため、一個のリクエストが全部のルールにマッチするようにしました(ので、無理やり感ありますが、ご容赦ください)。
- Security の Rule で Block にマッチすると Trace が止まりましたが、Challenge の場合は Skip Challenge を On にすることで、次に進むことができました。
- 付与する情報の例として、Rule にマッチ・アンマッチするような任意のヘッダーを追加する、 Geo を指定する、などがあります。


結果
リクエストがそのフェーズの条件にマッチすれば、左端が緑の Matchded となりました。
右端の ▼ をクリックすると、どの ruleset(と、そのなかの rule )にリクエストがマッチしたのかがドリルダウンできました。
では、TRACE START から END まで順にたどっていきます。
URL normalization

有効化すると、入力リクエストの URL を正規化するオプションです。
今回のリクエストは URL path に %68
を入れたので h
に書き換えられました。
これにより、後続フェーズの Ruleset はこの URL を h 文字列でマッチできるようになります。
View rule detail
View rule detail(青字)をクリックします。
詳細( API での応答内容)が表示されます。
設定画面
Matched Rule の Name が外部リンク(青字)になっているので、クリックします。
当該 Rule の設定画面に飛び、実際の設定を確認することができます。
Transform Rules - URL Rewrites

URL リライトということで、その名の通り URL を書き換えています。
View rule detail
今回のリクエストに対して Path の /tr/
が /
に置換されるルールとなっています。
設定画面

Waiting Room

デジタル待合室で、リクエストをキューします。
設定画面
Hostname and Path でリクエスト URL とマッチさせています。
Configuration Rules

リクエスト・レスポンスに対する Proxy での動作オプションを変えれます。
View rule detail
設定画面

Origin Rules

オリジンサーバーに接続すときのルールを定義できます。
View rule detail
オリジンサーバーに接続する Host ヘッダーを入力リクエストから別の名前に置換しています。

設定画面

File Upload Scan

アップロードしたファイルに対するスキャンです。
現時点では Enterprise plan の特定のお客様に提供される機能です。
設定画面

WAF Custom Rules

Rules Language で expression とそれに対する action を定義し、自分自身の WAF ルールを作ることができます。
View rule detail
WAF の Machine Learning Score 40 以下にマッチさせいます。
設定画面

Rate Limiting Rules

オリジンサーバーに対するリクエストレート制限を行います。
リクエストレートのカウントや制限を送信元 IP に頼らないなど、柔軟な設定ができます。
View rule detail

設定画面

API Shield

API エンドポイントに対する保護を提供します。
下の例では API からのレスポンスにクレジットカード情報がレスポンスに含まれているのを検知し、警告しています(Sensitive Data Detection )。
設定画面
当該 Path に Schema Validation を定義しています。
WAF Managed Rules

Cloudflare が管理する WAF のルールです。
View rule detail
複数の Rule にマッチしていますが、たとえばこの様な内容です。
設定画面

Super Bot Fight Mode
今回は Bot Management を有効にしている Zone なので、 Super Bot Fight Mode は無効になっています。
Request Managed Headers

予め定義された Cloudflare マネージドの Request Header 変更をリクエストに適用します。
設定画面
リクエストに関する bot 関連の情報をヘッダーでオリジンに提供しています。
Transform Rules - HTTP Request Headers
リクエストヘッダーの書き換えを実施します。
View rule detail
設定画面

Cache Rules

Cache に関する設定を行います。
View rule detail
Edge Cache TTL を上書きするよう指示しています。
設定画面

Response Managed Headers

予め定義された Cloudflare マネージドの Response Header 変更をレスポンスに適用します。
設定画面
補足
curl で API を叩くサンプルも表示されています。
出力
{
"success": true,
"result": {
"trace": [
{
"step_name": "http_request_sanitize",
"type": "phase",
"matched": true,
"public_name": "URL Normalization",
"trace": [
{
"step_name": "921aaf52eb104dfcb18db1149dbbcab7",
"type": "ruleset",
"matched": true,
"description": "ruleset for controlling url normalization",
"name": "Entrypoint for url normalization ruleset",
"kind": "zone",
"trace": [
{
"step_name": "989066487cd545629681f5efa152ff9e",
"type": "rule",
"matched": true,
"action_parameter": {
"id": "70339d97bdb34195bbf054b1ebe81f76",
"version": "latest",
"overrides": {
"rules": [
{
"id": "78723a9e0c7c4c6dbec5684cb766231d",
"enabled": true
},
{
"id": "b232b534beea4e00a21dcbb7a8a545e9",
"enabled": false
},
{
"id": "20e18610e4a048d6b87430b3cb2d89a3",
"enabled": false
},
{
"id": "60444c0705d4438799584a15cca2cb7d",
"enabled": false
}
]
}
},
"expression": "true",
"trace": [
{
"step_name": "70339d97bdb34195bbf054b1ebe81f76",
"type": "ruleset",
"matched": true,
"description": "Created by the Cloudflare security team, this ruleset provides normalization on the URL path",
"name": "Cloudflare Normalization Ruleset",
"kind": "managed",
"trace": [
{
"step_name": "78723a9e0c7c4c6dbec5684cb766231d",
"type": "rule",
"matched": true,
"action_parameter": {
"uri": {
"path": {
"expression": "normalize_url_path(raw.http.request.uri.path)"
},
"origin": false
}
},
"description": "Normalization on the URL path, without propagating it to the origin"
}
]
}
]
}
]
}
]
},
{
"step_name": "http_request_transform",
"type": "phase",
"matched": true,
"public_name": "Transform Rules - URL Rewrites",
"trace": [
{
"step_name": "d6a7f5de8dc34ba5a562f2c1dcb82b24",
"type": "ruleset",
"matched": true,
"name": "transfer ruleset",
"kind": "zone",
"trace": [
{
"step_name": "5e9987321e62450c92c8a0259cb656b4",
"type": "rule",
"matched": true,
"action_parameter": {
"uri": {
"path": {
"expression": "regex_replace(http.request.uri.path, \"^/tr/\", \"/\")"
}
}
},
"expression": "(starts_with(http.host, \"s3-o\"))",
"description": "trace test"
}
]
}
]
},
{
"step_name": "waiting_room",
"type": "product",
"matched": true
},
{
"step_name": "http_config_settings",
"type": "phase",
"matched": true,
"public_name": "Configuration Rules",
"trace": [
{
"step_name": "e3112c9c198a44888ebb693e78218636",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "76493dc8e75f478c9adeff4aca1697eb",
"type": "rule",
"matched": true,
"action_parameter": {
"automatic_https_rewrites": false,
"autominify": {
"html": false,
"css": false,
"js": true
}
},
"expression": "(starts_with(http.host, \"s3-o\"))",
"description": "trace test"
}
]
}
]
},
{
"step_name": "http_request_origin",
"type": "phase",
"matched": true,
"public_name": "Origin Rules",
"trace": [
{
"step_name": "07c0e14bc5a54188a2684bac8e0eadb2",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "1c214943e4ce46979cb1a6408ea3fe5d",
"type": "rule",
"matched": true,
"action_parameter": {
"host_header": "s3-o.s3.ap-northeast-1.amazonaws.com"
},
"expression": "(starts_with(http.host, \"s3-o\"))",
"description": "s3-o Host override"
}
]
}
]
},
{
"step_name": "file_upload_scan",
"type": "product",
"matched": true
},
{
"step_name": "http_request_firewall_custom",
"type": "phase",
"matched": true,
"public_name": "WAF Custom Rules",
"trace": [
{
"step_name": "7d0b838c24a24a7b8d3e7b046db9e7bd",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "40ee6e0959ca4ca6bb5ee3716414886c",
"type": "rule",
"matched": true,
"expression": "cf.waf.ml.score le 40\n",
"description": "WAFML Test"
},
{
"step_name": "f988f2a562744036ba284374256b9507",
"type": "rule",
"matched": true,
"expression": "(http.host eq \"s3-o.oyama.cf\")",
"description": "trace test"
}
]
}
]
},
{
"step_name": "http_ratelimit",
"type": "phase",
"matched": true,
"public_name": "Rate Limiting Rules",
"trace": [
{
"step_name": "6ab99a1a40c543598a9606cbac5c5a73",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "698bde60fa6e4447b15750cfd4b2bc48",
"type": "rule",
"matched": true,
"expression": "(http.host eq \"s3-o.oyama.cf\")",
"description": "trace test"
}
]
}
]
},
{
"step_name": "api_shield",
"type": "product",
"matched": true
},
{
"step_name": "http_request_firewall_managed",
"type": "phase",
"matched": true,
"public_name": "WAF Managed Rules",
"trace": [
{
"step_name": "0fea3f5a773d4202baeb89c705a2e74a",
"type": "ruleset",
"matched": false,
"name": "root",
"kind": "root"
},
{
"step_name": "3c28d3a62c9d4016b29d6d059dad9afc",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "641f6b64ee1a4003b1bcdee81a9e823f",
"type": "rule",
"matched": true,
"action_parameter": {
"id": "c2e184081120413c86c3ab7e14069605",
"version": "latest",
"overrides": {
"action": "block"
},
"matched_data": {
"public_key": "pgjfQqjuZenvYduM9/olKGjAIlZPH187Ddnw3RZ28xw="
}
},
"expression": "true",
"description": "zone",
"trace": [
{
"step_name": "c2e184081120413c86c3ab7e14069605",
"type": "ruleset",
"matched": false,
"description": "Exposed credentials check rules",
"name": "Cloudflare Exposed Credentials Check Ruleset",
"kind": "managed"
}
]
},
{
"step_name": "de2be07400384f58841dee5400adc4bd",
"type": "rule",
"matched": true,
"action_parameter": {
"id": "efb7b8c949ac4650a09736fc376e9aee",
"version": "latest",
"overrides": {
"action": "managed_challenge",
"enabled": true
},
"matched_data": {
"public_key": "pgjfQqjuZenvYduM9/olKGjAIlZPH187Ddnw3RZ28xw="
}
},
"expression": "true",
"description": "zone",
"trace": [
{
"step_name": "efb7b8c949ac4650a09736fc376e9aee",
"type": "ruleset",
"matched": true,
"description": "Created by the Cloudflare security team, this ruleset is designed to provide fast and effective protection for all your applications. It is frequently updated to cover new vulnerabilities and reduce false positives.",
"name": "Cloudflare Managed Ruleset",
"kind": "managed",
"trace": [
{
"step_name": "1c3d3022129c48e9bb52e953fe8ceb2f",
"type": "rule",
"matched": true,
"description": "Anomaly:URL:Query String - Multiple Slashes, Relative Paths, CR, LF or NULL"
}
]
}
]
},
{
"step_name": "9ec7b4004fd3467c8837ec858abca029",
"type": "rule",
"matched": true,
"action_parameter": {
"id": "4814384a9e5d4991b9815dcfc25d2f1f",
"version": "latest",
"overrides": {
"categories": [
{
"category": "paranoia-level-4",
"enabled": false
}
],
"rules": [
{
"id": "6179ae15870a4bb7b2d480d4843b323c",
"action": "managed_challenge",
"score_threshold": 25
}
]
},
"matched_data": {
"public_key": "pgjfQqjuZenvYduM9/olKGjAIlZPH187Ddnw3RZ28xw="
}
},
"expression": "true",
"description": "zone",
"trace": [
{
"step_name": "4814384a9e5d4991b9815dcfc25d2f1f",
"type": "ruleset",
"matched": true,
"description": "Cloudflare's implementation of the Open Web Application Security Project (OWASP) ModSecurity Core Rule Set. We routinely monitor for updates from OWASP based on the latest version available from the official code repository",
"name": "Cloudflare OWASP Core Ruleset",
"kind": "managed",
"trace": [
{
"step_name": "3500d96add324dcbbc0a93b2bd22c723",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "920270: Invalid character in request (null character)"
},
{
"step_name": "a882bfdf91b3440b83020de61d8cf992",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "920271: Invalid character in request (non printable characters)"
},
{
"step_name": "6fac9ca10e764e06a0e242791813a269",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "920272: Invalid character in request (outside of printable chars below ascii 127)"
},
{
"step_name": "e358b09dbfa34f3194ee6e48fc1987a9",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "941110: XSS Filter - Category 1: Script Tag Vector"
},
{
"step_name": "1c2c87f990e34262a0fd890fa2bdaa68",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "941160: NoScript XSS InjectionChecker: HTML Injection"
},
{
"step_name": "1fd9e041e6944a5c9c080d19346650ed",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "941320: Possible XSS Attack Detected - HTML Tag Handler"
},
{
"step_name": "5a6f5a57cde8428ab0668ce17cdec0c8",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "942370: Detects classic SQL injection probings 2/3"
},
{
"step_name": "f5aebedc99a14c8d9e8cfa2ce5f94216",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 3
},
"description": "942431: Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)"
},
{
"step_name": "edf8c37cc81747d382690b3c77e82ce4",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 3
},
"description": "942460: Meta-Character Anomaly Detection Alert - Repetitive Non-Word Characters"
},
{
"step_name": "3e032e0fd1d34bbeb63eb77050e2c244",
"type": "rule",
"matched": true,
"action_parameter": {
"increment": 5
},
"description": "942511: SQLi bypass attempt by ticks detected"
},
{
"step_name": "6179ae15870a4bb7b2d480d4843b323c",
"type": "rule",
"matched": true,
"description": "949110: Inbound Anomaly Score Exceeded"
}
]
}
]
}
]
}
]
},
{
"step_name": "http_request_sbfm",
"type": "phase",
"matched": false,
"public_name": "Super Bot Fight Mode",
"trace": [
{
"step_name": "208412990ef24af5ae810b06cac52535",
"type": "ruleset",
"matched": false,
"name": "default",
"kind": "zone"
}
]
},
{
"step_name": "request_managed_headers",
"type": "product",
"matched": true,
"managed_headers": [
{
"id": "add_bot_protection_headers",
"enabled": true
},
{
"id": "add_client_certificate_headers",
"enabled": false
},
{
"id": "add_visitor_location_headers",
"enabled": false
},
{
"id": "add_true_client_ip_headers",
"enabled": false
},
{
"id": "remove_visitor_ip_headers",
"enabled": false
}
]
},
{
"step_name": "http_request_late_transform",
"type": "phase",
"matched": true,
"public_name": "Transform Rules - HTTP Request Headers",
"trace": [
{
"step_name": "397707921f77417082a4fbf3ca9d6c82",
"type": "ruleset",
"matched": true,
"name": "header modification",
"kind": "zone",
"trace": [
{
"step_name": "7f902770c157435096e8135d2bb34548",
"type": "rule",
"matched": true,
"action_parameter": {
"headers": {
"user-agent": {
"operation": "set",
"value": "02F2F1C1-5C6F-410D-A08F-BD2D014FD3F4"
}
}
},
"expression": "(starts_with(http.host, \"s3-v\")) or (starts_with(http.host, \"s3-o\"))",
"description": "s3-v UA override"
}
]
}
]
},
{
"step_name": "http_request_cache_settings",
"type": "phase",
"matched": true,
"public_name": "Cache Rules",
"trace": [
{
"step_name": "79d47699204049d188a99c28b7f17029",
"type": "ruleset",
"matched": true,
"name": "default",
"kind": "zone",
"trace": [
{
"step_name": "e37d98f1880d47e9be63150cf94bcfa1",
"type": "rule",
"matched": true,
"action_parameter": {
"cache": true,
"edge_ttl": {
"mode": "override_origin",
"default": 5
}
},
"expression": "(http.host eq \"s3-o.oyama.cf\")",
"description": "trace test"
}
]
}
]
},
{
"step_name": "response_managed_headers",
"type": "product",
"matched": true,
"managed_headers": [
{
"id": "remove_x-powered-by_header",
"enabled": false
},
{
"id": "add_security_headers",
"enabled": true
}
]
}
],
"status_code": 200
}
}
まとめ

Beta なので、試したらフィードバックを行い、改善を期待します。
青で強調されてる feedback をクリックしましょう。
Google Form でフィードバックできるようになってました。
私も早速入れておきました。