HiTechCloud Panel - web application firewall rules
==================================================

Files here are read in filename order. Every *.conf is loaded; anything else
(this file included) is ignored, which is how a .disabled or .example suffix
takes a file out of service without deleting it.

One rule per line. Blank lines and lines starting with # are ignored.

    id:1001 phase:query act:block sev:critical score:5 tag:attack-sqli \
        msg:"union select" rx:(?i)\bunion\b[\s/*]+select\b

(written on one line - there is no line continuation)

    id      Required, unique across every file. This is what the panel's WAF
            log viewer shows, and what an administrator excludes a rule by.
            Keep local rules in the 900000+ range so a panel upgrade that adds
            shipped rules can never collide with yours.

    phase   Required. Which part of the request the pattern runs against:

              path     the URL path, percent-decoded
              query    the query string
              body     the request body, when it is a type worth reading and
                       within MAX_BODY_BYTES
              header   every request header, as "Name: value" lines
              ua       the User-Agent header alone
              cookie   the Cookie header
              method   the request method

            path, query, body, header, ua and cookie are each matched against
            the raw text and against it percent-decoded up to twice, so a
            payload encoded twice to slip past inspection is still seen.

    rx      Required, and MUST BE LAST: everything after "rx:" to the end of
            the line is the pattern, because patterns contain spaces and
            colons. Go regexp syntax (RE2) - no backreferences, no lookaround.
            Case-insensitive matching is "(?i)" at the front.

    act     block (default) or challenge. "challenge" serves the proof-of-work
            interstitial instead of an error: use it for traffic that is
            suspicious rather than hostile, where a real browser should be let
            through and an unattended script should not.

    score   Points contributed on a match, default 5. A request is acted on
            once its total reaches SCORE_THRESHOLD in waf.conf (also 5 by
            default), so a default rule fires on its own and a rule scored
            below the threshold only matters alongside something else. That is
            how the weaker signals in 60-bad-bots.conf are kept from acting on
            their own.

    sev     Free text shown in the log viewer: critical, error, warning,
            notice.

    tag     Repeatable. Shown in the log viewer and useful for grouping.

    msg     Quoted, human-readable. Shown in the log viewer.


EXTENDING AND OVERRIDING
------------------------

Add your own file - 90-local.conf is the conventional name and is loaded last.
Shipped files are replaced on upgrade, so a change made in one of them will not
survive; put local work in your own file.

There is no "remove this rule" directive. To silence a shipped rule, either
lower its site's mode to detect while you investigate, or copy the shipped file
to a name that sorts later, delete the line, and rename the original to
.disabled.

After editing anything here:

    hitechcloudcli native-waf check      # parse everything, report bad lines
    hitechcloudcli native-waf reload     # make it live, no dropped connections

A line that does not parse is skipped and reported by `check`; it never stops
the other rules loading, and it never stops the service starting.


TESTING A CHANGE SAFELY
-----------------------

Put the site in detect mode first. It logs every decision, including what
enforce would have blocked, and blocks nothing:

    hitechcloudcli native-waf mode <domain> detect

Watch /var/log/hitechcloud/native/waf/<domain>.log, or the panel's WAF log
page, and only then switch to enforce.
