Blob


1 #!/bin/sh
3 QUICK_WHITELIST=192.168.10.10
5 alias log="logger -st http-ban"
6 alias show="doas /sbin/pfctl -t players -T show"
7 alias ban="doas /sbin/pfctl -t players -T add -f-"
8 alias grace="doas /sbin/pfctl -t players -T delete -f-"
10 # Filter functions returning 'count IP' based on HTTP return code
11 IN_300_HOSTS() {
12 awk '$(NF-1) >= 300 && $(NF-1) < 400 { print $2 }' | sort | uniq -c
13 }
15 IN_400_HOSTS() {
16 awk '$(NF-1) >= 400 && $(NF-1) < 500 { print $2 }' | sort | uniq -c
17 }
19 IN_500_HOSTS() {
20 awk '$(NF-1) >= 500 && $(NF-1) < 600 { print $2 }' | sort | uniq -c
21 }
23 # Our local logs
24 access() {
25 last_access
26 doas /bin/cat /var/www/logs/access.log
27 doas /usr/bin/zcat /var/www/logs/access.log.*gz 2>/dev/null
28 }
30 apply_whitelist() {
31 GF=$(for ip in $(printf %s\\n $QUICK_WHITELIST); do printf -- '-ve %s\n' "$ip"; done)
32 GF=${GF:-'.*'}
33 grep $GF
34 }
36 limit() {
37 awk -vtrig="${1:-10}" ' $1 >= trig { print $2 }'
38 }
40 pre_block() {
41 access | IN_500_HOSTS | limit 1
42 access | IN_400_HOSTS | limit 3
43 access | IN_300_HOSTS | limit 3
44 }
46 block() {
47 pre_block | sort | uniq | apply_whitelist
48 }
50 umask 127
52 block | sort >/tmp/http-ban.new
54 show | sort | awk '{ print $1 }' >/tmp/http-ban.current
56 DIFF=$(comm /tmp/http-ban.new /tmp/http-ban.current)
57 NEW=$(comm -23 /tmp/http-ban.new /tmp/http-ban.current)
58 GRACE=$(comm -13 /tmp/http-ban.new /tmp/http-ban.current)
60 rm /tmp/http-ban.*
62 test -n "$NEW" -o -n "$GRACE" || exit 0
64 # There's new IP's
65 if test -n "$NEW"; then
66 log Banning new IPs:
67 log <<..
68 $NEW
69 ..
70 ban <<..
71 $NEW
72 ..
73 fi
75 # There's Old IP's not attacking anymore
76 if test -n "$GRACE"; then
77 log Gracing old IPs:
78 log <<..
79 $GRACE
80 ..
82 grace <<..
83 $GRACE
84 ..
85 fi