commit 88f3e13dadb91d43520a3e4ceff3b61170d32759 from: xs date: Tue Jan 30 18:37:27 2024 UTC Todolist done, now testing commit - 78bfe33e2736141f6e7e5566694c61ddbf273dd2 commit + 88f3e13dadb91d43520a3e4ceff3b61170d32759 blob - 238890e43813e6caf6c352887e3de6e476bfe15e blob + c384389b84d8488db0b174aac34dfff0d1c144ce --- README.md +++ README.md @@ -10,6 +10,13 @@ Feel free to try it and share enhancements/ideas aroun For me it has been quite effective. +# Environment Variables + +- `HTTPBAN_WHITELIST`: List of whitelisted IP's +- `HTTPBAN_LIMIT_500`: Number of hits in the 500's HTTP return code range +- `HTTPBAN_LIMIT_400`: Number of hits in the 400's HTTP return code range +- `HTTPBAN_LIMIT_300`: Number of hits in the 300's HTTP return code range + # Installation 1. Create an user @@ -25,26 +32,23 @@ For me it has been quite effective. # cat /etc/doas.conf permit nopass _httpban cmd /bin/cat args /var/www/logs/access.log permit nopass _httpban cmd /usr/bin/zcat args /var/www/logs/access.log.*gz - permit nopass _httpban cmd /sbin/pfctl args -t players -T show - permit nopass _httpban cmd /sbin/pfctl args -t players -T add -f- - permit nopass _httpban cmd /sbin/pfctl args -t players -T delete -f- + permit nopass _httpban cmd /sbin/pfctl args -t httpban -T show + permit nopass _httpban cmd /sbin/pfctl args -t httpban -T add -f- + permit nopass _httpban cmd /sbin/pfctl args -t httpban -T delete -f- -4. Create a table in /etc/pf.conf +4. Create a table in /etc/pf.conf # cat /etc/pf.conf - table persist - block in quick on egress from + table persist + block in quick on egress from 3. Run it as _httpban (here every 5 minutes) # crontab -eu _httpban + HTTPBAN_WHITELIST='127.0.0.1 67.225.146.248' + HTTPBAN_500=20 + HTTPBAN_400=15 + HTTPBAN_300=10 */5 * * * * -s http-ban -# TODO - -- [ ] parametrize the table name, as is not really a good name -- [ ] remove unused filter functions -- [ ] make it more pleasant to read / give the impression I'm mentally saner - -WORK branch: I have no idea if it works. Probably not yet. Need more -time to test and yet tired. +WORK branch: bug fix and testing phase blob - 16531b725391f48cc1450c1af17d46e12651916a blob + 20656c482a7d12328bafbce1863ef45312abbb33 --- http-ban.sh +++ http-ban.sh @@ -1,15 +1,17 @@ #!/bin/sh -# WARNING! -# Export this variable properly to avoid locking you out -: ${QUICK_WHITELIST:=127.0.0.1} +: ${HTTPBAN_WHITELIST:=127.0.0.1} +: ${HTTPBAN_LIMIT_500:=10} +: ${HTTPBAN_LIMIT_400:=10} +: ${HTTPBAN_LIMIT_300:=10} +: ${HTTPBAN_TABLE:=httpban} alias log="logger -st http-ban" alias show="doas /sbin/pfctl -t players -T show" alias ban="doas /sbin/pfctl -t players -T add -f-" alias grace="doas /sbin/pfctl -t players -T delete -f-" -# Filter functions returning 'count IP' based on HTTP return code +# Filter functions returning 'count IP' based on HTTP return code IN_300_HOSTS() { awk '$(NF-1) >= 300 && $(NF-1) < 400 { print $2 }' | sort | uniq -c } @@ -32,20 +34,15 @@ limit() { awk -vtrig="${1:-10}" ' $1 >= trig { print $2 }' } -pre_block() { - access | IN_500_HOSTS | limit 1 - access | IN_400_HOSTS | limit 3 - access | IN_300_HOSTS | limit 3 -} - block() { - GF=$(for ip in $(printf %s\\n $QUICK_WHITELIST); do printf -- '-e "^%s$" ' "$ip"; done) - pre_block | sort | uniq | { - if test -n "$GF"; then - grep -v $GF - else - cat - - fi + set -- $HTTPBAN_WHITELIST + set -- $(for ip; do printf -- '-e %s ' "$ip" done) + { + access | IN_500_HOSTS | limit "$HTTPBAN_LIMIT_500" + access | IN_400_HOSTS | limit "$HTTPBAN_LIMIT_400" + access | IN_300_HOSTS | limit "$HTTPBAN_LIMIT_300" + } | sort | uniq | { + test -n "$*" && grep -v "$@" || cat } } @@ -53,8 +50,8 @@ umask 127 block | sort >/tmp/http-ban.new +# Diff processing show | sort | awk '{ print $1 }' >/tmp/http-ban.current - DIFF=$(comm /tmp/http-ban.new /tmp/http-ban.current) NEW=$(comm -23 /tmp/http-ban.new /tmp/http-ban.current) GRACE=$(comm -13 /tmp/http-ban.new /tmp/http-ban.current)