Blob


1 #!/bin/sh
3 # WARNING!
4 # Export this variable properly to avoid locking you out
5 : ${QUICK_WHITELIST:=127.0.0.1}
7 alias log="logger -st http-ban"
8 alias show="doas /sbin/pfctl -t players -T show"
9 alias ban="doas /sbin/pfctl -t players -T add -f-"
10 alias grace="doas /sbin/pfctl -t players -T delete -f-"
12 # Filter functions returning 'count IP' based on HTTP return code
13 IN_300_HOSTS() {
14 awk '$(NF-1) >= 300 && $(NF-1) < 400 { print $2 }' | sort | uniq -c
15 }
17 IN_400_HOSTS() {
18 awk '$(NF-1) >= 400 && $(NF-1) < 500 { print $2 }' | sort | uniq -c
19 }
21 IN_500_HOSTS() {
22 awk '$(NF-1) >= 500 && $(NF-1) < 600 { print $2 }' | sort | uniq -c
23 }
25 # Our local logs
26 access() {
27 doas /bin/cat /var/www/logs/access.log
28 doas /usr/bin/zcat /var/www/logs/access.log.*gz 2>/dev/null
29 }
31 apply_whitelist() {
32 GF=$(for ip in $(printf %s\\n $QUICK_WHITELIST); do printf -- '-ve %s\n' "$ip"; done)
33 GF=${GF:-'.*'}
34 grep $GF
35 }
37 limit() {
38 awk -vtrig="${1:-10}" ' $1 >= trig { print $2 }'
39 }
41 pre_block() {
42 access | IN_500_HOSTS | limit 1
43 access | IN_400_HOSTS | limit 3
44 access | IN_300_HOSTS | limit 3
45 }
47 block() {
48 pre_block | sort | uniq | apply_whitelist
49 }
51 umask 127
53 block | sort >/tmp/http-ban.new
55 show | sort | awk '{ print $1 }' >/tmp/http-ban.current
57 DIFF=$(comm /tmp/http-ban.new /tmp/http-ban.current)
58 NEW=$(comm -23 /tmp/http-ban.new /tmp/http-ban.current)
59 GRACE=$(comm -13 /tmp/http-ban.new /tmp/http-ban.current)
61 rm /tmp/http-ban.*
63 test -n "$NEW" -o -n "$GRACE" || exit 0
65 # There's new IP's
66 if test -n "$NEW"; then
67 log Banning new IPs:
68 log <<..
69 $NEW
70 ..
71 ban <<..
72 $NEW
73 ..
74 fi
76 # There's Old IP's not attacking anymore
77 if test -n "$GRACE"; then
78 log Gracing old IPs:
79 log <<..
80 $GRACE
81 ..
83 grace <<..
84 $GRACE
85 ..
86 fi