Request tags, with refusing and limits per tag (closes #175)
check / check (push) Failing after 1m22s

Each request gets sorted tags from the lookup, new address lists, the
reputation sources and the rule matches, logged as `tags`. New settings:
`SWW_TAG_LISTS`, `SWW_TAG_DENY`, `SWW_TAG_LIMIT_PERCENT`. They replace
`SWW_ASN_LIMIT_PERCENT`, `SWW_COUNTRY_LIMIT_PERCENT` and
`SWW_DENIED_COUNTRIES`. New heuristics `tag_lists` and `tag_deny`; the
latter runs before the rate limits and again after the Core Rule Set.

Model: opus-5-5
This commit is contained in:
clawbot authored and sneak committed 2026-11-09 02:04:05 +00:00
1 parent f6435b1a73
commit de9c71a796
42 files changed
+1420 -362

No files matched your search

+32 -1
View File
@@ -4,8 +4,10 @@ import (
"context"
"net/http"
"net/netip"
"strings"
"time"
"sneak.berlin/go/smallwebwaf/internal/config"
"sneak.berlin/go/smallwebwaf/internal/lookup"
)
@@ -19,7 +21,8 @@ const (
)
// lookUp looks up the client's AS number and country, in the lookup
// database or through GeoJS, and notes them for the log line, unless
// database or through GeoJS, and notes them for the log line and as the
// request's asn= and country= tags, unless
// SWW_LOOKUP_SOURCE is off or the client is on a private, loopback or
// link-local address, which no lookup can place. The lookup database
// answers at once. With GeoJS, while a setting needs the answer, such as a
@@ -47,6 +50,34 @@ func (rq *request) lookUp(ctx context.Context, now time.Time) {
rq.line.ASN = rq.lookupAnswer.ASN
rq.line.ASName = rq.lookupAnswer.ASName
rq.line.Country = rq.lookupAnswer.Country
if tag := asnTag(rq.line.ASN); tag != "" {
rq.addTag(tag)
}
if tag := countryTag(rq.line.Country); tag != "" {
rq.addTag(tag)
}
}
// asnTag returns the tag of asn, an AS number as the lookup gives it, such as
// asn=64496 for AS64496, or "" for no AS number.
func asnTag(asn string) string {
if asn == "" {
return ""
}
return config.ASNTagPrefix + strings.TrimPrefix(asn, "AS")
}
// countryTag returns the tag of country, a code as the lookup gives it, such
// as country=DE for DE, or "" for no country.
func countryTag(country string) string {
if country == "" {
return ""
}
return config.CountryTagPrefix + country
}
// addLookup adds answer, an answer about a client from the lookup