check / check (push) Waiting to run
The old README opened with project history and one list of a hundred settings. The new one leads with what smallwebwaf is, what it protects against, how to build and deploy it, what happens to a request, the settings most deployments touch, how to check it works, the entrypoints, the rationale and the design, as REPO_POLICIES.md requires. The reference lists, every setting, the rule file format, the endpoints, the request log's fields, the alert events, the metrics, the state files, the image and the gitea notes, move to files under docs/, each linked from the README, with SPEC.md as the one place for behaviour. Every statement was checked against the code on next. Model: fable-5-1
16 KiB
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
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. Their clients are refused only for a size or time limit or a missing or wrong token.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 always refused.
Request rate limits, per client
SWWAF_RATE_LIMIT_PER_MINUTE(default1000),SWWAF_RATE_LIMIT_PER_HOUR(default10000) andSWWAF_RATE_LIMIT_PER_DAY(default50000): 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(default10G),SWWAF_BYTES_LIMIT_PER_HOUR(default20G) andSWWAF_BYTES_LIMIT_PER_DAY(default50G): 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(default5G): the largest response body. A size oroff.
Lookup of AS number and country
SWWAF_LOOKUP_SOURCE(defaultgeojs):geojs,fileoroff.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 for a rule match, a trap path, a Core Rule Set match or a failed token check. 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. Needs a lookup source.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.