From 9770398ab0f341e546d5e42a5faa744269f5996e Mon Sep 17 00:00:00 2001 From: Josh Knapp Date: Thu, 14 May 2026 08:52:01 -0700 Subject: [PATCH] coraza: pass var(txn.real_ip) instead of src to Coraza (real client IP in WAF logs) --- templates/hap_coraza_spoe_engine.tpl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/templates/hap_coraza_spoe_engine.tpl b/templates/hap_coraza_spoe_engine.tpl index 3e55db5..ff282d0 100644 --- a/templates/hap_coraza_spoe_engine.tpl +++ b/templates/hap_coraza_spoe_engine.tpl @@ -44,8 +44,14 @@ spoe-agent coraza # Arg order/names are mandatory: Coraza-SPOA parses positionally and renames # break the agent. `app=str(haproxy)` is the literal application name from # coraza-spoa's config.yaml `applications:` block. +# +# src-ip uses var(txn.real_ip) — HAProxy resolves the real client IP at the +# top of the frontend (CF-Connecting-IP > X-Real-IP > X-Forwarded-For > src, +# only honoring those headers from trusted proxies). Falls back to `src` +# when no proxy headers are present. This is what shows up as `client_ip` +# in /var/log/coraza/audit.log and the rule manager's view-matches panel. spoe-message coraza-req - args app=str(haproxy) src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body + args app=str(haproxy) src-ip=var(txn.real_ip) src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body # Group binding for send-spoe-group invocation in the frontend. One group, # one message; could add more in the future (e.g. coraza-res for response