From e20ccc5d0c0c35eef46dd456867b3cdbd8167da5 Mon Sep 17 00:00:00 2001 From: omer <86437599+highpingblorg@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:54:07 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20injecting=20r?= =?UTF-8?q?equest=20header=20value=20into=20ban=20HTML=20template=20(#296)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add parameter to specify Request header value to inject in HTML template * Add documentation for specifying request header value * Fix example in docs for CustomHeader * Update parameter name to traceCustomHeader * Ensure naming is consitent with project --- README.md | 5 +++++ bouncer.go | 18 +++++++++++++++++- examples/custom-ban-page/README.md | 2 ++ pkg/configuration/configuration.go | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ce09359..e245810 100644 --- a/README.md +++ b/README.md @@ -497,6 +497,10 @@ make run - string - default: "" - Path where the ban html file is stored (default empty ""=disabled) +- TraceHeadersCustomName + - string + - default: "" + - Request Header name whose value to inject in ban HTML response (default empty ""=disabled) ### Configuration @@ -603,6 +607,7 @@ http: captchaGracePeriodSeconds: 1800 captchaHTMLFilePath: /captcha.html banHTMLFilePath: /ban.html + traceHeadersCustomName: X-Request-ID metricsUpdateIntervalSeconds: 600 ``` diff --git a/bouncer.go b/bouncer.go index eff1d19..f738c90 100644 --- a/bouncer.go +++ b/bouncer.go @@ -108,6 +108,7 @@ type Bouncer struct { crowdsecHeader string redisUnreachableBlock bool banTemplate *htmltemplate.Template + traceCustomHeader string clientPoolStrategy *ip.PoolStrategy serverPoolStrategy *ip.PoolStrategy httpClient *http.Client @@ -193,6 +194,7 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam remediationStatusCode: config.RemediationStatusCode, redisUnreachableBlock: config.RedisCacheUnreachableBlock, banTemplate: banTemplate, + traceCustomHeader: config.TraceHeadersCustomName, crowdsecStreamRoute: crowdsecStreamRoute, crowdsecHeader: crowdsecHeader, log: log, @@ -402,7 +404,21 @@ func (bouncer *Bouncer) handleBanServeHTTP(rw http.ResponseWriter, req *http.Req if req.Method == http.MethodHead { return } - err := bouncer.banTemplate.Execute(rw, map[string]string{"RemediationReason": reason, "ClientIP": remoteIP}) + templateData := map[string]string{ + "RemediationReason": reason, + "ClientIP": remoteIP, + } + + if bouncer.traceCustomHeader != "" { + headerVal := req.Header.Get(bouncer.traceCustomHeader) + + if headerVal != "" { + templateData["TraceID"] = headerVal + } + } + + err := bouncer.banTemplate.Execute(rw, templateData) + if err != nil { bouncer.log.Error("handleBanServeHTTP banTemplateServe " + err.Error()) } diff --git a/examples/custom-ban-page/README.md b/examples/custom-ban-page/README.md index e81c5e4..21c159d 100644 --- a/examples/custom-ban-page/README.md +++ b/examples/custom-ban-page/README.md @@ -50,8 +50,10 @@ make run_custom_ban_page In the html of the ban page, you can use: - {{ .ClientIP }} to display the IP used to ban the request. - {{ .RemediationReason }} that convert on runtime into why the ban page is served. It's an enum with "APPSEC", "LAPI", "TECHNICAL_ISSUE" and it is useful to help user understand why the request is blocked. +- {{ .CustomHeader }} value of the specified Request Header (for example X-Request-ID) ``` + ``` With the above tweak and some other js, you can customize your ban page on runtime. diff --git a/pkg/configuration/configuration.go b/pkg/configuration/configuration.go index cbda4ca..be78b80 100644 --- a/pkg/configuration/configuration.go +++ b/pkg/configuration/configuration.go @@ -86,6 +86,7 @@ type Config struct { RedisCacheDatabase string `json:"redisCacheDatabase,omitempty"` RedisCacheUnreachableBlock bool `json:"redisCacheUnreachableBlock,omitempty"` BanHTMLFilePath string `json:"banHtmlFilePath,omitempty"` + TraceHeadersCustomName string `json:"traceHeadersCustomName,omitempty"` CaptchaHTMLFilePath string `json:"captchaHtmlFilePath,omitempty"` CaptchaProvider string `json:"captchaProvider,omitempty"` CaptchaCustomJsURL string `json:"captchaCustomJsUrl,omitempty"`