Add asn= and prefix= tags from a routewatch instance (closes #204)
check / check (push) Successful in 5m0s
check / check (push) Successful in 5m0s
With `SWW_ROUTEWATCH_URL` set, a new heuristic, `routewatch_tags`, adds `asn=<number>` and `prefix=<netblock>` to a request from what a routewatch instance answers about the client. New package `internal/routewatch` asks in the background, never on a request's path, and keeps answers 1 hour in memory. The request log gains `routewatch_tags_missing`, saying why a request has none. `prefix=` works in `SWW_TAG_DENY` and `SWW_TAG_LIMIT_PERCENT`. Trips a reader: a client's first request has no routewatch tags, so `prefix=` refuses from its next request after the answer comes. Judgement call: with `SWW_LOOKUP_SOURCE=off` and `SWW_ROUTEWATCH_URL` set, an `asn=` tag no longer stops the start. Model: opus-5-5
This commit was merged in pull request #232.
This commit is contained in:
1 parent
d7c62f2854
commit
6850cb0e9f
14 files changed
+1043
-17
No files matched your search
@@ -61,6 +61,7 @@ const (
|
||||
reputationAction = "SWW_REPUTATION_ACTION"
|
||||
reputationCacheTTL = "SWW_REPUTATION_CACHE_TTL"
|
||||
reputationTimeout = "SWW_REPUTATION_TIMEOUT"
|
||||
routeWatchURL = "SWW_ROUTEWATCH_URL"
|
||||
crowdSecURL = "SWW_CROWDSEC_LAPI_URL"
|
||||
crowdSecKey = "SWW_CROWDSEC_LAPI_KEY"
|
||||
banResponse = "SWW_BAN_RESPONSE"
|
||||
@@ -1403,6 +1404,63 @@ func TestTagSettingsAsSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouteWatchURLAndPrefixTags(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const rw = "https://routewatch.example"
|
||||
|
||||
if cfg := fromEnvironment(t, environment{}); cfg.RouteWatchURL != "" {
|
||||
t.Errorf("default %s is %q, want unset", routeWatchURL, cfg.RouteWatchURL)
|
||||
}
|
||||
|
||||
cfg := fromEnvironment(t, environment{
|
||||
routeWatchURL: rw, tagDeny: "prefix=2001:DB8::/32",
|
||||
tagLimitPercent: "prefix=192.0.2.0/24:50",
|
||||
})
|
||||
wantDeny := []string{"prefix=2001:db8::/32"}
|
||||
|
||||
if cfg.RouteWatchURL != rw || !slices.Equal(cfg.TagDeny, wantDeny) ||
|
||||
cfg.TagLimitPercent["prefix=192.0.2.0/24"] != 50 {
|
||||
t.Errorf("gave %q, %v, %v", cfg.RouteWatchURL, cfg.TagDeny, cfg.TagLimitPercent)
|
||||
}
|
||||
|
||||
// routewatch gives asn= tags too, so an asn= tag needs no lookups while it is set.
|
||||
fromEnvironment(t, environment{
|
||||
lookupSource: off, routeWatchURL: rw, tagDeny: "asn=64496",
|
||||
})
|
||||
|
||||
for _, stopped := range []struct {
|
||||
env environment
|
||||
name string
|
||||
}{
|
||||
{environment{routeWatchURL: "ftp://routewatch.example"}, routeWatchURL},
|
||||
{environment{routeWatchURL: "routewatch.example"}, routeWatchURL},
|
||||
{environment{tagDeny: "prefix=192.0.2.0/24"}, tagDeny},
|
||||
{environment{routeWatchURL: rw, tagDeny: "prefix=nowhere"}, tagDeny},
|
||||
{environment{routeWatchURL: rw, tagDeny: "prefix=192.0.2.5/24"}, tagDeny},
|
||||
{
|
||||
environment{routeWatchURL: rw, tagLimitPercent: "prefix=192.0.2.0/33:50"},
|
||||
tagLimitPercent,
|
||||
},
|
||||
{environment{lookupSource: off, routeWatchURL: rw, tagDeny: "country=DE"}, tagDeny},
|
||||
{environment{lookupSource: off, tagDeny: "asn=64496"}, tagDeny},
|
||||
} {
|
||||
_, err := config.FromEnvironment(stopped.env.lookupEnv)
|
||||
if err == nil || !strings.HasPrefix(err.Error(), stopped.name+": ") {
|
||||
t.Errorf("%v gave the error %v, want one naming %s", stopped.env, err, stopped.name)
|
||||
}
|
||||
}
|
||||
|
||||
badURL := environment{routeWatchURL: "ftp://routewatch.example"}
|
||||
_, err := config.FromEnvironment(badURL.lookupEnv)
|
||||
|
||||
want := routeWatchURL + `: "ftp://routewatch.example" is not an http or https URL ` +
|
||||
"without a user or a fragment, such as https://routewatch.example"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("error %v, want %s", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagThatNoRequestCanGetIsToldApartFromOneItCan(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -2503,6 +2561,7 @@ func TestLogsEachSettingWithItsValue(t *testing.T) {
|
||||
reputationAction: "limit:25",
|
||||
reputationCacheTTL: defaultReputationCacheTTL,
|
||||
reputationTimeout: "2s",
|
||||
routeWatchURL: "",
|
||||
crowdSecURL: "",
|
||||
crowdSecKey: "",
|
||||
banResponse: "403",
|
||||
|
||||
Reference in new issue
Block a user