check / check (push) Successful in 2m18s
SWWAF_DENIED_COUNTRIES and SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES refuse a request with 403 before its body is read and before the rate limits count it, logged as country_denied; every log line gains country. The new internal/lookup asks GeoJS only while a list is set, one request at a time carrying up to 200 waiting clients, keeps answers 7 days (at most 100,000), and after a failure waits a second, doubling to five minutes. Private, loopback and link-local clients have no country and are never sent. Codes are checked with golang.org/x/text/language. Deviation from SPEC.md, per the issue: no SWWAF_LOOKUP_SOURCE or SWWAF_LOOKUP_TIMEOUT; 403, not SWWAF_BAN_RESPONSE. Deviation: GeoJS's country endpoint, not geo.json, since only the country is needed. Judgement call: an IPv6 /64 is asked about by its first address; at most 10,000 clients wait. Deviation: go.mod and go.sum hand-written; no make target tidies them. Model: opus-5-5
42 lines
1.1 KiB
Go
42 lines
1.1 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"slices"
|
|
)
|
|
|
|
// countryDenied reports whether the country lists refuse the request.
|
|
// The client's country is looked up only while a list is set, and never
|
|
// for a client on a private, loopback or link-local address, which has
|
|
// no country and which neither list checks. A client whose country
|
|
// cannot be found is refused only by SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES.
|
|
// ctx is the request's own context.
|
|
func (rq *request) countryDenied(ctx context.Context) bool {
|
|
denied := rq.h.config.DeniedCountries
|
|
allowed := rq.h.config.ExclusivelyAllowedCountries
|
|
|
|
if len(denied) == 0 && len(allowed) == 0 {
|
|
return false
|
|
}
|
|
|
|
if !hasCountry(rq.client) {
|
|
return false
|
|
}
|
|
|
|
country := rq.h.geojs.Country(ctx, clientGroup(rq.client))
|
|
rq.line.Country = country
|
|
|
|
if slices.Contains(denied, country) {
|
|
return true
|
|
}
|
|
|
|
return len(allowed) > 0 && !slices.Contains(allowed, country)
|
|
}
|
|
|
|
// hasCountry reports whether addr can be placed in a country: private,
|
|
// loopback and link-local addresses cannot.
|
|
func hasCountry(addr netip.Addr) bool {
|
|
return !addr.IsPrivate() && !addr.IsLoopback() && !addr.IsLinkLocalUnicast()
|
|
}
|