Files
guard/internal/config/example.yaml
T
abrown38andClaude Opus 5.5 d06bf8d531 Guard: watch logs, ban misbehaving addresses in Housecarl
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>
2026-10-22 16:29:37 +01:00

72 lines
2.3 KiB
YAML

# Guard's configuration (docs/configuration.md). Guard reads it when it
# starts: systemctl restart guard after a change, and 'guard check' to
# check it first.
# Housecarl, which does the banning. Give Guard a token for its ban list
# alone; on the firewall:
# hc banlist add web --scope hosts --host 10.0.10.57
# hc user add guard-web --no-password --grant bans:write:web
# hc token create web --user guard-web # as root
housecarl:
url: https://router.lan:8070
# On the firewall itself, the local socket instead of url:
# socket: /run/housecarl/housecarl.sock
token_file: /etc/guard/token
# ca_cert: /etc/guard/housecarl-ca.pem # a private CA
# The ban list a watch bans into, unless it says another.
list: web
# Never banned, whatever the logs say: addresses, prefixes, host names
# (looked up every ten minutes). Housecarl itself never bans the inside
# networks, the firewall's own addresses, or this machine.
never_ban:
# - 198.51.100.7
# - 2001:db8:ffff::/48
# - vps.example.org
# What every watch does unless it says otherwise: this many matches of an
# address within this time ban it for this long. Each earlier ban of the
# address within "forget" doubles the time ("factor"), up to "max".
defaults:
hits: 5
within: 10m
ban: 1h
repeat: {factor: 2, max: 1w, forget: 1w}
watch:
# OpenSSH, from the journal (the preset knows where).
- name: ssh
preset: sshd
ban: {protocol: tcp, port: 22}
# A log file, with your own pattern: <IP> is where the address is.
# - name: web-login
# file: /var/log/nginx/access.log
# match:
# - '^<IP> \S+ \S+ \[[^\]]+\] "POST /login[^"]*" 401 '
# ignore:
# - '/healthz'
# hits: 10
# ban: {time: 6h}
# Jarl's, Housecarl's or Steward's failed logins (presets jarl,
# housecarl, steward), banned from every port of the list's scope.
# - name: jarl
# preset: jarl
# On the firewall: sources whose packets Housecarl's logged rules keep
# dropping (TCP only: UDP sources can be faked). The token also needs
# log:read.
# - name: scans
# preset: housecarl-drops
# hits: 20
# within: 1m
# ban: {list: edge, time: 1d}
# Guard's memory of its bans (repeat offenders), and the socket 'guard
# status' asks.
state: /var/lib/guard/state.json
socket: /run/guard/guard.sock
log: {level: info, format: text}