Under attack¶
Each step is one API call (API access defines $API and $ZP_KEY). It
is live on all edges in about 30 seconds and recorded with user and diff in the change
history (GET /services/{fqdn}/history). Change one thing at a time and give it a minute.
1. See what gets through¶
Watch the allowed traffic, not the blocked, and look for what the attack has in common: one path, country, fingerprint or network.
curl -s -H "Authorization: Bearer $ZP_KEY" \
"$API/services/www.example.com/logs?view=allowed&type=top_ja4&range=15m&limit=10"
Other type values: top_uris, top_countries, top_asns, top_ips, see
Logs and metrics. Portal: Forensics.
2. Switch the defense posture¶
curl -s -X PATCH -H "Authorization: Bearer $ZP_KEY" -H 'Content-Type: application/json' \
$API/services/www.example.com -d '{"defense_posture": "under_attack"}'
under_attackis the most aggressive baseline, for example 200 instead of 1000 requests per fingerprint per 10 s before the challenge. Service capacity (sensitivity) rests while it is set.- Applying a posture overwrites rate limits, proof-of-work, WAF, slow-HTTP and cache
settings with its values; the allowlist and your own rules stay. Set
standardagain afterwards. - Refused for
service_profileapiandhls, whose clients cannot solve a challenge: useoffand set the limits directly, see Rate limits.
Portal: Overview → Defense Posture.
3. Deny what the attack has in common¶
protection_rules is one list, and a PATCH replaces it: read it, append, send it back.
RULE='{"name": "flood-ja4", "match": {"fingerprint": ["t13d1516h2_8daaf6152771_b0da82dd1658"]}, "action": "deny"}'
curl -s -H "Authorization: Bearer $ZP_KEY" $API/services/www.example.com \
| jq --argjson r "$RULE" '{protection_rules: (.protection_rules + [$r])}' \
| curl -s -X PATCH -H "Authorization: Bearer $ZP_KEY" -H 'Content-Type: application/json' \
$API/services/www.example.com -d @-
denyanswers403,block429,dropnothing,challengesends the proof-of-work. A fingerprint is shared by everyone on the same software: if your users carry it, usechallenge.- Several countries, networks or paths go into one rule as a list;
ratemakes a rule fire only above a threshold. Shape and order: Protection rules. - Remove it afterwards the same way, with
jq '{protection_rules: [.protection_rules[] | select(.name != "flood-ja4")]}'.
Portal: Protection → ACL Rules, or the one-click rule from the Forensics top lists.
4. Allowlist a partner¶
Machine clients (APIs, monitoring, webhooks, payment callbacks) cannot solve a challenge. Add their address to the allowlist and send the whole object back:
curl -s -H "Authorization: Bearer $ZP_KEY" $API/services/www.example.com \
| jq '{protection_allowlist: ((.protection_allowlist // {}) | .ips = ((.ips // []) + ["198.51.100.20"]))}' \
| curl -s -X PATCH -H "Authorization: Bearer $ZP_KEY" -H 'Content-Type: application/json' \
$API/services/www.example.com -d @-
- Every entry becomes an
allowrule at the top: exempt from all protection rules, blocklists, rate limits and the challenge; only the WAF still inspects. Automatic mitigation never acts against it. ips: up to 128, none broader than/16(IPv4) or/32(IPv6). To exempt one address on one path from single stages only, use askiprule, for example{"match": {"ip": ["198.51.100.20"], "path": ["/api/webhook"]}, "action": "skip", "skip": ["pow", "rate_limits"]}.
Portal: Advanced → Protection Allowlist.
Emergency actions¶
| Action | PATCH /services/{fqdn} |
Effect |
|---|---|---|
| Block | a deny, block or drop rule (step 3) |
sources, ranges or fingerprints refused |
| Lockdown | {"pow": {"always_challenge": true}} |
every request behind the proof-of-work challenge |
| Maintenance mode | {"maintenance_mode": true} |
the edge serves a branded maintenance page and does not contact the origin |
| Auto mitigation (beta) | {"auto_mitigation": true} |
the platform sets time-limited rules itself, see below |
Auto mitigation, off by default:
- Acts only when the origin is in distress (latency 3× baseline with 5 % errors, origin errors, or a 5× surge) and the traffic looks like an attack against your own history.
- Challenges the fingerprint that grew most (plus country and network when one country carries the increase) with TTL'd rules; blocks after five minutes without effect.
- Never touches the allowlist or anything above 5 % of your legitimate traffic; switched off, it only produces a suggestion and a ticket.
Avoid¶
allowrules for a country or network, even your own provider: everything inside skips the whole pipeline.- Deleting posture rules: raise a threshold or switch posture.
- Chasing countries one by one: deny everything outside your markets in one rule with
match_mode: orandnegate. - Guessing at the origin's
maxconn, see Origins. - Judging a fix from one client: test from several networks.
When to call support¶
- The edge figures fall while the service stays unreachable: the attack is larger than the line. Flowspec acts within seconds by itself; above the edge of a dedicated site the agreed policy applies, see Sites, pools and dedicated edges.
- Posture and rules do not help, or an
allowrule covers the requests that hurt. - A visitor reports an error page: send its Ray ID and Edge Node; we find the request within 14 days.
- A write-up of the attack afterwards.