Files and the journal, patterns with one <IP>, bounties within a window, bans in a Housecarl ban list with repeat offenders' bans growing; presets for sshd, jarl, housecarl, steward, bind-xfr, postfix-sasl, dovecot, nginx-auth and housecarl-drops; guard run/check/test/status/bans/ban/unban; a Debian package with a sandboxed unit; an end-to-end test with Housecarl. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
3.7 KiB
Markdown
86 lines
3.7 KiB
Markdown
# Presets and patterns
|
|
|
|
A preset is a watch Guard knows: its patterns, and where its program's
|
|
lines usually are. `guard presets` lists them; `guard presets sshd`
|
|
shows one's patterns.
|
|
|
|
```yaml
|
|
watch:
|
|
- name: ssh
|
|
preset: sshd
|
|
ban: {protocol: tcp, port: 22}
|
|
- name: ssh-file # the same, from a syslog file
|
|
preset: sshd
|
|
file: /var/log/auth.log
|
|
```
|
|
|
|
A watch's own `file` or `journal` replaces the preset's source, and its
|
|
`match` and `ignore` lines are added to the preset's.
|
|
|
|
| Preset | Source | Matches |
|
|
|---|---|---|
|
|
| `sshd` | journal, identifiers `sshd`, `sshd-session` | failed passwords and keys, unknown users, connections closed before login, too many attempts, failed key exchanges, garbage banners |
|
|
| `jarl`, `housecarl`, `steward` | journal, units `jarl.service`, `housecarl.service`, `steward.service` | their failed logins and refused API tokens (`msg="login failed" ip=…`, text or JSON logs) |
|
|
| `bind-xfr` | journal, identifier `named` | zone transfers BIND refused (TCP, so the address is real) |
|
|
| `postfix-sasl` | journal, identifiers `postfix/smtpd`, `postfix/submission/smtpd`, `postfix/smtps/smtpd` | failed SMTP logins |
|
|
| `dovecot` | journal, identifier `dovecot` | failed IMAP, POP3, submission and ManageSieve logins |
|
|
| `nginx-auth` | file `/var/log/nginx/error.log` | failed HTTP basic authentication |
|
|
| `housecarl-drops` | Housecarl's log of dropped packets | every TCP packet a logged rule dropped (on the firewall, for scans) |
|
|
|
|
OpenSSH 9.8 and later (Debian 13) logs logins from `sshd-session`, not
|
|
`sshd`; the preset reads both. Debian 13 has no `/var/log/auth.log`
|
|
unless rsyslog is installed: the journal is the place.
|
|
|
|
There's deliberately no preset for BIND's refused queries: they come
|
|
over UDP, whose source address anyone can fake, so banning on them would
|
|
let a stranger get your users' resolvers banned. Use BIND's response
|
|
rate limiting for floods.
|
|
|
|
## Writing patterns
|
|
|
|
A pattern is a Go regular expression ([RE2 syntax](https://github.com/google/re2/wiki/Syntax))
|
|
with `<IP>` once, where the address is:
|
|
|
|
```yaml
|
|
match:
|
|
- '^<IP> \S+ \S+ \[[^\]]+\] "POST /login[^"]*" 401 '
|
|
- 'authentication failure; .* rhost=<IP>(?: |$)'
|
|
```
|
|
|
|
`<IP>` matches IPv4 and IPv6 addresses, bracketed (`[2001:db8::9]`),
|
|
IPv4-mapped (`::ffff:203.0.113.9`, counted as `203.0.113.9`) or with a
|
|
zone. The text it matches must be a real address: `12:34:56` isn't one.
|
|
|
|
Patterns match anywhere in a line unless anchored. A line from a syslog
|
|
file starts with its date, host and program (`Oct 22 10:00:01 web
|
|
sshd[123]: `); a journal entry is the message alone. The presets begin
|
|
with `(?:^|: )` so they work on both.
|
|
|
|
**Where the address is matters.** Many log lines carry text a client
|
|
chose: a user name, a URL, a reverse DNS name. If a pattern lets that
|
|
text supply the address, a client can get any address banned:
|
|
|
|
```
|
|
Failed password for invalid user x from 198.51.100.1 port 22 from 203.0.113.9 port 4444 ssh2
|
|
```
|
|
|
|
Anchor patterns at the end of the line, or put `<IP>` where the
|
|
program writes the address after the client's text, so it is the
|
|
program's address that matches. The presets do; `guard test` shows
|
|
what yours find. Programs that log the address first (Jarl, Housecarl,
|
|
Steward log `msg="login failed" ip=… user=…`) are the easiest to match
|
|
safely.
|
|
|
|
## Trying patterns: guard test
|
|
|
|
```sh
|
|
guard test web-login /var/log/nginx/access.log.1
|
|
guard test ssh # a journal watch: its last 5000 entries
|
|
zcat /var/log/nginx/access.log.2.gz | guard test web-login -
|
|
```
|
|
|
|
It prints each matching line with its address, then the addresses that
|
|
would be banned. Nothing is banned. Lines from a file carry no time
|
|
Guard reads, so every match counts however far apart; the journal's
|
|
entries have times, and the watch's window is used.
|