check / check (push) Successful in 5m33s
The program is now sww, built from cmd/sww, with two modes: sww rproxy and sww discriminator. servewaf becomes discriminator everywhere it names that daemon: the package (internal/discriminator), its types, functions, files, the discriminator_line log field, and its docs and tests. smallwebwaf is left only where sneak's directive allows it: the documents' product name, the git.eeqj.de/sneak/smallwebwaf URLs, and the Go module path sneak.berlin/go/smallwebwaf. Everywhere else a name containing it takes the sww form: the package (internal/sww), metric names (sww_*), the X-Sww-* headers, the /_sww/ admin endpoints, the SWW_COMMAND setting, the OS user, and the state and rules directories. No logic changes. make check passes. Model: deepseek-v4-pro
74 lines
2.9 KiB
Markdown
74 lines
2.9 KiB
Markdown
# Rule files
|
|
|
|
The format of a rule file, and the default file the image ships. "Rule files" in
|
|
[`SPEC.md`](../SPEC.md) says how the files are read, watched and mounted, and
|
|
what each action leads to.
|
|
|
|
## The format
|
|
|
|
A rule is a line of four fields separated by spaces or tabs: an id, a target, an
|
|
action and a regex. The regex runs to the end of the line. Blank lines and lines
|
|
starting with `#` are ignored.
|
|
|
|
```
|
|
# id target action regex
|
|
env-file path ban (?i)^/\.env(\.[a-z]+)?$
|
|
scanner-agent user_agent ban (?i)\b(sqlmap|nikto|nuclei|wpscan)\b
|
|
```
|
|
|
|
- The id is letters, digits, `-` and `_`, unique across all files. The log line,
|
|
the metrics, the alerts and a ban's notes name the rule by it.
|
|
- The target is what the regex is matched against:
|
|
- `path`: the path without the query;
|
|
- `uri`: the path and the query together;
|
|
- `query`: the query as sent;
|
|
- `method`, `host`, `user_agent` and `referer`;
|
|
- `header:<Name>`: any one request header but `Host` and
|
|
`Transfer-Encoding`.
|
|
- The action is `log`, `block` or `ban`.
|
|
- The regex is in Go's syntax, RE2. It matches anywhere in the target unless
|
|
anchored with `^` and `$`. `(?i)` at its front makes it ignore case.
|
|
|
|
## The default file
|
|
|
|
The image ships one file, `share/rules.d/00-default.rules`, installed as
|
|
`/etc/sww/rules.d/00-default.rules`:
|
|
|
|
```
|
|
# 00-default.rules: probes no real visitor sends, anchored at the site root
|
|
|
|
# id target action regex
|
|
env-file path ban (?i)^/\.env(\.[a-z]+)?$
|
|
vcs-dir path ban (?i)^/\.(git|svn|hg|bzr)(/|$)
|
|
secrets-dir path ban (?i)^/\.(aws|ssh|docker|kube)/
|
|
secret-file path ban (?i)^/\.(htpasswd|htaccess|npmrc|netrc|pgpass|git-credentials|bash_history|DS_Store)$
|
|
editor-dir path ban (?i)^/\.(vscode|idea)/
|
|
backup-file path ban (?i)^/[^/]+\.(php(\.[a-z0-9]+|~)|sql(\.[a-z0-9]+)?)$
|
|
log-file path ban (?i)^/(debug|error|access)\.log$
|
|
compose-file path ban (?i)^/(docker-)?compose\.ya?ml$
|
|
php-shell path ban (?i)^/(shell|c99|r57|wso|alfa)\.php$
|
|
scanner-agent user_agent ban (?i)\b(sqlmap|nikto|nuclei|masscan|zgrab|wpscan)\b
|
|
path-traversal uri block (\.\./){2,}
|
|
empty-agent user_agent log ^$
|
|
```
|
|
|
|
## A file of your own
|
|
|
|
`discriminator` reads the rule files in its own container. Rules of your own go
|
|
in a file named to sort after the default, such as `50-site.rules`:
|
|
|
|
```
|
|
# 50-site.rules: WordPress probes, which this site never serves
|
|
wp-probe path ban (?i)^/(wp-login\.php|xmlrpc\.php|wp-admin/)
|
|
```
|
|
|
|
A `Dockerfile` built on the `smallwebwaf` image, for `discriminator` to run
|
|
from, adds it:
|
|
|
|
```dockerfile
|
|
COPY 50-site.rules /etc/sww/rules.d/50-site.rules
|
|
```
|
|
|
|
Or mount it there. A `path` rule applies on every site behind that
|
|
`discriminator`.
|