check / check (push) Failing after 3m27s
Every setting of discriminator and rproxy is read through viper, in place of the os.LookupEnv function Main passed down. NewViper turns AutomaticEnv and AllowEmptyEnv on, so a setting that is set but empty reads as set. A setting may also be given as a file, the _FILE form, which rproxy's settings now have too; rproxy still writes nothing to disk. The settings are renamed. Discriminator's take the prefix SWW_WAF_, rproxy's take SWW_RPROXY_, and the shared SWW_COMMAND keeps SWW_. The Core Rule Set's settings take SWW_WAF_CORE_RULE_SET_ rather than SWW_WAF_WAF_. Every place a name appeared changed: the code, the viper keys, tests, documents, examples, the README's settings table and the image files. Model: deepseek-v4-pro
63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package discriminator
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"net/http"
|
|
"net/netip"
|
|
"slices"
|
|
)
|
|
|
|
// peerAddress is the address of the request's TCP peer.
|
|
func peerAddress(r *http.Request) netip.Addr {
|
|
addrPort, err := netip.ParseAddrPort(r.RemoteAddr)
|
|
if err != nil {
|
|
return netip.Addr{}
|
|
}
|
|
|
|
return addrPort.Addr().Unmap()
|
|
}
|
|
|
|
// requestIDHeader carries the request's id, from rproxy.
|
|
const requestIDHeader = "X-Request-ID"
|
|
|
|
// requestID is the request's id: the one a question gives, or for any other
|
|
// request a new random one.
|
|
func requestID(r *http.Request, isQuestion bool) string {
|
|
if isQuestion {
|
|
return r.Header.Get(requestIDHeader)
|
|
}
|
|
|
|
return rand.Text()
|
|
}
|
|
|
|
// scheme is how the visitor reached rproxy, or the trusted proxy in front of
|
|
// it, as a question says in X-Forwarded-Proto, or otherwise http.
|
|
func scheme(r *http.Request, isQuestion bool) string {
|
|
proto := r.Header.Get("X-Forwarded-Proto")
|
|
if !isQuestion || proto == "" {
|
|
return "http"
|
|
}
|
|
|
|
return proto
|
|
}
|
|
|
|
// clientGroup is the client a request is counted toward: its IPv4
|
|
// address, or its IPv6 group, the netblock its IPv6 address is in of the
|
|
// length SWW_WAF_IPV6_GROUP_PREFIX sets, a /64 by default, since one abuser
|
|
// usually holds a whole /64. An IPv4 address in IPv6 form counts as IPv4.
|
|
func (h *handler) clientGroup(addr netip.Addr) netip.Prefix {
|
|
addr = addr.Unmap()
|
|
if addr.Is6() {
|
|
return netip.PrefixFrom(addr, h.config.IPv6GroupPrefix).Masked()
|
|
}
|
|
|
|
return netip.PrefixFrom(addr, addr.BitLen())
|
|
}
|
|
|
|
// isInside reports whether addr is in one of the netblocks.
|
|
func isInside(addr netip.Addr, netblocks []netip.Prefix) bool {
|
|
return slices.ContainsFunc(netblocks, func(netblock netip.Prefix) bool {
|
|
return netblock.Contains(addr)
|
|
})
|
|
}
|