Ban lists: where Guard and fail2ban ban addresses
A program bans an address (every port, or a protocol's ports) for a time; the ban list says what it is kept from: the firewall, some hosts behind it, or everything. Bans drop ahead of every rule, close the address's connections, group IPv6 by /64, are kept in the database across restarts and audited. Never banned: the inside, the firewall's own addresses, the caller, the list's never. bans grant (bans:write:LIST), hc banlist/bans/ban/unban, Traffic -> Bans, a fail2ban action in contrib/, and failed logins and refused tokens logged for Guard and fail2ban. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f56eefae2
commit
500bfc7bdd
44 files changed
+2541
-39
No files matched your search
@@ -480,6 +480,96 @@ run "the VLAN rule goes" 0 H rule delete -y "$VR"
|
||||
run "the VLAN zone goes" 0 H zone delete -y iot
|
||||
R ip link del enp2s0.30
|
||||
|
||||
# ---- ban lists: bans kept from the firewall, a host, or everything
|
||||
|
||||
# DNS is open to the internet on the router (tcp/53): a listener answers.
|
||||
docker exec -d ${P}-router sh -c 'while [ ! -f /tmp/nodns ]; do echo dns | nc -N -l 0.0.0.0 53; done'
|
||||
sleep 1
|
||||
run "the router's tcp/53 from the internet" 0 connect net $WAN4 53
|
||||
contains "^dns$"
|
||||
run "a ban list for the firewall" 0 H banlist add router --scope firewall
|
||||
# The lab's internet host shares the router's WAN /64: ban IPv6 addresses
|
||||
# alone (a /64 would hold the router's own, and is refused).
|
||||
run "a ban list for jellyfin" 0 H banlist add jf --scope hosts --host $JF4 --host $JF6 --group-v6 128
|
||||
run "a ban list for everything" 0 H banlist add edge --scope everything --max-time 1h
|
||||
run "the lists" 0 H banlist list
|
||||
contains "jf *hosts *10.88.10.57, 2001:db8:7f3d:10::57 *0"
|
||||
# The firewall's own DNS, for the internet host.
|
||||
run "ban from the firewall's tcp/53" 0 H ban router $NET4 --tcp dns --reason "e2e"
|
||||
contains "banned $NET4, tcp/53, in router"
|
||||
run "the router's DNS is cut for it" 1 connect net $WAN4 53
|
||||
run "the port forward isn't (scope firewall)" 0 connect net $WAN4 8096
|
||||
contains "^jellyfin$"
|
||||
run "the ban in the ruleset" 0 R nft list ruleset
|
||||
contains "ip saddr . meta l4proto . th dport @ban_[0-9]*_v4_svc counter packets [1-9]"
|
||||
run "lift it" 0 H unban router $NET4
|
||||
contains "1 bans lifted"
|
||||
run "DNS again" 0 connect net $WAN4 53
|
||||
contains "^dns$"
|
||||
# fail2ban on jellyfin, with Housecarl's action and a token for its list.
|
||||
run "a user for jellyfin's fail2ban" 0 H user add f2b-jf --no-password --grant bans:write:jf
|
||||
R sh -c "/w/hc token create jf --user f2b-jf > /w/f2b.token 2>/dev/null"
|
||||
run "its token" 0 test -s "$WORK/f2b.token"
|
||||
# f2b ACTION ip=… port=…: the action's command from contrib/, with the
|
||||
# jail's values, as fail2ban runs it (on jellyfin).
|
||||
f2b() {
|
||||
local conf="$ROOT/contrib/fail2ban/action.d/housecarl.conf" a=$1; shift
|
||||
local cmd curl
|
||||
cmd=$(awk -v a="$a" '$0 ~ "^"a" *=" {sub(/^[^=]*= */,""); print; on=1; next} on && /^[ \t]/ {sub(/^[ \t]+/,""); print; next} {on=0}' "$conf" | tr '\n' ' ')
|
||||
curl=$(sed -n 's/^_curl *= *//p' "$conf")
|
||||
cmd=${cmd//<_curl>/$curl}
|
||||
local kv
|
||||
for kv in "$@" "list=jf" "url=http://$LAN4:8070" "tokenfile=/w/f2b.token" "curlopts=" "protocol=tcp" "bantime=600" "name=jellyfin"; do
|
||||
cmd=${cmd//<${kv%%=*}>/${kv#*=}}
|
||||
done
|
||||
docker exec ${P}-jf sh -c "$cmd"
|
||||
}
|
||||
run "fail2ban bans the internet host's https" 0 f2b actionban ip=$NET4 port=https
|
||||
run "the port forward to jellyfin is cut for it" 1 connect net $WAN4 8096
|
||||
run "the router's DNS isn't (scope hosts)" 0 connect net $WAN4 53
|
||||
run "fail2ban bans its IPv6 address" 0 f2b actionban ip=$NET6 port=https
|
||||
run "IPv6 to jellyfin's 443 is cut" 1 connect net $JF6 443
|
||||
run "the bans" 0 H bans jf
|
||||
contains "$NET4 *tcp/443 .*f2b-jf *fail2ban/jellyfin"
|
||||
contains "$NET6 *tcp/443"
|
||||
run "never the inside" 22 f2b actionban ip=$CLIENT4 port=https
|
||||
run "refused, audited" 0 H audit --action ban.add
|
||||
contains "failure.*inside"
|
||||
run "fail2ban unbans" 0 f2b actionunban ip=$NET4
|
||||
run "the port forward works again" 0 connect net $WAN4 8096
|
||||
contains "^jellyfin$"
|
||||
run "unbanning what Housecarl already let go is no error" 0 f2b actionunban ip=$NET4
|
||||
run "and the IPv6 ban" 0 f2b actionunban ip=$NET6
|
||||
run "jellyfin by IPv6 again" 0 connect net $JF6 443
|
||||
contains "jellyfin6"
|
||||
run "the token can't ban elsewhere" 22 f2b actionban ip=$NET4 port=https list=router
|
||||
# Everything, cutting a connection that is open, and kept over a restart.
|
||||
R touch /tmp/nodns
|
||||
connect net $WAN4 53 >/dev/null 2>&1
|
||||
docker exec -d ${P}-router sh -c 'nc -l 0.0.0.0 53 > /w/held.out'
|
||||
sleep 1
|
||||
docker exec -d ${P}-net sh -c "sleep 30 | nc $WAN4 53"
|
||||
sleep 1
|
||||
run "an open connection from the internet host" 0 H connections --search "$NET4 :53"
|
||||
contains "$NET4:[0-9]* *$WAN4:53"
|
||||
run "ban it from everything" 0 H ban edge $NET4 --time 1d
|
||||
contains "banned $NET4, every port, in edge (ends in 1h)"
|
||||
contains "[1-9][0-9]* connections closed"
|
||||
run "its connection is gone" 0 H connections --search "$NET4 :53"
|
||||
not_contains ":53"
|
||||
run "nothing gets through for it" 1 connect net $WAN4 8096
|
||||
stop
|
||||
run "restart housecarld" 0 start
|
||||
run "the ban is back after the restart" 0 R nft list ruleset
|
||||
contains "$NET4 timeout [0-9hms]* expires"
|
||||
run "still nothing for it" 1 connect net $WAN4 8096
|
||||
run "lift it" 0 H unban edge $NET4
|
||||
run "the ban is out of the ruleset" 0 R nft list ruleset
|
||||
not_contains "$NET4 timeout"
|
||||
run "the port forward again" 0 connect net $WAN4 8096
|
||||
contains "^jellyfin$"
|
||||
run "the lists go" 0 sh -c "docker exec ${P}-router /w/hc banlist delete -y router && docker exec ${P}-router /w/hc banlist delete -y jf && docker exec ${P}-router /w/hc banlist delete -y edge"
|
||||
|
||||
# ---- renaming a zone others refer to
|
||||
|
||||
run "rename the imported dhcp zone" 0 H zone update dhcp --name lan
|
||||
|
||||
Reference in new issue
Block a user