Files
smallwebwaf/docs/settings.md
T
sneak 8282404453
check / check (push) Waiting to run
Seventh review: false statements fixed, README shortened to link the spec
- Engine error handling dropped as not built; unknown country and AS
  number each on its own; observe mode makes no ban of its own.
- README no longer restates the request steps, the refusal answers or
  the design; its step list uses the spec's numbers.
- Repeats, misreadable sentences, late verbs and long sentences reworded
  as the review asks.

Model: fable-5-1
2026-10-26 00:37:38 +00:00

16 KiB

Settings

Every setting, its default and the values it takes, in the groups of "Settings" in SPEC.md. That section gives the conventions, the settings that take off, the _FILE form, and what each group does and why.

Forms of values

  • A duration is Go's syntax, with d for days: 90s, 15m, 24h, 7d. Zero and negative durations are refused.
  • 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.
  • A list is comma separated, with spaces around items ignored. An empty item is refused.
  • A netblock is an address and a prefix length, such as 10.0.0.0/8. A bare address stands for itself alone.
  • A country is a two-letter code of ISO 3166-1, in either case: de and DE are the same. xk stands for Kosovo. A code that is not a country is refused, such as nk (North Korea is kp) or the withdrawn su.
  • An AS number is AS and the number, in either case, such as AS64496.
  • A percentage is a whole number from 0 to 100.
  • A path prefix starts with /, such as /assets/.

