Skip to content

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_attack is 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 standard again afterwards.
  • Refused for service_profile api and hls, whose clients cannot solve a challenge: use off and 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 @-
  • deny answers 403, block 429, drop nothing, challenge sends the proof-of-work. A fingerprint is shared by everyone on the same software: if your users carry it, use challenge.
  • Several countries, networks or paths go into one rule as a list; rate makes 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 allow rule 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 a skip rule, 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

  • allow rules 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: or and negate.
  • 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 allow rule 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.