This commit was merged in pull request #210.
This commit is contained in:
@@ -402,10 +402,10 @@ scrapers that send many requests slowly over hours or days. The hour limit is
|
||||
the main one.
|
||||
|
||||
- Per minute: 120, 2 requests a second. It leaves room for a person opening two
|
||||
pages at once with an empty cache. A gitea page opened with an empty cache
|
||||
pages at once with an empty cache. A web app's page opened with an empty cache
|
||||
loads 20 to 60 files, and a handful once cached.
|
||||
- Per hour: 1,500. A person reading code in gitea for a whole hour, a page every
|
||||
20 seconds, makes about 900 requests. A scraper making one request every 2
|
||||
- Per hour: 1,500. A person reading a site for a whole hour, a page every 20
|
||||
seconds, makes about 900 requests. A scraper making one request every 2
|
||||
seconds makes 1,800 an hour, more than the limit.
|
||||
- Per day: 6,000, four hours at the hour limit. A scraper making one request
|
||||
every 10 seconds makes 8,640 a day, more than the limit.
|
||||
@@ -417,7 +417,7 @@ the blocklists. An abuser that trips none of them is not caught.
|
||||
|
||||
Some legitimate clients pass the limits:
|
||||
|
||||
- An Actions runner asks gitea for work all day and can pass the limits.
|
||||
- A CI runner asks its code forge for work all day and can pass the limits.
|
||||
- Everyone behind one shared address, such as an office, shares one client's
|
||||
limits.
|
||||
|
||||
@@ -550,12 +550,11 @@ service's abuse comes from.
|
||||
By default the Core Rule Set reads the method, the URL with its query string,
|
||||
and the headers of every request. That is where automated attacks show:
|
||||
injection in query strings, path traversal, attacks carried in headers,
|
||||
scanners' user agents. It reads no request body. In front of a code forge such
|
||||
as gitea, bodies carry what people write and publish, such as issue text and
|
||||
files saved in the web editor. The Core Rule Set takes the shell commands and
|
||||
code in them for attacks. The default gives up refusing an attack carried in a
|
||||
body. The rule files, the limits and the bans still apply to the client that
|
||||
sends it.
|
||||
scanners' user agents. It reads no request body. In front of a code forge,
|
||||
bodies carry what people write and publish, such as issue text and files saved
|
||||
in the web editor. The Core Rule Set takes the shell commands and code in them
|
||||
for attacks. The default gives up refusing an attack carried in a body. The rule
|
||||
files, the limits and the bans still apply to the client that sends it.
|
||||
|
||||
- The Core Rule Set skips a path under `SWWAF_WAF_EXEMPT_PATHS`.
|
||||
- `SWWAF_WAF_PARANOIA_LEVEL` and `SWWAF_WAF_ANOMALY_THRESHOLD` are the Core Rule
|
||||
@@ -591,15 +590,14 @@ sends it.
|
||||
data, where binary content such as a git push trips rules written for text. A
|
||||
body the Core Rule Set cannot parse adds 5 to the score, and so does a
|
||||
multipart body cut by the limit in the middle of a part's header. Body
|
||||
inspection suits apps whose forms carry no code; `docs/gitea.md` records what
|
||||
it refuses in front of gitea.
|
||||
inspection suits apps whose forms carry no code.
|
||||
- `SWWAF_TRAP_PATHS` names paths the app never serves and only scanners ask for,
|
||||
such as `/wp-login.php` in front of gitea. This is the short form of a `path`
|
||||
rule with the `ban` action, for deployments that mount no rule files. A trap
|
||||
path is matched whole, without the query, against the path as sent and once
|
||||
percent-decoded: `/wp-login.php` matches `/wp-login.php?x=1` and
|
||||
`/%77p-login.php`, and does not match `/wp-login.php/` or
|
||||
`/blog/wp-login.php`.
|
||||
such as `/wp-login.php` in front of an app that is not WordPress. This is the
|
||||
short form of a `path` rule with the `ban` action, for deployments that mount
|
||||
no rule files. A trap path is matched whole, without the query, against the
|
||||
path as sent and once percent-decoded: `/wp-login.php` matches
|
||||
`/wp-login.php?x=1` and `/%77p-login.php`, and does not match `/wp-login.php/`
|
||||
or `/blog/wp-login.php`.
|
||||
- `SWWAF_ERROR_BURST_THRESHOLD` counts a client's refusals per minute of these
|
||||
kinds, and of no other:
|
||||
- a rule file match;
|
||||
@@ -609,8 +607,8 @@ sends it.
|
||||
More than this breaks a limit (see "Bans"). A client trying one attack after
|
||||
another is refused many times a minute; a person rarely more than a few
|
||||
times. Answers the app gives are not counted, since they do not tell a
|
||||
scanner from an ordinary client. In front of gitea, registry and git clients
|
||||
get `404` and `401` by design, hundreds of times a minute.
|
||||
scanner from an ordinary client. In front of a code forge, registry and git
|
||||
clients get `404` and `401` by design, hundreds of times a minute.
|
||||
|
||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in six ways, since in front of
|
||||
gitea it would otherwise refuse ordinary requests. The changes hold in front of
|
||||
@@ -836,7 +834,7 @@ and the default file.
|
||||
runs. It reads the files again once the directory has had no change for 2
|
||||
seconds, so that a file still being written is read whole. A file whose name
|
||||
starts with `.`, such as an editor's lock file, is not a rule file.
|
||||
- Files are read in name order (`00-default.rules` before `50-gitea.rules`),
|
||||
- Files are read in name order (`00-default.rules` before `50-site.rules`),
|
||||
rules in line order.
|
||||
- A rule's regex is Go's RE2 syntax. It has no backreferences or lookaround; in
|
||||
exchange matching time is linear in the input, so no rule can be made to stall
|
||||
@@ -865,14 +863,12 @@ and the default file.
|
||||
|
||||
- The image ships a default file, kept short and limited to patterns that are
|
||||
wrong for every app, with its path rules anchored at the site root. In front
|
||||
of gitea, `/.env` is a probe, while
|
||||
of a code forge, `/.env` is a probe, while
|
||||
`/<owner>/<repo>/src/branch/main/.env.example` is a file in a repository that
|
||||
any visitor may open. Anchor the paths of your own `ban` rules at the site
|
||||
root too. Anything else, such as a rule banning WordPress probes in front of
|
||||
gitea, belongs in a file the deployer adds to the image `servewaf` runs from,
|
||||
or mounts. A rule has one target, so a `path` rule applies on every site
|
||||
behind that `servewaf`. A directory mounted over `SWWAF_RULES_DIR` replaces
|
||||
the default file; single files mounted into it add to it.
|
||||
root too. A rule has one target, so a `path` rule applies on every site behind
|
||||
that `servewaf`. A directory mounted over `SWWAF_RULES_DIR` replaces the
|
||||
default file; single files mounted into it add to it.
|
||||
- Rules meant to be edited while `servewaf` runs belong in a mounted directory,
|
||||
not a mounted file. Many editors save a file by replacing it, and a container
|
||||
keeps seeing the old one when the file alone is mounted. The lookup database
|
||||
@@ -1695,8 +1691,7 @@ with no change to upaas. upaas builds the app's Dockerfile and runs the one
|
||||
container as it runs any app. The traefik labels route to port 8080, and the
|
||||
`SWRP_` settings go with the app's environment variables. `servewaf` runs in a
|
||||
container of its own, on a network the app's container can reach, with its state
|
||||
volume and the directory of any token file. `docs/gitea.md` records what the
|
||||
defaults do in front of gitea, and `script/gitea-requests` checks those notes.
|
||||
volume and the directory of any token file.
|
||||
|
||||
## Planned, not built
|
||||
|
||||
|
||||
Reference in New Issue
Block a user