check / check (push) Waiting to run
Each check servewaf runs on a request is a type in its own file behind one interface, heuristic, and is registered in one of four ordered lists in heuristics.go. Order and behaviour are unchanged. Every refusal now logs heuristic, the name of the heuristic that made it, and heuristic_figures, the figures it acted on. A ban by refusal_limit or byte_limits after the answer logs after_answer_heuristic and after_answer_heuristic_figures instead, so a line can name both. All four are in docs/request-log.md, and SPEC.md names each heuristic at its step. Model: opus-5-5
37 lines
1.1 KiB
Go
37 lines
1.1 KiB
Go
package servewaf
|
|
|
|
// The heuristic dnsbl. It reads SWWAF_REPUTATION_ACTION, and the DNSBL zones'
|
|
// verdicts through the DNSBL checker.
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
|
)
|
|
|
|
// dnsbl notes the DNSBL zones whose verdict lists the client, as noteListed
|
|
// does, and refuses the request when SWWAF_REPUTATION_ACTION is deny. Being
|
|
// limit, it lowers the client's limits instead (see limitPercentages), and
|
|
// being log, it does nothing more. A zone without a verdict on the client is
|
|
// asked about it in the background, and the request does not wait for the
|
|
// answer. Its figure is the zones that list the client, their keys masked.
|
|
type dnsbl struct{}
|
|
|
|
func (dnsbl) name() string { return "dnsbl" }
|
|
|
|
func (dnsbl) check(ctx context.Context, rq *request, _ time.Time) *verdict {
|
|
listedBy := rq.h.dnsbl.ListedBy(ctx, rq.client)
|
|
rq.dnsblListed = len(listedBy) > 0
|
|
rq.noteListed(listedBy, "listed by a DNSBL zone")
|
|
|
|
if !rq.dnsblListed || rq.h.config.ReputationAction != deny {
|
|
return nil
|
|
}
|
|
|
|
return &verdict{
|
|
action: requestlog.ActionDenied,
|
|
figures: map[string]any{"zones": listedBy},
|
|
}
|
|
}
|