package servewaf // The heuristic crowdsec. It reads SWWAF_CROWDSEC_LAPI_URL, and the decisions // through the reputation lists. import ( "context" "time" "sneak.berlin/go/smallwebwaf/internal/bans" "sneak.berlin/go/smallwebwaf/internal/reputation" "sneak.berlin/go/smallwebwaf/internal/requestlog" ) // crowdSec refuses a request when a decision of the CrowdSec decision list on // the client is in force at now. It then notes the list, as noteHit does, and // bans the client until that decision ends. Its figures are the decision's // scenario and when it ends. type crowdSec struct{} func (crowdSec) name() string { return "crowdsec" } func (crowdSec) check(_ context.Context, rq *request, now time.Time) *verdict { decision, listed := rq.crowdSecDecisionInForce(now) if !listed { return nil } rq.noteHit(bans.ReputationHit{Source: rq.h.config.CrowdSecDecisionsURL}, "listed by the CrowdSec decision list") rq.banForCrowdSec(now, decision) return &verdict{ action: requestlog.ActionBanned, figures: map[string]any{ "scenario": decision.Scenario, "expires": requestlog.FormatTime(decision.Expires), }, } } // crowdSecDecisionInForce returns the decision of the CrowdSec decision list on // the client that is in force at now, and reports whether there is one, which // the heuristic crowdsec refuses the request for. func (rq *request) crowdSecDecisionInForce( now time.Time, ) (reputation.Decision, bool) { return rq.h.lists.CrowdSecDecision(rq.client, now) }