`smallwebwaf servewaf` runs today's checks on the visitor's request each question carries, answers rproxy, and passes nothing to an app. rproxy reports every request servewaf answered. A report counts an allowed request's bytes and writes servewaf's second log line. The table holds a copy of what a report needs, never the request, so a report cannot reach a request being handled. Judgement call: a question's body is read before any check; over 64 KiB gets 400. Judgement call: a report's bytes and durations have ceilings, so they cannot overflow. Judgement call: a `close` disposition for SWWAF_BAN_RESPONSE=close. Model: opus-5-5
17 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.
servewaf
smallwebwaf servewaf uses every setting here but these, which it ignores:
SWWAF_UPSTREAM_URLandSWWAF_TRUSTED_PROXIES;- the five timeouts under "Size and time limits";
SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES,SWWAF_REQUEST_MAX_BYTESandSWWAF_RESPONSE_MAX_BYTES.
An invalid value of one of these still stops the start, and the line of settings at start still shows them.
SWWAF_ADD_LOOKUP_HEADERS puts the headers on the answer to rproxy, not on a
request to an app. SWWAF_WAF_BODY_LIMIT has an effect up to 64 KiB less one
byte, whatever its value. A question carries no more of a body than 64 KiB (see
"servewaf" in SPEC.md).
Forms of values
- A duration is Go's syntax, with
dfor days:90s,15m,24h,7d. Zero and negative durations are refused. - A size is a number of bytes with an optional
K,MorG, which are powers of 1024, so1Kis 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:
deandDEare the same.xkstands for Kosovo. A code that is not a country is refused, such asnk(North Korea iskp) or the withdrawnsu. - An AS number is
ASand the number, in either case, such asAS64496. - A percentage is a whole number from 0 to 100.
- A path prefix starts with
/, such as/assets/.
Core
SWWAF_UPSTREAM_URL(defaulthttp://127.0.0.1:8081): the app. AnhttporhttpsURL with a host and an optional port, and nothing more.SWWAF_LISTEN_ADDR(default:8080): wheresmallwebwaflistens::and a port, such as:9000. Leave the host out (see "Ports" inSPEC.md).SWWAF_INSTANCE_NAME(default: the container's host name): theinstancename in every log line, alert and metric, such asfsn1app1/gitea. Valid UTF-8. No control character whileSWWAF_ALERT_NTFY_URLis set. 1 to 48 printable ASCII characters without a space whileSWWAF_LOG_REMOTE_URLis set andSWWAF_LOG_REMOTE_APP_NAMEis not.SWWAF_MODE(defaultenforce):enforceorobserve.SWWAF_TRUSTED_PROXIES(default10.0.0.0/8,172.16.0.0/12,192.168.0.0/16): the netblocks whoseX-Forwarded-Foris believed. Set but empty, it trusts nothing.SWWAF_IPV6_GROUP_PREFIX(default64): the prefix length of an IPv6 client's group, from 32 to 128.SWWAF_MAX_TRACKED_CLIENTS(default20000): the most clients kept, a whole number above zero.SWWAF_MAX_BANS(default5000): how many of its own banssmallwebwafkeeps, 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(default10s): how longbans.jsonwaits to be written after a ban is made, lifted or made permanent. A duration.SWWAF_STATE_COUNTER_INTERVAL(default15m): how often every state file is written. A duration.
Logging
SWWAF_LOG_LEVEL(defaultinfo): the least severe ofsmallwebwaf's own messages that are written:debug,info,warnorerror.SWWAF_LOG_REQUEST_HEADERS(defaultaccept,accept-language,accept-encoding,content-type,origin,range): the request headers recorded in the log line, in either case.HostandTransfer-Encodingare refused; the host is the fieldhost.SWWAF_LOG_REMOTE_URL(default unset): a syslog server that also gets every line written to stdout:syslog+udp://,syslog+tcp://orsyslog+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 asyslog+tlsserver'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(default10000): the most lines held while they wait to be sent, a whole number above zero.SWWAF_LOG_REMOTE_FACILITY(defaultlocal0): the syslog facility:kern,user,mail,daemon,auth,syslog,lpr,news,uucp,cron,authpriv,ftp, orlocal0tolocal7.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(default50): 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 inSPEC.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 inSPEC.md).
Request rate limits, per client
SWWAF_RATE_LIMIT_PER_MINUTE(default6000),SWWAF_RATE_LIMIT_PER_HOUR(default100000) andSWWAF_RATE_LIMIT_PER_DAY(default1000000): the most requests a client may make in each window. A count oroff.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(default4G),SWWAF_BYTES_LIMIT_PER_HOUR(default20G) andSWWAF_BYTES_LIMIT_PER_DAY(default200G): the most bytes counted for a client in each window. A size oroff.SWWAF_BYTES_COUNT(defaultboth): which body bytes the byte limits count:response,requestorboth.
Size and time limits
SWWAF_CLIENT_REQUEST_TIMEOUT(default60s): 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 oroff.SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES(default32K): the largest request line and headers. A size over4K; neveroff.SWWAF_CLIENT_IDLE_TIMEOUT(default120s): how long a kept-open connection may wait for its next request before it is closed. A duration oroff.SWWAF_CLIENT_RESPONSE_TIMEOUT(default30m): how long the answer may take to reach the client, from the end of the request to the last byte. A duration oroff.SWWAF_UPSTREAM_REQUEST_TIMEOUT(default60s): how long connecting to the app and sending it the whole request may take. A duration oroff.SWWAF_UPSTREAM_RESPONSE_TIMEOUT(default30m): how long the app may take to send its whole answer. A duration oroff.SWWAF_REQUEST_MAX_BYTES(default100M): the largest request body. A size oroff.SWWAF_RESPONSE_MAX_BYTES(default1G): the largest response body. A size oroff.
Lookup of AS number and country
SWWAF_LOOKUP_SOURCE(defaultgeojs):geojs,fileoroff.offstops 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_PERCENTbelow100;- an anomaly threshold per AS number.
SWWAF_LOOKUP_DB_PATH(default empty): the IPinfo Lite database file, in its.mmdbform, forSWWAF_LOOKUP_SOURCE=file.SWWAF_LOOKUP_TIMEOUT(default1s): how long a request waits for its client's first answer from GeoJS, and how long a request to GeoJS may take. A duration; neveroff.SWWAF_ADD_LOOKUP_HEADERS(defaultfalse):truepasses the app the client's AS number inX-Client-ASNand its country inX-Client-Country.
Country lists
SWWAF_DENIED_COUNTRIES(default empty): countries whose clients are refused, such ascn,ru,kp.SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES(default empty): when set, the only countries whose clients get through, such asus,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 asAS14061:50,AS16276:50,AS45102:25. An AS number listed twice is refused.SWWAF_COUNTRY_LIMIT_PERCENT(default empty): the same by country, such ascn:25,ru:50.SWWAF_ASN_BYTES_PERCENTandSWWAF_COUNTRY_BYTES_PERCENT(default empty): the same, for the byte limits alone.SWWAF_UNKNOWN_LIMIT_PERCENT(default100): the percentage for a client the lookup cannot place.SWWAF_ASN_LIMIT_PERCENT_URL(default unset): thehttporhttpsURL of a text file with one AS number and percentage on each line, such asAS64496:50. A URL that is also inSWWAF_BLOCKLIST_URLSis refused.
Attack detection
SWWAF_RULES_DIR(default/etc/smallwebwaf/rules.d): the directory of the rule files.SWWAF_RULES_ENABLED(defaulttrue):falsereads 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(defaultblock):off,detectorblock.SWWAF_WAF_PARANOIA_LEVEL(default1): the Core Rule Set's paranoia level, from 1 to 4.SWWAF_WAF_ANOMALY_THRESHOLD(default5): the score at which a request is a match. A whole number above zero, oroff.SWWAF_WAF_DISABLED_RULES(default920340,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, andsmallwebwaf's own.SWWAF_WAF_EXEMPT_PATHS(default empty): path prefixes the Core Rule Set does not inspect.SWWAF_WAF_BODY_LIMIT(defaultoff):off, or how much of a request body the Core Rule Set reads, a size of at most1G.SWWAF_ERROR_BURST_THRESHOLD(default30): the most refusals of one client in a minute (see "Attack detection" inSPEC.md). A count oroff.
Ban lengths, response and scope
SWWAF_BAN_RESPONSE(default403):403,429orclose.SWWAF_LIMIT_BAN_DURATION(default1h): the ban for a first broken limit. A duration.SWWAF_LIMIT_BAN_REPEAT_WINDOW(default24h): the time after a ban ends within which breaking a limit again lengthens the next ban. A duration.SWWAF_MAX_BAN_DURATION(default7d): the longest ban for a broken limit; one that would be longer is permanent. A duration.SWWAF_ATTACK_BAN_DURATION(default7d): the ban for a first clear sign of attack. A duration.SWWAF_BAN_SCOPE_V4_PREFIX(default32): 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 ashttps://www.spamhaus.org/drop/drop.txt. Each anhttporhttpsURL without a user or a fragment. A URL listed twice is refused.SWWAF_BLOCKLIST_REFRESH(default24h): how long a list waits after its last try before it is fetched again. A duration of1hor more.SWWAF_BLOCKLIST_ACTION(defaultdeny):deny,limit:<percent>orlog.SWWAF_DNSBL_ZONES(default empty): the DNS blocklists to ask, such asdnsbl.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 as192.0.2.53or[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(default75): the least abuse confidence score, from 0 to 100, that is a hit.SWWAF_ABUSEIPDB_DAILY_BUDGET(default900): 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 ashttp://172.17.0.1:8080. AnhttporhttpsURL without a user or a fragment; its decision list is atv1/decisionsunder it. Set without the key, it is refused. So is a decision list URL that is also inSWWAF_BLOCKLIST_URLS, or that isSWWAF_ASN_LIMIT_PERCENT_URL.SWWAF_CROWDSEC_LAPI_KEY(default unset): the key the engine gave forsmallwebwaf, ascscli bouncers add smallwebwafprints it. Set without the URL, it is refused.SWWAF_REPUTATION_ACTION(defaultlimit:25):deny,limit:<percent>orlog, for DNS blocklist and AbuseIPDB hits.SWWAF_REPUTATION_CACHE_TTL(default24h): how long a zone's verdict or AbuseIPDB's score is used. A duration.SWWAF_REPUTATION_TIMEOUT(default2s): 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. AnhttporhttpsURL without a user or a fragment.SWWAF_ALERT_WEBHOOK_HEADERS(default empty): headers sent with each post, such asAuthorization: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 ashttps://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(defaultban,permanent_ban,waf_block,anomaly,reputation_hit,source_failure,file_error): the event types alerts are sent for, from those inalerts.mdbutsummary. Any other name is refused.SWWAF_ALERT_COOLDOWN(default15m): how long after an alert is sent its repeats are held back. A duration oroff.SWWAF_ALERT_MAX_PER_HOUR(default60): the most alerts sent in an hour. A whole number above zero, oroff.
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(default24, from 0 to 32) for an IPv4 client;SWWAF_ANOMALY_NET_V6_PREFIX(default48, from 0 to 128) for an IPv6 client.
SWWAF_ANOMALY_ASN_...: per AS number.SWWAF_ANOMALY_TOTAL_...: the whole service.SWWAF_WATCH_...: each netblock inSWWAF_WATCH_NETS, as a whole.SWWAF_WATCH_NETS(default empty) is a list of name,=and netblock, such asoffice=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;
servewafholds at most 10,000 answered requests awaiting their reports.