mirror of
https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin.git
synced 2026-07-21 03:28:59 +02:00
✨ Add ban html template (#142)
* ✨ Add ban html template * 📝 Add doc for custom ban page * 🍱 fix Mathieu work * 🍱 fix lint * 🍱 fix lint * 🍱 fix lint * 🍱 fix lint --------- Co-authored-by: Max Lerebourg <maxlerebourg@gmail.com>
This commit is contained in:
co-authored by
Max Lerebourg
parent
6059f23dc3
commit
615e7ccf69
+27
-10
@@ -8,6 +8,7 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
htmlTemplate "html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -72,6 +73,7 @@ type Bouncer struct {
|
||||
customHeader string
|
||||
crowdsecStreamRoute string
|
||||
crowdsecHeader string
|
||||
banTemplate *htmlTemplate.Template
|
||||
clientPoolStrategy *ip.PoolStrategy
|
||||
serverPoolStrategy *ip.PoolStrategy
|
||||
httpClient *http.Client
|
||||
@@ -118,6 +120,10 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
|
||||
}
|
||||
config.CrowdsecLapiKey = apiKey
|
||||
}
|
||||
var banTemplate *htmlTemplate.Template
|
||||
if config.BanHTMLFilePath != "" {
|
||||
banTemplate, _ = configuration.GetHTMLTemplate(config.BanHTMLFilePath)
|
||||
}
|
||||
|
||||
bouncer := &Bouncer{
|
||||
next: next,
|
||||
@@ -141,6 +147,7 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
|
||||
crowdsecStreamRoute: crowdsecStreamRoute,
|
||||
crowdsecHeader: crowdsecHeader,
|
||||
log: log,
|
||||
banTemplate: banTemplate,
|
||||
serverPoolStrategy: &ip.PoolStrategy{
|
||||
Checker: serverChecker,
|
||||
},
|
||||
@@ -219,13 +226,13 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
remoteIP, err := ip.GetRemoteIP(req, bouncer.serverPoolStrategy, bouncer.customHeader)
|
||||
if err != nil {
|
||||
bouncer.log.Error(fmt.Sprintf("ServeHTTP:getRemoteIp ip:%s %s", remoteIP, err.Error()))
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
return
|
||||
}
|
||||
isTrusted, err := bouncer.clientPoolStrategy.Checker.Contains(remoteIP)
|
||||
if err != nil {
|
||||
bouncer.log.Error(fmt.Sprintf("ServeHTTP:checkerContains ip:%s %s", remoteIP, err.Error()))
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
return
|
||||
}
|
||||
// if our IP is in the trusted list we bypass the next checks
|
||||
@@ -248,7 +255,7 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
bouncer.log.Debug(fmt.Sprintf("ServeHTTP:Get ip:%s isBanned:false %s", remoteIP, cacheErrString))
|
||||
if cacheErrString != cache.CacheMiss {
|
||||
bouncer.log.Error(fmt.Sprintf("ServeHTTP:Get ip:%s %s", remoteIP, cacheErrString))
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -256,7 +263,7 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if value == cache.NoBannedValue {
|
||||
handleNextServeHTTP(bouncer, remoteIP, rw, req)
|
||||
} else {
|
||||
handleErrorServeHTTP(bouncer, remoteIP, value, rw, req)
|
||||
handleRemediationServeHTTP(bouncer, remoteIP, value, rw, req)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -268,7 +275,7 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
handleNextServeHTTP(bouncer, remoteIP, rw, req)
|
||||
} else {
|
||||
bouncer.log.Debug(fmt.Sprintf("ServeHTTP isCrowdsecStreamHealthy:false ip:%s", remoteIP))
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
}
|
||||
} else {
|
||||
value, err := handleNoStreamCache(bouncer, remoteIP)
|
||||
@@ -276,7 +283,7 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
handleNextServeHTTP(bouncer, remoteIP, rw, req)
|
||||
} else {
|
||||
bouncer.log.Debug(fmt.Sprintf("ServeHTTP:handleNoStreamCache ip:%s isBanned:%v %s", remoteIP, value, err.Error()))
|
||||
handleErrorServeHTTP(bouncer, remoteIP, value, rw, req)
|
||||
handleRemediationServeHTTP(bouncer, remoteIP, value, rw, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,8 +316,18 @@ type Login struct {
|
||||
Expire string `json:"expire"`
|
||||
}
|
||||
|
||||
func handleErrorServeHTTP(bouncer *Bouncer, remoteIP, remediation string, rw http.ResponseWriter, req *http.Request) {
|
||||
bouncer.log.Debug(fmt.Sprintf("handleErrorServeHTTP ip:%s remediation:%s", remoteIP, remediation))
|
||||
func handleBanServeHTTP(bouncer *Bouncer, rw http.ResponseWriter) {
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
if bouncer.banTemplate != nil {
|
||||
err := bouncer.banTemplate.Execute(rw, map[string]string{"caca": "caca"})
|
||||
if err != nil {
|
||||
bouncer.log.Info(fmt.Sprintf("handleBanServeHTTP banTemplateServe %s", err.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleRemediationServeHTTP(bouncer *Bouncer, remoteIP, remediation string, rw http.ResponseWriter, req *http.Request) {
|
||||
bouncer.log.Debug(fmt.Sprintf("handleRemediationServeHTTP ip:%s remediation:%s", remoteIP, remediation))
|
||||
if bouncer.captchaClient.Valid && remediation == cache.CaptchaValue {
|
||||
if bouncer.captchaClient.Check(remoteIP) {
|
||||
handleNextServeHTTP(bouncer, remoteIP, rw, req)
|
||||
@@ -319,14 +336,14 @@ func handleErrorServeHTTP(bouncer *Bouncer, remoteIP, remediation string, rw htt
|
||||
bouncer.captchaClient.ServeHTTP(rw, req, remoteIP)
|
||||
return
|
||||
}
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
}
|
||||
|
||||
func handleNextServeHTTP(bouncer *Bouncer, remoteIP string, rw http.ResponseWriter, req *http.Request) {
|
||||
if bouncer.appsecEnabled {
|
||||
if err := appsecQuery(bouncer, remoteIP, req); err != nil {
|
||||
bouncer.log.Debug(fmt.Sprintf("handleNextServeHTTP ip:%s isWaf:true %s", remoteIP, err.Error()))
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
handleBanServeHTTP(bouncer, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user