deploy: add firewalld direct-rule flood-mitigation script (per-IP hashlimit on the IRC ports); gitignore the pinned bin/ artifact
This commit is contained in:
parent
be97089dfa
commit
d8a963d0f9
2 changed files with 65 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -15,3 +15,4 @@ Cargo.lock
|
|||
*.xlines
|
||||
*.metadata
|
||||
*.reputation
|
||||
bin/
|
||||
|
|
|
|||
64
deploy/firewalld-echoircd.sh
Executable file
64
deploy/firewalld-echoircd.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env bash
|
||||
# echoIRCd kernel-layer flood mitigation — defense-in-depth on top of the ircd's own
|
||||
# per-IP `accept_rate` limiter. Drops excess NEW connections to the IRC client ports
|
||||
# (per source IP) in the kernel, before they ever reach the daemon.
|
||||
#
|
||||
# THIS BOX RUNS firewalld, so the rule is installed through firewalld's DIRECT interface
|
||||
# (`firewall-cmd --direct`). firewalld then owns the rule — it won't be flushed on a
|
||||
# `firewall-cmd --reload`, and `--permanent` persists it across reboot. (A raw
|
||||
# `iptables -I INPUT ...` would be silently wiped the next time firewalld rebuilds its
|
||||
# ruleset, which is why that approach is wrong here.)
|
||||
#
|
||||
# SAFE: it only DROPs the rate-limited *excess* to 6767/6770. It changes no zone,
|
||||
# service, or default policy; ports 6767/6770 stay open as firewalld already has them.
|
||||
# Loopback is exempt (the liveness probe + local tools). Idempotent and one-command
|
||||
# removable.
|
||||
#
|
||||
# Apply: sudo deploy/firewalld-echoircd.sh add
|
||||
# Remove: sudo deploy/firewalld-echoircd.sh del
|
||||
# Show: sudo deploy/firewalld-echoircd.sh show
|
||||
#
|
||||
# Uses iptables `hashlimit` (per-source-IP). firewalld rich rules can't express this —
|
||||
# their `limit` is a single global token bucket, not per-source — so a direct rule is
|
||||
# the right tool. IPv4 only (the ircd binds 0.0.0.0); add an ipv6 rule if you ever bind ::.
|
||||
set -u
|
||||
|
||||
PORTS="6767,6770" # IRC client ports (plaintext + TLS); S2S 7700 intentionally left alone
|
||||
RATE="30/second" # sustained NEW connections/sec per source IP
|
||||
BURST="60" # instantaneous burst allowed per source IP
|
||||
ACTION="${1:-}"
|
||||
|
||||
# the raw rule (added into INPUT at priority 0 = top): drop NEW conns to the IRC ports
|
||||
# from any single source IP that exceeds the rate. `! -i lo` exempts loopback.
|
||||
RULE=(ipv4 filter INPUT 0
|
||||
! -i lo -p tcp -m multiport --dports "$PORTS"
|
||||
-m conntrack --ctstate NEW
|
||||
-m hashlimit --hashlimit-name ircrate --hashlimit-mode srcip
|
||||
--hashlimit-above "$RATE" --hashlimit-burst "$BURST"
|
||||
-j DROP)
|
||||
|
||||
add_one() { firewall-cmd "$@" --direct --add-rule "${RULE[@]}"; }
|
||||
del_one() { firewall-cmd "$@" --direct --remove-rule "${RULE[@]}" >/dev/null 2>&1 || true; }
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
del_one # runtime: clear any prior copy (idempotent)
|
||||
del_one --permanent
|
||||
add_one # runtime (takes effect now)
|
||||
add_one --permanent # persists across reboot / reload
|
||||
echo "echoircd rate-limit added via firewalld direct rule: ports ${PORTS}, ${RATE} burst ${BURST} per source IP (runtime + permanent)"
|
||||
;;
|
||||
del)
|
||||
del_one
|
||||
del_one --permanent
|
||||
echo "echoircd rate-limit removed (runtime + permanent)"
|
||||
;;
|
||||
show)
|
||||
echo "== runtime direct rules =="; firewall-cmd --direct --get-all-rules
|
||||
echo "== permanent direct rules =="; firewall-cmd --permanent --direct --get-all-rules
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 {add|del|show}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Loading…
Add table
Add a link
Reference in a new issue