Rename the settings whose names do not say what they control (closes #234)
check / check (push) Waiting to run

Applies the setting renames of the naming audit under the SWW_WAF_ and
SWW_RPROXY_ prefixes, with sneak's names for the IP reputation cache
time and the two time limits, which now take milliseconds. The rproxy
log field default_disposition becomes waf_backend_no_answer, and
config.Config and config.FromEnvironment become config.WAF and
config.WAFFromEnvironment. Go fields, test names and prose follow. No
aliases; nothing reads the old names.

Model: opus-5-5
This commit is contained in:
clawbot committed 2026-11-12 09:08:49 +00:00
1 parent 101cc0aba5
commit a18926ec4d
100 files changed
+2181 -1935

No files matched your search

+3 -2
View File
@@ -6,7 +6,7 @@ the `instance` label as `exported_instance` unless the scrape sets
`honor_labels: true`. `rproxy` has no metrics.
Every `sww_*request_bytes_total` and `sww_*response_bytes_total` series counts
body bytes, never headers, whatever `SWW_WAF_BYTES_COUNT` says.
body bytes, never headers, whatever `SWW_WAF_BYTES_COUNTED` says.
## Traffic
@@ -33,7 +33,8 @@ body bytes, never headers, whatever `SWW_WAF_BYTES_COUNT` says.
## Countries and AS numbers
For the `SWW_WAF_METRICS_TOP_N` busiest of each, the rest as `other`:
For the `SWW_WAF_METRICS_BUSIEST_COUNTRIES_AND_ASNS` busiest of each, the rest
as `other`:
- `sww_country_requests_total`, `sww_country_request_bytes_total`,
`sww_country_response_bytes_total` and `sww_country_list_refusals_total`, by
+10 -8
View File
@@ -128,8 +128,8 @@ Every one of these lines has:
- `rule_files`: `rule_id` and `rule_action`, of the rule that refused it;
- `header_limits`: `fields`, `fields_limit`, `cookies` and `cookies_limit`;
- `core_rule_set`: `score`, and `threshold`,
`SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD`;
- `refusal_limit`: `window`, `count` and `limit`, of the error burst;
`SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD`;
- `refusal_limit`: `window`, `count` and `limit`, of the refusal limit;
- `byte_limits`: `window`, `count` and `limit`, the count in bytes.
- `after_answer_heuristic`: the heuristic that banned the client after `waf`
answered the request, in `observe` mode too: `refusal_limit` or `byte_limits`.
@@ -148,7 +148,7 @@ Every one of these lines has:
holds:
- `minute`, `hour` and `day`: requests;
- `minute_bytes`, `hour_bytes` and `day_bytes`: the body bytes
`SWW_WAF_BYTES_COUNT` names, in that window.
`SWW_WAF_BYTES_COUNTED` names, in that window.
A count can have a fraction (see "Counting method" in
[`SPEC.md`](../SPEC.md)). The bytes counted for an allowed request and its
@@ -158,7 +158,8 @@ Every one of these lines has:
- `limit_hit`: the limit broken:
- `minute`, `hour` or `day` for a rate limit;
- `minute_bytes`, `hour_bytes` or `day_bytes` for a byte limit;
- `minute_refusals` for the error burst (`SWW_WAF_ERROR_BURST_THRESHOLD`).
- `minute_refusals` for the refusal limit
(`SWW_WAF_REFUSALS_LIMIT_PER_MINUTE`).
When the bytes counted for a request and its response break a limit, the
request has been passed on whole, so its `action` stays `forward`. Only its
@@ -233,14 +234,15 @@ meanings where they differ:
was sooner. It includes the wait for `waf`.
- `duration_response_ms`: milliseconds from then until the end of the answer.
- `disposition`: what was done with the request: `allow`, `deny` or `close`. It
is `waf`'s answer, or the value of `SWW_RPROXY_DEFAULT_DISPOSITION`. It is
left out when:
is `waf`'s answer, or the value of
`SWW_RPROXY_WAF_BACKEND_NO_ANSWER_DISPOSITION`. It is left out when:
- `waf` was not asked, as for the health check;
- the visitor went away while `waf` was being asked;
- `waf`'s answer had no valid `X-Sww-Disposition`;
- `rproxy` could not pass on `waf`'s answer, and answered `502`.
- `default_disposition`: `true` when `SWW_RPROXY_DEFAULT_DISPOSITION` gave
`disposition`, and otherwise left out.
- `waf_backend_no_answer`: `true` when
`SWW_RPROXY_WAF_BACKEND_NO_ANSWER_DISPOSITION` gave `disposition`, and
otherwise left out.
For example:
+69 -62
View File
@@ -12,6 +12,8 @@ chooses between the two (see "The image's command" below).
- A duration is Go's syntax, with `d` for days: `90s`, `15m`, `24h`, `7d`. Zero
and negative durations are refused.
- A time in milliseconds is a whole number above zero, such as `2000`. Its
setting's name ends in `_MS`.
- A size is a number of bytes with an optional `K`, `M` or `G`, which are powers
of 1024, so `1K` is 1024 bytes. Examples: `512K`, `100M`, `5G`.
- A count is a whole number of requests, such as `1000`.
@@ -55,9 +57,9 @@ chooses between the two (see "The image's command" below).
- `SWW_WAF_STATE_DIR` (default `/var/lib/sww`): the directory of the state
files, an absolute path that can be written. The image's `run` script makes
it.
- `SWW_WAF_STATE_WRITE_DELAY` (default `10s`): how long `bans.json` waits to be
- `SWW_WAF_BANS_WRITE_DELAY` (default `10s`): how long `bans.json` waits to be
written after a ban is made, lifted or made permanent. A duration.
- `SWW_WAF_STATE_COUNTER_INTERVAL` (default `15m`): how often every state and
- `SWW_WAF_STATE_WRITE_INTERVAL` (default `15m`): how often every state and
cache file is written. A duration.
- `SWW_WAF_CACHE_DIR` (default `/var/cache/sww`): the directory of the cache
files, an absolute path that can be written. The image's `run` script makes
@@ -77,8 +79,8 @@ chooses between the two (see "The image's command" below).
- `SWW_WAF_LOG_REMOTE_TLS_CA_FILE` (default unset): a file of PEM certificates
that a `syslog+tls` server's certificate must chain to, instead of the host's
own. A file that cannot be read, or holds no certificate, is refused.
- `SWW_WAF_LOG_REMOTE_BUFFER` (default `10000`): the most lines held while they
wait to be sent, a whole number above zero.
- `SWW_WAF_LOG_REMOTE_BUFFER_LINES` (default `10000`): the most lines held while
they wait to be sent, a whole number above zero.
- `SWW_WAF_LOG_REMOTE_FACILITY` (default `local0`): the syslog facility: `kern`,
`user`, `mail`, `daemon`, `auth`, `syslog`, `lpr`, `news`, `uucp`, `cron`,
`authpriv`, `ftp`, or `local0` to `local7`.
@@ -87,8 +89,9 @@ chooses between the two (see "The image's command" below).
## Metrics
- `SWW_WAF_METRICS_TOP_N` (default `50`): how many AS numbers and how many
countries get series of their own. A whole number above zero.
- `SWW_WAF_METRICS_BUSIEST_COUNTRIES_AND_ASNS` (default `50`): how many AS
numbers and how many countries get series of their own. A whole number above
zero.
## Static lists
@@ -134,10 +137,10 @@ cut off; the client is banned.
- `SWW_WAF_BYTES_LIMIT_PER_MINUTE` (default `off`),
`SWW_WAF_BYTES_LIMIT_PER_HOUR` (default `50G`) and
`SWW_WAF_BYTES_LIMIT_PER_DAY` (default `100G`): the most bytes counted for a
client in each window, a size or `off`. `SWW_WAF_BYTES_COUNT` says which bytes
count: response bodies, request bodies or both. The request that passes the
limit is not cut off, and the client is banned when its response ends.
- `SWW_WAF_BYTES_COUNT` (default `both`): what the byte limits and the byte
client in each window, a size or `off`. `SWW_WAF_BYTES_COUNTED` says which
bytes count: response bodies, request bodies or both. The request that passes
the limit is not cut off, and the client is banned when its response ends.
- `SWW_WAF_BYTES_COUNTED` (default `both`): what the byte limits and the byte
anomaly thresholds count: `response`, the app's response bodies; `request`,
the visitors' request bodies; or `both`. What the visitor sent over a
WebSocket counts as request bytes, and what the app sent as response bytes.
@@ -151,13 +154,13 @@ cut off; the client is banned.
- `SWW_WAF_TAG_DENY` or `SWW_WAF_TAG_LIMIT_PERCENT` naming a `country=` tag,
or an `asn=` tag while `SWW_WAF_ROUTEWATCH_URL` is unset;
- the two byte percentage lists and `SWW_WAF_ASN_LIMIT_PERCENT_URL`;
- `SWW_WAF_UNKNOWN_LIMIT_PERCENT` below `100`;
- `SWW_WAF_UNKNOWN_COUNTRY_LIMIT_PERCENT` below `100`;
- an anomaly threshold per AS number.
- `SWW_WAF_LOOKUP_DB_PATH` (default empty): the IPinfo Lite database file, in
its `.mmdb` form, for `SWW_WAF_LOOKUP_SOURCE=file`.
- `SWW_WAF_LOOKUP_TIMEOUT` (default `800ms`): how long a request waits for its
client's first answer from GeoJS, and how long a request to GeoJS may take. A
duration; never `off`.
- `SWW_WAF_ASN_AND_COUNTRY_LOOKUP_TIMEOUT_MS` (default `800`): how long a
request waits for its client's first answer from GeoJS, and how long a request
to GeoJS may take. A time in milliseconds; never `off`.
- `SWW_WAF_ADD_LOOKUP_HEADERS` (default `false`): `true` has `rproxy` pass the
app the client's AS number in `X-Client-ASN` and its country in
`X-Client-Country`.
@@ -206,22 +209,23 @@ tag that no request can get stops the start. A request can get only these:
- a `dnsbl=` tag of a zone in `SWW_WAF_DNSBL_ZONES`, in lower case, with a key
masked as the `reputation` field shows it;
- `abuseipdb`, while `SWW_WAF_ABUSEIPDB_KEY` is set;
- `exploitsignature`, in `SWW_WAF_TAG_DENY` only, while `SWW_WAF_RULES_ENABLED`
is `true`, or while neither `SWW_WAF_CORE_RULE_SET_MODE` nor
`SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD` is `off`.
- `exploitsignature`, in `SWW_WAF_TAG_DENY` only, while
`SWW_WAF_RULE_FILES_ENABLED` is `true`, or while neither
`SWW_WAF_CORE_RULE_SET_MODE` nor `SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD` is
`off`.
`crowdsec` stops the start in both settings, because a CrowdSec decision refuses
the request first.
## Biased thresholds
- `SWW_WAF_ASN_BYTES_PERCENT` and `SWW_WAF_COUNTRY_BYTES_PERCENT` (default
empty): a percentage of the byte limits alone, for the AS numbers or countries
listed, such as `AS14061:50` or `cn:25`. It takes the place of the percentage
`SWW_WAF_TAG_LIMIT_PERCENT` gives their `asn=` or `country=` tag. An AS number
or country listed twice is refused.
- `SWW_WAF_UNKNOWN_LIMIT_PERCENT` (default `100`): the percentage for a client
the lookup cannot place.
- `SWW_WAF_ASN_BYTES_LIMIT_PERCENT` and `SWW_WAF_COUNTRY_BYTES_LIMIT_PERCENT`
(default empty): a percentage of the byte limits alone, for the AS numbers or
countries listed, such as `AS14061:50` or `cn:25`. It takes the place of the
percentage `SWW_WAF_TAG_LIMIT_PERCENT` gives their `asn=` or `country=` tag.
An AS number or country listed twice is refused.
- `SWW_WAF_UNKNOWN_COUNTRY_LIMIT_PERCENT` (default `100`): the percentage for a
client the lookup cannot place.
- `SWW_WAF_ASN_LIMIT_PERCENT_URL` (default unset): the `http` or `https` URL of
a text file with one AS number and percentage on each line, such as
`AS64496:50`. Each entry counts like an `asn=` tag in
@@ -230,15 +234,15 @@ the request first.
## Attack detection
- `SWW_WAF_RULES_DIR` (default `/etc/sww/rules.d`): the directory of the rule
files.
- `SWW_WAF_RULES_ENABLED` (default `true`): `false` reads no rule file.
- `SWW_WAF_RULE_FILES_DIR` (default `/etc/sww/rules.d`): the directory of the
rule files.
- `SWW_WAF_RULE_FILES_ENABLED` (default `true`): `false` reads no rule file.
- `SWW_WAF_TRAP_PATHS` (default empty): paths only scanners ask for, such as
`/wp-login.php,/xmlrpc.php`. Each starts with `/` and holds no `?`.
- `SWW_WAF_CORE_RULE_SET_MODE` (default `block`): `off`, `detect` or `block`.
- `SWW_WAF_CORE_RULE_SET_PARANOIA_LEVEL` (default `1`): the Core Rule Set's
paranoia level, from 1 to 4.
- `SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD` (default `5`): the score at which a
- `SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD` (default `5`): the score at which a
request is a match. A whole number above zero, or `off`.
- `SWW_WAF_CORE_RULE_SET_DISABLED_RULES` (default
`920340,920420,920440,920640,930130,930140`): the ids of Core Rule Set rules
@@ -247,10 +251,10 @@ the request first.
`smallwebwaf`'s own.
- `SWW_WAF_CORE_RULE_SET_EXEMPT_PATHS` (default empty): path prefixes the Core
Rule Set does not inspect.
- `SWW_WAF_CORE_RULE_SET_BODY_LIMIT` (default `off`): `off`, or how much of a
request body the Core Rule Set reads, a size of at most `64K`. A question
carries no more of a body than 64 KiB, and the Core Rule Set reads at most 64
KiB less one byte of it, whatever the value (see "The answer" in
- `SWW_WAF_CORE_RULE_SET_BODY_INSPECTION_SIZE` (default `off`): `off`, or how
much of a request body the Core Rule Set reads, a size of at most `64K`. A
question carries no more of a body than 64 KiB, and the Core Rule Set reads at
most 64 KiB less one byte of it, whatever the value (see "The answer" in
[`SPEC.md`](../SPEC.md)).
- `SWW_WAF_CORE_RULE_SET_EXCLUSIONS_FILE` (default unset): a file of Core Rule
Set exclusions, written as Coraza directives. It is loaded before the Core
@@ -288,9 +292,10 @@ the request first.
- a hostname listed twice;
- an app listed twice for one hostname;
- an entry without a colon.
- `SWW_WAF_ERROR_BURST_THRESHOLD` (default `30`): the most refusals a client may
get in a minute from a rule file, a trap path or the Core Rule Set, a count or
`off`. The next one bans the client (see "Attack detection" in `SPEC.md`).
- `SWW_WAF_REFUSALS_LIMIT_PER_MINUTE` (default `30`): the most refusals a client
may get in a minute from a rule file, a trap path or the Core Rule Set, a
count or `off`. The next one bans the client (see "Attack detection" in
`SPEC.md`).
## Ban lengths, response and scope
@@ -299,8 +304,8 @@ the request first.
A duration.
- `SWW_WAF_LIMIT_BAN_REPEAT_WINDOW` (default `24h`): the time after a ban ends
within which breaking a limit again lengthens the next ban. A duration.
- `SWW_WAF_MAX_BAN_DURATION` (default `7d`): the longest ban for a broken limit;
one that would be longer is permanent. A duration.
- `SWW_WAF_LIMIT_BAN_PERMANENT_ABOVE` (default `7d`): a ban for a broken limit
that would be longer than this is permanent instead. A duration.
- `SWW_WAF_ATTACK_BAN_DURATION` (default `7d`): the ban for a first clear sign
of attack. A duration.
- `SWW_WAF_BAN_SCOPE_V4_PREFIX` (default `32`): how much a ban on an IPv4 client
@@ -336,12 +341,12 @@ the request first.
- `SWW_WAF_CROWDSEC_LAPI_KEY` (default unset): the key the engine gave for
`smallwebwaf`, as `cscli bouncers add smallwebwaf` prints it. Set without the
URL, it is refused.
- `SWW_WAF_REPUTATION_ACTION` (default `limit:25`): `deny`, `limit:<percent>` or
`log`, for DNS blocklist and AbuseIPDB hits.
- `SWW_WAF_REPUTATION_CACHE_TTL` (default `24h`): how long a zone's verdict or
AbuseIPDB's score is used. A duration.
- `SWW_WAF_REPUTATION_TIMEOUT` (default `2s`): how long a query to a zone or a
check with AbuseIPDB may take. A duration.
- `SWW_WAF_DNSBL_ABUSEIPDB_ACTION` (default `limit:25`): `deny`,
`limit:<percent>` or `log`, for DNS blocklist and AbuseIPDB hits.
- `SWW_WAF_IP_REPUTATION_CACHE_TTL` (default `24h`): how long a zone's verdict
or AbuseIPDB's score is used. A duration.
- `SWW_WAF_DNSBL_ABUSEIPDB_TIMEOUT_MS` (default `2000`): how long a query to a
zone or a check with AbuseIPDB may take. A time in milliseconds.
## Alerting
@@ -369,7 +374,7 @@ the request first.
## Anomaly thresholds
Each scope has four thresholds: the most requests and the most body bytes
counted in a minute and in an hour. The bytes are those `SWW_WAF_BYTES_COUNT`
counted in a minute and in an hour. The bytes are those `SWW_WAF_BYTES_COUNTED`
names. Requests are counts, bytes are sizes. Each is `off` by default. The four
thresholds per client are:
@@ -389,9 +394,10 @@ as `REQUESTS_PER_MINUTE`:
client.
- `SWW_WAF_ANOMALY_ASN_...`: per AS number.
- `SWW_WAF_ANOMALY_TOTAL_...`: the whole service.
- `SWW_WAF_WATCH_...`: each netblock in `SWW_WAF_WATCH_NETS`, as a whole.
`SWW_WAF_WATCH_NETS` (default empty) is a list of name, `=` and netblock, such
as `office=203.0.113.0/24,scraper-x=198.51.100.0/22`. An item without `=` or a
- `SWW_WAF_ANOMALY_WATCHED_NET_...`: each netblock in
`SWW_WAF_ANOMALY_WATCHED_NETS`, as a whole. `SWW_WAF_ANOMALY_WATCHED_NETS`
(default empty) is a list of name, `=` and netblock, such as
`office=203.0.113.0/24,scraper-x=198.51.100.0/22`. An item without `=` or a
name, or with a bad netblock, is refused. So is a name used twice.
## Settings given as files
@@ -435,10 +441,11 @@ A few limits are fixed rather than settings:
## `waf`'s answer and `rproxy`'s wait
`SWW_WAF_LOOKUP_TIMEOUT` is the longest a question waits on an outside source.
Keep it well under `rproxy`'s `SWW_RPROXY_TIMEOUT_MS`, as the default is. No
question waits for `SWW_WAF_REPUTATION_TIMEOUT`, since the DNS blocklists and
AbuseIPDB are asked in the background (see "Answering in time" under "`waf`" in
`SWW_WAF_ASN_AND_COUNTRY_LOOKUP_TIMEOUT_MS` is the longest a question waits on
an outside source. Keep it well under `rproxy`'s
`SWW_RPROXY_WAF_BACKEND_TIMEOUT_MS`, as the default is. No question waits for
`SWW_WAF_DNSBL_ABUSEIPDB_TIMEOUT_MS`, since the DNS blocklists and AbuseIPDB are
asked in the background (see "Answering in time" under "`waf`" in
[`SPEC.md`](../SPEC.md)).
## `rproxy`
@@ -447,18 +454,17 @@ AbuseIPDB are asked in the background (see "Answering in time" under "`waf`" in
start, and an invalid value stops the start. Any can be given as a file, as a
`SWW_WAF_` setting can. "`rproxy`" in [`SPEC.md`](../SPEC.md) says what they do.
A time here is a whole number of milliseconds above zero, such as `2000`.
- `SWW_RPROXY_WAF_BACKEND` (required, no default): `waf`'s URL. An `http` or
`https` URL with a host and an optional port, and nothing more. `rproxy`
speaks HTTP/1.1 to it.
- `SWW_RPROXY_TIMEOUT_MS` (default `2000`): how long `rproxy` waits for `waf`'s
answer, to a question and to a report. A time; never `off`.
- `SWW_RPROXY_DEFAULT_DISPOSITION` (default `allow`): what is done with a
request when `waf` cannot be connected to, does not answer at all, or does not
answer within `SWW_RPROXY_TIMEOUT_MS`. `allow` passes it to the app, and
`deny` answers `503`. It does not apply to an answer `waf` gives, such as an
error.
- `SWW_RPROXY_WAF_BACKEND_TIMEOUT_MS` (default `2000`): how long `rproxy` waits
for `waf`'s answer, to a question and to a report. A time in milliseconds;
never `off`.
- `SWW_RPROXY_WAF_BACKEND_NO_ANSWER_DISPOSITION` (default `allow`): what is done
with a request when `waf` cannot be connected to, does not answer at all, or
does not answer within `SWW_RPROXY_WAF_BACKEND_TIMEOUT_MS`. `allow` passes it
to the app, and `deny` answers `503`. It does not apply to an answer `waf`
gives, such as an error.
- `SWW_RPROXY_MAX_REQUEST_SIZE` (default `100M`): the largest request body. A
size or `off`.
- `SWW_RPROXY_MAX_RESPONSE_SIZE` (default `1G`): the largest response body. A
@@ -466,11 +472,12 @@ A time here is a whole number of milliseconds above zero, such as `2000`.
- `SWW_RPROXY_MAX_REQUEST_TIME_MS` (default `60000`): how long the visitor may
take to send its request line and headers. It then also bounds, from the end
of the headers, the time until the app has been sent the whole request. A time
or `off`.
in milliseconds or `off`.
- `SWW_RPROXY_MAX_RESPONSE_TIME_MS` (default `1800000`): how long the answer may
take, from the end of the request to its last byte reaching the visitor. An
answer `rproxy` gives itself always has at least 10 seconds to be sent, and so
do the status and headers of the app's answer. A time or `off`.
do the status and headers of the app's answer. A time in milliseconds or
`off`.
- `SWW_RPROXY_LISTEN_ADDR` (default `:8080`): where `rproxy` listens, such as
`:9000`.
- `SWW_RPROXY_UPSTREAM_URL` (default `http://127.0.0.1:8081`): the app. An