rproxy and servewaf replace the one-process smallwebwaf (closes #172, closes #165)
check / check (push) Failing after 23m49s

`smallwebwaf` with no command now prints the commands and exits with status 2.
The image runs rproxy, or servewaf with SMALLWEBWAF_COMMAND=servewaf. The
passing-on code, its settings and its log fields and metric go. internal/proxy
keeps the checks, answers, reports and own endpoints; its tests run through the
real rproxy. The documents describe the pair.

Judgement call: clients.json keeps token_refused, since state files refuse unknown fields.
Deviation: script/gitea-requests sets SWWAF_LOG_REQUEST_HEADERS, to label requests.

Model: opus-5-5
This commit is contained in:
2026-11-05 10:33:24 +00:00
committed by sneak
parent 17c5dd2438
commit ac1a69e863
71 changed files with 2653 additions and 5493 deletions
+19 -27
View File
@@ -92,10 +92,9 @@ type History struct {
ASName string `json:"as_name,omitempty"`
Country string `json:"country,omitempty"`
LookedUp time.Time `json:"looked_up,omitzero"`
// Requests are all the client's requests: Forwarded those passed to
// the app, Refused those refused before anything reached it, a 401 at
// smallwebwaf's own endpoints included, and neither the others
// smallwebwaf answered there.
// Requests are all the client's requests: Forwarded those servewaf allowed,
// Refused those it refused, and neither those for a path under
// /_smallwebwaf/.
Requests int64 `json:"requests"`
Forwarded int64 `json:"forwarded"`
Refused int64 `json:"refused"`
@@ -124,21 +123,20 @@ type Offences struct {
// Limit is its requests that broke a rate limit, a byte limit or the
// error burst, Attack those that were a clear sign of attack, a match
// of a ban rule or a request for a trap path, RuleBlocked those a block
// rule refused, WAFBlocked those the Core Rule Set refused, and
// TokenRefused those refused for a missing or wrong token.
Limit int64 `json:"limit"`
Attack int64 `json:"attack"`
RuleBlocked int64 `json:"rule_blocked"`
WAFBlocked int64 `json:"waf_blocked"`
TokenRefused int64 `json:"token_refused"`
// rule refused, and WAFBlocked those the Core Rule Set refused.
Limit int64 `json:"limit"`
Attack int64 `json:"attack"`
RuleBlocked int64 `json:"rule_blocked"`
WAFBlocked int64 `json:"waf_blocked"`
// TokenRefused is what a clients.json written by an earlier version gives,
// which must still load. Nothing adds to it.
TokenRefused int64 `json:"token_refused,omitempty"`
}
// Request is what a client's history keeps of one of its requests.
type Request struct {
// Forwarded is true for a request passed to the app, Refused for one
// refused before anything reached it, a 401 at smallwebwaf's own
// endpoints included. Both are false for any other request smallwebwaf
// answered there.
// Forwarded is true for a request servewaf allowed, and Refused for one it
// refused. Both are false for a request for a path under /_smallwebwaf/.
Forwarded bool
Refused bool
// Status is what the client was sent, 0 if nothing was.
@@ -149,14 +147,12 @@ type Request struct {
ResponseBytes int64
// BrokeLimit is true for a request that broke a rate limit, a byte
// limit or the error burst, Attack for one that matched a ban rule or
// asked for a trap path, RuleBlocked for one a block rule refused,
// WAFBlocked for one the Core Rule Set refused, and TokenRefused for
// one refused for a missing or wrong token.
BrokeLimit bool
Attack bool
RuleBlocked bool
WAFBlocked bool
TokenRefused bool
// asked for a trap path, RuleBlocked for one a block rule refused, and
// WAFBlocked for one the Core Rule Set refused.
BrokeLimit bool
Attack bool
RuleBlocked bool
WAFBlocked bool
}
// New returns a Limiter for limits, with no client counted yet, whose
@@ -334,10 +330,6 @@ func (l *Limiter) AddToHistory(client netip.Prefix, now time.Time, r Request) {
if r.WAFBlocked {
h.Offences.WAFBlocked++
}
if r.TokenRefused {
h.Offences.TokenRefused++
}
}
// AddLookup gives client's history its AS number, AS name and country, as