diff --git a/docs/features/under_attack_mode/README.md b/docs/features/under_attack_mode/README.md index 210cad7d..991db3cb 100644 --- a/docs/features/under_attack_mode/README.md +++ b/docs/features/under_attack_mode/README.md @@ -6,7 +6,7 @@ **Under Attack Mode (UAM)** is a WebShield feature that lets a server administrator put one or more **domains** (optionally scoped to specific URL paths) "under attack". While a domain is under attack, every matching HTTP request is first served a lightweight **JavaScript splash challenge** instead of being passed straight to the site: -- Regular browsers solve the challenge transparently and receive a short-lived cookie; subsequent requests carrying a valid cookie flow through normally. +- Regular browsers solve the challenge transparently and receive a clearance cookie (its lifetime is configurable per rule); subsequent requests carrying a valid cookie flow through normally. - Simple bots that cannot run the challenge never reach the application. UAM is a **server-wide administrator feature**. It is distinct from the per-IP GreyList / Anti-bot Challenge: UAM decisions are keyed on the request's `(domain, path)` and are configured explicitly by the administrator, rather than being driven by the state of an IP list. @@ -21,14 +21,14 @@ UAM is not available on every environment WebShield supports. Before relying on ## How it works -- A domain is placed under attack by creating a **UAM rule**. A rule is a `(domain, optional path-set)` tuple. +- A domain is placed under attack by creating a **UAM rule**. A rule pairs a `domain` (optionally narrowed to a path-set) with the clearance-cookie lifetime to grant once a visitor solves the challenge. - When a request matches an **active** rule, WebShield returns the JS splash challenge and does not forward the request to the backend until the visitor passes. - UAM is **fail-open**: if the feature is disabled, the request has no `Host`, the rule store cannot be read, or no active rule matches, the request simply proceeds through the normal WebShield flow. UAM never blocks a request outright — it only inserts a challenge. - The feature is gated behind a single on/off toggle that is **off by default**, and all UAM state is stored on the server itself. ## Prerequisites -- WebShield version >= 1.44.2 installed and running in an environment where UAM is available (see the note above). +- WebShield version >= 1.45.0 installed and running in an environment where UAM is available (see the note above). The core rule commands and the service toggle have been available since 1.44.2; the per-rule challenge-cookie lifetime and the `uam test` command described below were added in 1.45.0. - Root access to the server. UAM is managed with the `imunify360-wsctl uam` command, which must be run as `root`. ## Enabling and disabling UAM @@ -49,16 +49,25 @@ Disabling the feature stops all challenges immediately; your rules are preserved ## Managing rules -A rule is created from a small JSON payload. Only `domain` is required; `label` (a free-text note) and `paths` (path scoping) are optional. A new rule is active as soon as it is created. +A rule is created from a small JSON payload. The fields are: + +| Field | Required | Description | +|-|-|-| +|`domain`|yes|Exact hostname to put under attack (up to 253 characters).| +|`cookie_ttl`|yes|How long a visitor's clearance cookie stays valid after they solve the challenge, before they are challenged again. A Go-style duration string using the units `s`, `m`, `h` (compound values such as `1h30m` are allowed), between **10 seconds and 3 days**.| +|`label`|no|Free-text note (up to 128 characters).| +|`paths`|no|Path-scoping block (see [Path scoping](#path-scoping) below). Omit it to cover the whole domain.| + +A new rule is active as soon as it is created.
``` -# Put a whole domain under attack: -imunify360-wsctl uam add '{"domain":"shop.example.com","label":"Black Friday"}' +# Put a whole domain under attack; re-challenge visitors after 1 hour: +imunify360-wsctl uam add '{"domain":"shop.example.com","cookie_ttl":"1h","label":"Black Friday"}' # Scope the rule to specific paths (see "Path scoping" below): -imunify360-wsctl uam add '{"domain":"shop.example.com","paths":{"mode":"include","matchers":[{"value":"/checkout","condition":"prefix"}]}}' +imunify360-wsctl uam add '{"domain":"shop.example.com","cookie_ttl":"30m","paths":{"mode":"include","matchers":[{"value":"/checkout","condition":"prefix"}]}}' ```
@@ -74,25 +83,26 @@ imunify360-wsctl uam list --domain shop.example.com --json -The table shows `ID ACTIVE DOMAIN LABEL`. The `ID` is a positive integer assigned by WebShield when the rule is created; you use it to edit or delete the rule. +The table shows `ID ACTIVE DOMAIN COOKIE_TTL LABEL`. The `ID` is a positive integer assigned by WebShield when the rule is created; you use it to edit or delete the rule.
``` imunify360-wsctl uam list -ID ACTIVE DOMAIN LABEL -7 yes shop.example.com Black Friday +ID ACTIVE DOMAIN COOKIE_TTL LABEL +7 true shop.example.com 1h Black Friday ```
-Edit a rule with a partial JSON payload — only `active`, `label`, and `paths` can be changed. Temporarily pausing a rule is done by setting `active` to `false`: +Edit a rule with a partial JSON payload — only `active`, `cookie_ttl`, `label`, and `paths` can be changed. Temporarily pausing a rule is done by setting `active` to `false`:
``` -imunify360-wsctl uam edit 7 '{"active":false}' # pause the rule (keep it for later) -imunify360-wsctl uam edit 7 '{"label":"BF sale"}' # rename +imunify360-wsctl uam edit 7 '{"active":false}' # pause the rule (keep it for later) +imunify360-wsctl uam edit 7 '{"cookie_ttl":"2h"}' # change the clearance-cookie lifetime +imunify360-wsctl uam edit 7 '{"label":"BF sale"}' # rename imunify360-wsctl uam edit 7 '{"paths":null}' # clear paths -> back to whole-domain ``` @@ -129,6 +139,52 @@ imunify360-wsctl uam add '{"domain":"shop.example.com","paths":{"mode":"exclude"
+## Testing which rule matches a URL + +`uam test` checks whether a given URL would be challenged, using the **exact same matching as live traffic**. It is the quickest way to verify a rule's path scoping without generating real requests. + +
+ +``` +imunify360-wsctl uam test example.com/path # scheme optional; host required +imunify360-wsctl uam test https://shop.example.com/api?x=1 +``` + +
+ +The scheme is optional, the host is required, and both the path and the query string are significant (only a trailing `#fragment` is ignored, and an empty path is treated as `/`). When a rule matches, the command prints that rule as JSON; otherwise it prints `No matching rule`: + +
+ +``` +imunify360-wsctl uam test shop.example.com/checkout +[ + { + "id": 7, + "owner": "admin", + "active": true, + "label": "Black Friday", + "domain": "shop.example.com", + "cookie_ttl": "1h", + "paths": { + "mode": "include", + "matchers": [ + { + "value": "/checkout", + "condition": "prefix" + } + ] + } + } +] +``` + +
+ +:::tip Note +`uam test` only reports a match while UAM is enabled; if the service is disabled it returns a `service_disabled` error. +::: + ## Monitoring challenges Each challenge served for a rule is counted. Use `counters` to see which rules are actively challenging traffic, busiest first: @@ -151,7 +207,7 @@ The single optional argument is auto-detected: a positive integer is treated as ``` imunify360-wsctl uam counters ID ACTIVE DOMAIN HITS LABEL -7 yes shop.example.com 1523 Black Friday +7 true shop.example.com 1523 Black Friday ```