Core

  • SWWAF_UPSTREAM_URL (default http://127.0.0.1:8081): the app. An http or https URL with a host and an optional port, and nothing more.
  • SWWAF_LISTEN_ADDR (default :8080): where smallwebwaf listens: : and a port, such as :9000. Leave the host out (see "Ports" in SPEC.md).
  • SWWAF_INSTANCE_NAME (default: the container's host name): the instance name in every log line, alert and metric, such as fsn1app1/gitea. Valid UTF-8. No control character while SWWAF_ALERT_NTFY_URL is set. 1 to 48 printable ASCII characters without a space while SWWAF_LOG_REMOTE_URL is set and SWWAF_LOG_REMOTE_APP_NAME is not.
  • SWWAF_MODE (default enforce): enforce or observe.
  • SWWAF_TRUSTED_PROXIES (default 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16): the netblocks whose X-Forwarded-For is believed. Set but empty, it trusts nothing.
  • SWWAF_IPV6_GROUP_PREFIX (default 64): the prefix length of an IPv6 client's group, from 32 to 128.
  • SWWAF_MAX_TRACKED_CLIENTS (default 20000): the most clients kept, a whole number above zero.
  • SWWAF_MAX_BANS (default 5000): how many of its own bans smallwebwaf keeps, a whole number above zero.

Tokens

  • SWWAF_ADMIN_TOKEN (default unset): the token for the ban endpoints and /_smallwebwaf/clients/<ip>. At least 32 characters.
  • SWWAF_METRICS_TOKEN (default unset): the token for /_smallwebwaf/metrics. At least 32 characters.

State files

  • SWWAF_STATE_DIR (default /var/lib/smallwebwaf): the directory of the state files, an absolute path that exists and can be written.
  • SWWAF_STATE_WRITE_DELAY (default 10s): how long bans.json waits to be written after a ban is made, lifted or made permanent. A duration.
  • SWWAF_STATE_COUNTER_INTERVAL (default 15m): how often every state file is written. A duration.

Logging

  • SWWAF_LOG_LEVEL (default info): the least severe of smallwebwaf's own messages that are written: debug, info, warn or error.
  • SWWAF_LOG_REQUEST_HEADERS (default accept,accept-language,accept-encoding,content-type,origin,range): the request headers recorded in the log line, in either case. Host and Transfer-Encoding are refused; the host is the field host.
  • SWWAF_LOG_REMOTE_URL (default unset): a syslog server that also gets every line written to stdout: syslog+udp://, syslog+tcp:// or syslog+tls://, each with a host and a port and nothing more.
  • SWWAF_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.
  • SWWAF_LOG_REMOTE_BUFFER (default 10000): the most lines held while they wait to be sent, a whole number above zero.
  • SWWAF_LOG_REMOTE_FACILITY (default local0): the syslog facility: kern, user, mail, daemon, auth, syslog, lpr, news, uucp, cron, authpriv, ftp, or local0 to local7.
  • SWWAF_LOG_REMOTE_APP_NAME (default: SWWAF_INSTANCE_NAME): the app name in each syslog record, 1 to 48 printable ASCII characters without a space.

Metrics

  • SWWAF_METRICS_TOP_N (default 50): how many AS numbers and how many countries get series of their own. A whole number above zero.

Static lists

  • SWWAF_ALLOW_NETS (default empty): netblocks you trust, such as your monitoring (see step 3 in SPEC.md).
  • SWWAF_RATE_LIMIT_EXEMPT_NETS (default empty): netblocks whose clients are exempt from rate limiting and the byte limits.
  • SWWAF_DENY_NETS (default empty): netblocks whose clients are refused (see step 3 in SPEC.md).

Request rate limits, per client

  • SWWAF_RATE_LIMIT_PER_MINUTE (default 1000), SWWAF_RATE_LIMIT_PER_HOUR (default 10000) and SWWAF_RATE_LIMIT_PER_DAY (default 50000): the most requests a client may make in each window. A count or off.
  • SWWAF_RATE_LIMIT_EXEMPT_PATHS (default empty): path prefixes exempt from rate limiting and the byte limits, such as /assets/.

Byte limits, per client

  • SWWAF_BYTES_LIMIT_PER_MINUTE (default 10G), SWWAF_BYTES_LIMIT_PER_HOUR (default 20G) and SWWAF_BYTES_LIMIT_PER_DAY (default 50G): the most bytes counted for a client in each window. A size or off.
  • SWWAF_BYTES_COUNT (default both): which body bytes the byte limits count: response, request or both.

Size and time limits

  • SWWAF_CLIENT_REQUEST_TIMEOUT (default 60s): how long a client may take to send its request line and headers, and then, from the end of the headers, its body. A duration or off.
  • SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES (default 32K): the largest request line and headers. A size over 4K; never off.
  • SWWAF_CLIENT_IDLE_TIMEOUT (default 120s): how long a kept-open connection may wait for its next request before it is closed. A duration or off.
  • SWWAF_CLIENT_RESPONSE_TIMEOUT (default 30m): how long the answer may take to reach the client, from the end of the request to the last byte. A duration or off.
  • SWWAF_UPSTREAM_REQUEST_TIMEOUT (default 60s): how long connecting to the app and sending it the whole request may take. A duration or off.
  • SWWAF_UPSTREAM_RESPONSE_TIMEOUT (default 30m): how long the app may take to send its whole answer. A duration or off.
  • SWWAF_REQUEST_MAX_BYTES (default 100M): the largest request body. A size or off.
  • SWWAF_RESPONSE_MAX_BYTES (default 5G): the largest response body. A size or off.

Lookup of AS number and country

  • SWWAF_LOOKUP_SOURCE (default geojs): geojs, file or off. off stops the start while a setting that needs a lookup is set:
    • the two country lists;
    • SWWAF_ADD_LOOKUP_HEADERS;
    • the four biased threshold lists and SWWAF_ASN_LIMIT_PERCENT_URL;
    • SWWAF_UNKNOWN_LIMIT_PERCENT below 100;
    • an anomaly threshold per AS number.
  • SWWAF_LOOKUP_DB_PATH (default empty): the IPinfo Lite database file, in its .mmdb form, for SWWAF_LOOKUP_SOURCE=file.
  • SWWAF_LOOKUP_TIMEOUT (default 1s): 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.
  • SWWAF_ADD_LOOKUP_HEADERS (default false): true passes the app the client's AS number in X-Client-ASN and its country in X-Client-Country.

Country lists

  • SWWAF_DENIED_COUNTRIES (default empty): countries whose clients are refused, such as cn,ru,kp.
  • SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES (default empty): when set, the only countries whose clients get through, such as us,de. A country on both lists stops the start.

Biased thresholds

  • SWWAF_ASN_LIMIT_PERCENT (default empty): a list of AS numbers, each with : and a percentage, such as AS14061:50,AS16276:50,AS45102:25. An AS number listed twice is refused.
  • SWWAF_COUNTRY_LIMIT_PERCENT (default empty): the same by country, such as cn:25,ru:50.
  • SWWAF_ASN_BYTES_PERCENT and SWWAF_COUNTRY_BYTES_PERCENT (default empty): the same, for the byte limits alone.
  • SWWAF_UNKNOWN_LIMIT_PERCENT (default 100): the percentage for a client the lookup cannot place.
  • SWWAF_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. A URL that is also in SWWAF_BLOCKLIST_URLS is refused.

Attack detection

  • SWWAF_RULES_DIR (default /etc/smallwebwaf/rules.d): the directory of the rule files.
  • SWWAF_RULES_ENABLED (default true): false reads no rule file.
  • SWWAF_TRAP_PATHS (default empty): paths only scanners ask for, such as /wp-login.php,/xmlrpc.php. Each starts with / and holds no ?.
  • SWWAF_WAF_MODE (default block): off, detect or block.
  • SWWAF_WAF_PARANOIA_LEVEL (default 1): the Core Rule Set's paranoia level, from 1 to 4.
  • SWWAF_WAF_ANOMALY_THRESHOLD (default 5): the score at which a request is a match. A whole number above zero, or off.
  • SWWAF_WAF_DISABLED_RULES (default 920340,920420,920440,920640,930130,930140): the ids of Core Rule Set rules to switch off. Each a whole number above zero. An id from 900000 to 900999 is refused: those are the rules that set the Core Rule Set up, and smallwebwaf's own.
  • SWWAF_WAF_EXEMPT_PATHS (default empty): path prefixes the Core Rule Set does not inspect.
  • SWWAF_WAF_BODY_LIMIT (default off): off, or how much of a request body the Core Rule Set reads, a size of at most 1G.
  • SWWAF_ERROR_BURST_THRESHOLD (default 30): the most refusals of one client in a minute (see "Attack detection" in SPEC.md). A count or off.

Ban lengths, response and scope

  • SWWAF_BAN_RESPONSE (default 403): 403, 429 or close.
  • SWWAF_LIMIT_BAN_DURATION (default 1h): the ban for a first broken limit. A duration.
  • SWWAF_LIMIT_BAN_REPEAT_WINDOW (default 24h): the time after a ban ends within which breaking a limit again lengthens the next ban. A duration.
  • SWWAF_MAX_BAN_DURATION (default 7d): the longest ban for a broken limit; one that would be longer is permanent. A duration.
  • SWWAF_ATTACK_BAN_DURATION (default 7d): the ban for a first clear sign of attack. A duration.
  • SWWAF_BAN_SCOPE_V4_PREFIX (default 32): how much a ban on an IPv4 client covers: the prefix length of its netblock, from 0 to 32.

Reputation

  • SWWAF_BLOCKLIST_URLS (default empty): blocklists to fetch, such as https://www.spamhaus.org/drop/drop.txt. Each an http or https URL without a user or a fragment. A URL listed twice is refused.
  • SWWAF_BLOCKLIST_REFRESH (default 24h): how long a list waits after its last try before it is fetched again. A duration of 1h or more.
  • SWWAF_BLOCKLIST_ACTION (default deny): deny, limit:<percent> or log.
  • SWWAF_DNSBL_ZONES (default empty): the DNS blocklists to ask, such as dnsbl.dronebl.org. Each a DNS name of at most 189 characters. A Spamhaus zone carries its key, as in <key>.xbl.dq.spamhaus.net. A zone listed twice is refused, whatever its case or key.
  • SWWAF_DNSBL_RESOLVER (default unset): the resolver to ask the zones through, such as 192.0.2.53 or [2001:db8::53]:5353. An IP address with an optional port, 53 when none is given. Unset, the host's resolver is used.
  • SWWAF_ABUSEIPDB_KEY (default unset): the key of your AbuseIPDB account. A control character in it is refused.
  • SWWAF_ABUSEIPDB_MIN_SCORE (default 75): the least abuse confidence score, from 0 to 100, that is a hit.
  • SWWAF_ABUSEIPDB_DAILY_BUDGET (default 900): the most checks made in a day, a whole number above zero. AbuseIPDB's free accounts may make 1,000.
  • SWWAF_CROWDSEC_LAPI_URL (default unset): the local API of a CrowdSec engine you run, such as http://172.17.0.1:8080. An http or https URL without a user or a fragment; its decision list is at v1/decisions under it. Set without the key, it is refused. So is a decision list URL that is also in SWWAF_BLOCKLIST_URLS, or that is SWWAF_ASN_LIMIT_PERCENT_URL.
  • SWWAF_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.
  • SWWAF_REPUTATION_ACTION (default limit:25): deny, limit:<percent> or log, for DNS blocklist and AbuseIPDB hits.
  • SWWAF_REPUTATION_CACHE_TTL (default 24h): how long a zone's verdict or AbuseIPDB's score is used. A duration.
  • SWWAF_REPUTATION_TIMEOUT (default 2s): how long a query to a zone or a check with AbuseIPDB may take. A duration.

Alerting

  • SWWAF_ALERT_WEBHOOK_URL (default unset): the webhook that receives each alert as a JSON object. An http or https URL without a user or a fragment.
  • SWWAF_ALERT_WEBHOOK_HEADERS (default empty): headers sent with each post, such as Authorization:Bearer 0123456789abcdef. A list of name, : and value. A value cannot hold a comma.
  • SWWAF_ALERT_SLACK_WEBHOOK_URL (default unset): the Slack incoming webhook that receives each alert as a message, checked as the webhook URL is.
  • SWWAF_ALERT_NTFY_URL (default unset): the ntfy topic that receives each alert, as the topic's full URL, such as https://ntfy.sh/my-alerts, checked as the webhook URL is.
  • SWWAF_ALERT_NTFY_TOKEN (default unset): an ntfy access token. A control character in it is refused.
  • SWWAF_ALERT_EVENTS (default ban,permanent_ban,waf_block,anomaly,reputation_hit,source_failure,file_error): the event types alerts are sent for, from those in alerts.md but summary. Any other name is refused.
  • SWWAF_ALERT_COOLDOWN (default 15m): how long after an alert is sent its repeats are held back. A duration or off.
  • SWWAF_ALERT_MAX_PER_HOUR (default 60): the most alerts sent in an hour. A whole number above zero, or off.

Anomaly thresholds

Each scope has four thresholds: the most requests and the most bytes counted in a minute and in an hour. Requests are counts, bytes are sizes. Each is off by default. The four thresholds per client are:

  • SWWAF_ANOMALY_CLIENT_REQUESTS_PER_MINUTE;
  • SWWAF_ANOMALY_CLIENT_REQUESTS_PER_HOUR;
  • SWWAF_ANOMALY_CLIENT_BYTES_PER_MINUTE;
  • SWWAF_ANOMALY_CLIENT_BYTES_PER_HOUR.

The other scopes' names have another prefix before the same four endings, such as REQUESTS_PER_MINUTE:

  • SWWAF_ANOMALY_NET_...: per netblock around a client. Two settings give the netblock's length:
    • SWWAF_ANOMALY_NET_V4_PREFIX (default 24, from 0 to 32) for an IPv4 client;
    • SWWAF_ANOMALY_NET_V6_PREFIX (default 48, from 0 to 128) for an IPv6 client.
  • SWWAF_ANOMALY_ASN_...: per AS number.
  • SWWAF_ANOMALY_TOTAL_...: the whole service.
  • SWWAF_WATCH_...: each netblock in SWWAF_WATCH_NETS, as a whole. SWWAF_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 name, or with a bad netblock, is refused. So is a name used twice.

Settings given as files

To give a token as a file, as "Tokens" under "Deployment" in SPEC.md describes, make the file on the host:

mkdir -p /srv/app/tokens
openssl rand -hex 32 > /srv/app/tokens/metrics
chown 65532:65532 /srv/app/tokens/metrics
chmod 0400 /srv/app/tokens/metrics

Then mount its directory into the container read-only, and name the file:

docker run \
    -v /srv/app/tokens:/etc/smallwebwaf/tokens:ro \
    -e SWWAF_METRICS_TOKEN_FILE=/etc/smallwebwaf/tokens/metrics \
    ...

Fixed limits

A few limits are fixed rather than settings:

  • at most 100,000 GeoJS answers are kept;
  • at most 100,000 DNS blocklist verdicts and 100,000 AbuseIPDB scores are kept;
  • at most 1,000 DNS blocklist queries are under way at once;
  • at most 20,000 anomaly counters are kept;
  • each alert destination's queue holds at most 1,000 alerts.