- Cloudflare API Token with
Zone:Rulesets:Editpermission - Zone IDs for each domain
curl -s -X GET \
"https://api.cloudflare.com/client/v4/zones?account.id=YOUR_ACCOUNT_ID&status=active" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" | jq '.result[] | {name: .name, id: .id}'curl -s -X GET \
"https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" | \
jq '.result[] | select(.phase == "http_request_firewall_custom")'
If no existing http_request_firewall_custom ruleset exists:
curl -s -X POST \
"https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"name": "default",
"description": "WAF Custom Rules",
"kind": "zone",
"phase": "http_request_firewall_custom",
"rules": [
{
"action": "block",
"description": "Block traffic from Russia, Belarus, Iran, and North Korea",
"enabled": true,
"expression": "(ip.src.country in {\"RU\" \"BY\" \"IR\" \"KP\"})"
}
]
}' | jq '.success'If a ruleset already exists (use the ruleset ID from step 2):
curl -s -X PUT \
"https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets/RULESET_ID" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"description": "WAF Custom Rules",
"rules": [
{
"action": "block",
"description": "Block traffic from Russia, Belarus, Iran, and North Korea",
"enabled": true,
"expression": "(ip.src.country in {\"RU\" \"BY\" \"IR\" \"KP\"})"
}
]
}' | jq '.success'curl -s -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets/RULESET_ID"