Blocking abusers on personal servers (OpenBSD PF)

2018-09-07

Inspired by Jordan Geoghegan’s article about pf-badhost I wanted to create my own list based on the “attack attempts” I get on my personal servers. This was tested on OpenBSD 6.3.

I just put together a small shell script that parses the httpd(8) logs and creates 2 files. One to load into a PF table and another one with entries I’m not sure about and had to be checked manually (either to add them to the patterns to search for or to discard them as legit).

It’s all really simple. The script is this one:

#!/bin/sh

FILE=$1
BLOCK=$2
BAD=""
UNKNOWN=""

patterns="login.cgi
admin
php
webdav
iframe"

[ -z "$FILE" ] && echo "Need a log file" && exit 1

while IFS= read -r line
do
    # ignore first line (rotation)
    echo "$line" | grep -q newsyslog && continue

    #gather some info
    IP=$(echo "$line" | awk '{print $2}')
    REQ=$(echo "$line" | awk -F'"' '{print $2}' | awk '{print $2}')

    # if you're behind a NAT and want to remove your network segment ...
    # is not really needed if you just filter on egress, but still.
    # echo "$IP" | grep -q "^10\\.42" && continue

    # sort things into unknown and bad folks
    if echo "$REQ" | grep -q -e "$patterns" ; then
        BAD="${BAD}${IP}
"
    else
        UNKNOWN="${UNKNOWN}${IP} ($REQ)
"
    fi
done < "$FILE"

echo "$BAD" | sort -uV > /tmp/bad_folks.txt
echo "$UNKNOWN" | sort -uV >> /tmp/to_check.txt

# and now we clean for duplicates and stuff ...
cat /etc/pf_tables/bad_folks.txt >> /tmp/bad_folks.txt
sort -uV /tmp/bad_folks.txt > /etc/pf_tables/bad_folks.txt

# and clean
rm /tmp/bad_folks.txt

if [ "$BLOCK" = "block" ]; then
    doas pfctl -t bad_folks -T replace -f /etc/pf_tables/bad_folks.txt
fi

Just fill the patterns variable with one grep pattern per line.

Of course you’ll have to add some rules to pf.conf:

table <bad_folks> persist file "/etc/pf_tables/bad_folks.txt"
block in quick on egress from <bad_folks> to any

Remember to add the necessary permissions on doas.conf to the user that runs the script.

Have any comments ? Send an email to the comments address.