Hackers are constantly trying to break in. As a rule, most (all?) of these attempts are logged in /var/log/auth.log, so there's a good way to detect them and block them with a shell script.
#! /usr/local/bin/fish
# auth_block.sh
# reads auth.log, looks for "Authenticatian error lines" or "Invalid user", then adds those IPs to pfctl blacklist
# Robb Allan, 4 February 2021
set LOGFILE /var/log/auth_block.log
set BLACKLIST_FILE /usr/local/etc/pf/blacklist
set TMP_FILE /tmp/hack.txt
set TMP_TMP /tmp/hack2.txt
if test (count $argv) -eq 1
switch $argv
case "--review"
/bin/rm $TMP_FILE 2>> /dev/null
/usr/bin/bzgrep -e "error: PAM: Authentication error for illegal user" /var/log/auth.log* | /usr/bin/grep -ve "COMMAND=" | sed -nEe 's/.* ([.0-9]{7,15})$/\1/p' > $TMP_FILE
/usr/bin/bzgrep -e "[Ii]nvalid user" /var/log/auth.log* | grep -ve "COMMAND=" | sed -nEe 's/.* ([.0-9]{7,15}) port.*/\1/p' >> $TMP_FILE
/usr/bin/sort -n $TMP_FILE | /usr/bin/uniq > $TMP_TMP
/bin/cat $TMP_TMP
/bin/rm $TMP_FILE $TMP_TMP
case "--refresh"
/bin/echo (/bin/date "+%b %e %T") "running auth_block in refresh mode..." >> $LOGFILE
/bin/echo -n (/bin/date "+%b %e %T") "replacing blacklist..." >> $LOGFILE
/sbin/pfctl -t blacklist -T replace -f /usr/local/etc/pf/blacklist >> $LOGFILE 2>> $LOGFILE
/bin/echo -n (/bin/date "+%b %e %T") "replacing whitelist..." >> $LOGFILE
/sbin/pfctl -t whitelist -T replace -f /usr/local/etc/pf/whitelist >> $LOGFILE 2>> $LOGFILE
/sbin/pfctl -f /etc/pf.conf
/bin/echo (/bin/date "+%b %e %T") "done."\n >> $LOGFILE
case "--update"
/bin/echo (/bin/date "+%b %e %T") "running auth_block in update mode..." >> $LOGFILE
/bin/rm $TMP_FILE 2>> /dev/null
/usr/bin/bzgrep -e "error: PAM: Authentication error for illegal user" /var/log/auth.log* | /usr/bin/grep -ve "COMMAND=" | sed -nEe 's/.* ([.0-9]{7,15})$/\1/p' > $TMP_FILE
/usr/bin/bzgrep -e "[Ii]nvalid user" /var/log/auth.log* | grep -ve "COMMAND=" | sed -nEe 's/.* ([.0-9]{7,15}) port.*/\1/p' >> $TMP_FILE
if test -e $TMP_FILE
if test -e $BLACKLIST_FILE
/bin/cat $BLACKLIST_FILE >> $TMP_FILE
end
/usr/bin/sort -n $TMP_FILE | /usr/bin/uniq > $TMP_TMP
cmp $TMP_TMP $BLACKLIST_FILE >> /dev/null
if test $status -eq 1
/bin/cp $BLACKLIST_FILE $BLACKLIST_FILE.(date -j "+%Y%m%d.%H%M")
/bin/echo (diff -C 0 $BLACKLIST_FILE $TMP_TMP)| /usr/bin/mail -s "blacklist IPs changed" <my email address>
/bin/cat $TMP_TMP > $BLACKLIST_FILE
/bin/chmod a+w $BLACKLIST_FILE
/bin/echo (/bin/date "+%b %e %T") "blacklist file rebuilt..." >> $LOGFILE
/bin/echo -n (/bin/date "+%b %e %T") "replacing blacklist..." >> $LOGFILE
/sbin/pfctl -t blacklist -T replace -f /usr/local/etc/pf/blacklist >> $LOGFILE 2>> $LOGFILE
/bin/echo -n (/bin/date "+%b %e %T") "replacing whitelist..." >> $LOGFILE
/sbin/pfctl -t whitelist -T replace -f /usr/local/etc/pf/whitelist >> $LOGFILE 2>> $LOGFILE
/sbin/pfctl -f /etc/pf.conf
/bin/echo (tail -5 /var/log/auth_block.log) | /usr/bin/mail -s "blacklist updated" <my email address>
else
/bin/echo (/bin/date "+%b %e %T") "nothing to change." >> $LOGFILE
# /bin/echo "nada" (tail -3 /var/log/auth_block.log) | /usr/bin/mail -s "blacklist NOT updated" <my email address>
end
/bin/rm $TMP_FILE $TMP_TMP
/bin/echo (/bin/date "+%b %e %T") "done."\n >> $LOGFILE
end
case '*'
/bin/echo "unknown argument(s): " $argv
end
else
/bin/echo "auth_block requires an argument."
/bin/echo "Usage: auth_block [--review (list IPs to screen)| --refresh (reload pf)| --update (scan logs and rebuild blacklist)]"
end
Run this script with one of the following arguments:
- "--review": reads the logfile, looks for invalid login attempts, collects the IPs, uniq's and sort's them, and prints them to stdout.
- "--refresh": reloads the blacklist and whitelist files in /usr/local/pf, and resets the pf packet-filtering daemon.
- "--update": backs up the original /usr/local/pf/blacklist file, reads the logfile, looks for invalid login attempts, collects the IPs, merges them with the blacklist file, uniq's and sort's them, and tests for any change. If so, writes a new blacklist file, reloads it to pf, resets pf, and sends a notification email.