check / check (push) Waiting to run
The package passes nothing to an app since rproxy took that over, so it is named after the command it serves. Its constructor is New, like rproxy's. The rproxy tests call their stand-in for servewaf standIn, since a local servewaf would hide the package. No change of behaviour. Model: opus-5-5
63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package servewaf
|
|
|
|
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 SWWAF_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)
|
|
})
|
|
}
|