rproxy and servewaf replace the one-process smallwebwaf (closes #172, closes #165)
check / check (push) Successful in 17m6s

`smallwebwaf` with no command now prints the commands and exits with status 2.
The image runs rproxy, or servewaf with SMALLWEBWAF_COMMAND=servewaf. The
passing-on code, its settings and its log fields and metric go. internal/proxy
keeps the checks, answers, reports and own endpoints; its tests run through the
real rproxy. The documents describe the pair.

Judgement call: clients.json keeps token_refused, since state files refuse unknown fields.
Deviation: script/gitea-requests sets SWWAF_LOG_REQUEST_HEADERS, to label requests.

Model: opus-5-5
This commit is contained in:
2026-11-05 06:26:21 +00:00
parent 17c5dd2438
commit 4b0af7f85b
71 changed files with 2607 additions and 5497 deletions
+3 -39
View File
@@ -315,20 +315,6 @@ func TestObserveModeWaitsForGeoJSForARequestOverTheHeaderLimits(t *testing.T) {
}
}
func TestWithoutACommandTheHeaderLimitsDoNotApply(t *testing.T) {
t.Parallel()
app := startApp(t, func(http.ResponseWriter, *http.Request) {})
addr, out := startProxy(t, app.URL, nil)
req := newRequest(t, http.MethodGet, addr, "/", http.NoBody)
req.Header.Set(cookieHeader, cookies(cookieLimit+1))
fillHeaders(req, headerFieldLimit+1)
wantStatus(t, do(t, req), http.StatusOK)
wantLine(t, out.requestLine(t), http.StatusOK, requestlog.ActionForward)
}
// newServeWAFInBubble makes a servewaf for a synctest bubble: GeoJS never
// answers, a setting needs its answer, and everything is at its default but
// for env. No request to it may use the network.
@@ -338,8 +324,7 @@ func newServeWAFInBubble(t *testing.T, env map[string]string) (*proxy.Server, *o
settings := map[string]string{deniedCountries: "KP"}
maps.Copy(settings, env)
server, out, _ := newServerWith(t, proxy.NewServeWAF, "http://app.invalid",
unansweredGeoJSURL, time.Now, settings)
server, out, _ := newServeWAF(t, unansweredGeoJSURL, time.Now, settings)
return server, out
}
@@ -521,27 +506,6 @@ func TestAQuestionWaitsForASlowGeoJSOnlyAsLongAsTheDefaultSays(t *testing.T) {
}
}
func TestWithoutACommandARefusedRequestStillWaitsForGeoJS(t *testing.T) {
t.Parallel()
synctest.Test(t, func(t *testing.T) {
server, out, _ := newProxy(t, "http://app.invalid", unansweredGeoJSURL,
time.Now, map[string]string{deniedCountries: "KP", blocklistURLs: dropURL})
listClient(t, server, time.Now())
status, took := askDirectly(t, server, func(req *http.Request) {
req.RemoteAddr = net.JoinHostPort(client, "1234")
})
if status != http.StatusForbidden || took != defaultLookupWait {
t.Errorf("answered %d after %s, want %d after %s; output:\n%s",
status, took, http.StatusForbidden, defaultLookupWait, out.text())
}
wantLine(t, out.requestLine(t), http.StatusForbidden, requestlog.ActionDenied)
})
}
func TestServeWAFAnswersWithinTheTimeLimitWhileEveryOutsideSourceHangs(t *testing.T) {
t.Parallel()
@@ -555,11 +519,11 @@ func TestServeWAFAnswersWithinTheTimeLimitWhileEveryOutsideSourceHangs(t *testin
t.Cleanup(func() { _ = resolver.Close() })
server, out, _ := newServerWith(t, func(params proxy.Params) *proxy.Server {
server, out, _ := newServeWAFWith(t, func(params proxy.Params) *proxy.Server {
params.AbuseIPDBURL = silentAbuseIPDBURL
return proxy.NewServeWAF(params)
}, "http://app.invalid", held, time.Now, map[string]string{
}, held, time.Now, map[string]string{
deniedCountries: "KP", wafMode: block,
dnsblZones: dnsblZone, dnsblResolver: resolver.LocalAddr().String(),
abuseIPDBKey: accountKey,