UFW script for Logwatch

I enabled UFW on an Ubuntu server recently and started getting all manner of stuff in my logwatch reports. It activated a section called 'iptables' and started logging every line in syslog with [UFW BLOCK] in it. It was marginally interesting, but not really worth the space devoted to it, so I decided to write a little script to parse the UFW log and summarise the top Blocked Hosts and top Blocked Ports. Therefore I could easily see if there was a change in pattern.

Turns out one of the hardest things to do was to turn off the iptables report. My setup on Ubuntu (your mileage may vary with other distros) was just to put all the config into /etc/logwatch/conf/override.conf. Changing MailTo, MailFrom etc in that file worked fine. But apparently the commands to turn off reports don't work in that file, so the first thing I had to do was to create a new /etc/logwatch/conf/logwatch.conf file by copying it from the default directory, and adding my config items from override.conf to it.

cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/
nano logwatch.conf

The magic line you need to add is:

Service = "-iptables"

– the minus sign turns it off, which I suppose makes sense.

OK now the big iptables report is gone, we need to write a quick bash script to run through /var/log/syslog (or ufw.log) and throw out some info. You can apparently write logwatch scripts in any language – php, shell, perl etc – as long as they put out something to standard output: whatever they output to the terminal in other words.

So here's what I came up with. Not elegant, but it works. If you copy it from this page, make sure you swap curly quotes for straight ones:

#!/bin/bash
# UFW log analyser

LOGFILE=/var/log/syslog
FROMDATE=$(date --date="1 day ago" +"%b %_d %H")
FROMLINE=$(grep -n "${FROMDATE}" ${LOGFILE} | head -n 1 | awk 'BEGIN { FS = ":" } { print $1 }')

# Need to catch it if there are less than 24 hours of logs, and analyse the whole file.
if [ -z "${FROMLINE}" ] ; then
FROMDATE=`head -n 1 ${LOGFILE} | awk '{ print $1 " " $2 " "$3}'`
FROMLINE=1
fi

TOTALEVENTS=`tail -n +${FROMLINE} ${LOGFILE} | grep "UFW BLOCK" | wc -l`
echo "==== Processing ${LOGFILE}  ======"
echo "Starting Date = ${FROMDATE}:00 (Line ${FROMLINE})"
echo "Total Events = ${TOTALEVENTS}"
echo
echo "==== 20 Commonest Ports Blocked ============"
echo "  Tries   Port"
tail -n +${FROMLINE} ${LOGFILE} | grep "UFW BLOCK" | sed 's/.*DPT=//' | sed 's/ WINDOW=.*//' | sed 's/ LEN=.*//' | sort -n | uniq -c | sort -nr | head -n 20
echo
echo "==== 20 Commonest Hosts Blocked ============"
echo "  Tries   Host"
tail -n +${FROMLINE} ${LOGFILE} | grep "UFW BLOCK" | sed 's/.*SRC=//' | sed 's/ DST=.*//' | sort -n | uniq -c | sort -nr | head -n 20

The script itself goes in /etc/logwatch/scripts/services/ufw, And you'll need to chmod 750 it to make it executable.

You also need a tiny conf file in /etc/logwatc/conf/services/ufw.conf

Title = "UFW Summary"
Logfile = NONE

So that just about does it. The output looks something like this

==== Processing /var/log/syslog  ======
Starting Date = Feb 14 06:43:32:00 (Line 1)
Total Events = 105

==== 20 Commonest Ports Blocked ============
Tries   Port
18 1433
14 58996
10 3389
9 3306
7 5900
7 23
7 1080
5 8080
4 5060
3 53
3 4899
3 22
3 135
2 808
1 8888
1 8443
1 8081
1 8000
1 6060
1 3129

==== 20 Commonest Hosts Blocked ============
Tries   Host
8 93.174.88.31
7 58.3.0.55
7 121.110.99.31
6 88.225.226.167
4 220.249.99.147
4 168.93.190.169
3 62.249.146.46
3 183.60.130.110
2 92.243.110.235
2 85.17.250.197
2 60.28.255.179
2 60.191.153.156
2 54.241.54.66
2 222.186.15.32
2 205.204.85.97
2 198.136.26.81
2 189.2.20.70
1 98.143.37.104
1 94.102.49.213
1 88.253.217.111