diff --git a/VERSION b/VERSION index f1498dc..510ab47 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2026.08.7 +2026.08.8 diff --git a/templates/hap_coraza_spoe_engine.tpl b/templates/hap_coraza_spoe_engine.tpl index ff282d0..058e35e 100644 --- a/templates/hap_coraza_spoe_engine.tpl +++ b/templates/hap_coraza_spoe_engine.tpl @@ -37,7 +37,22 @@ spoe-agent coraza timeout processing 100ms use-backend coraza-spoa-backend - log global + + # NO `log global` here, deliberately. + # + # `log global` in a spoe-agent emits one line PER INSPECTED REQUEST, e.g. + # SPOE: [coraza] sid=537 st=0 0/0/0/0/0 32/32 0/0 0/467 + # Measured on whp01 immediately after access logging started working: + # 618 SPOE lines vs 669 real access lines -- it was ~48% of the log volume, + # i.e. it would roughly DOUBLE the edge's log footprint (~400 MB/day extra) + # to record `st=0` over and over. + # + # It carries nothing incident response needs: the WAF's verdict is already + # visible in the access log line (status 403 + the `id=` UUID, which joins + # to /var/log/coraza/audit.log for the rule_id), and per-transaction WAF + # detail is written by the SPOA itself to /var/log/coraza/spoa.log. + # Agent-level failures still surface via `option set-on-error error` -> + # var(txn.coraza.error) and the fail-open path in hap_listener.tpl. # Per-request inspection message. No `event` directive — fires only when # explicitly invoked from haproxy.cfg via `http-request send-spoe-group`. diff --git a/templates/hap_listener.tpl b/templates/hap_listener.tpl index e15a17d..13b323f 100644 --- a/templates/hap_listener.tpl +++ b/templates/hap_listener.tpl @@ -29,7 +29,15 @@ frontend web # Any new capture MUST be appended AFTER this line, never inserted # above it, or the slot indices in the log-format silently shift and # the access log starts attributing the wrong string to the wrong field. - http-request capture req.hdr(User-Agent) len 200 + # req.fhdr(), NOT req.hdr(): req.hdr() treats the header as a comma- + # separated list and returns only the LAST element. Real User-Agent strings + # contain commas -- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) + # AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" + # captured with req.hdr() logs as just "like Gecko) Chrome/131.0.0.0 + # Safari/537.36", silently losing the platform half -- which is exactly the + # half you need to tell a spoofed crawler from a real browser. + # Observed in production on whp01 before this was corrected. + http-request capture req.fhdr(User-Agent) len 200 # --- Access logging ----------------------------------------------------- # Scoped to THIS frontend on purpose: it references capture slots and