Last week I decided it was about time to write a Perl script for parsing
/var/log/pflog files.
If you use logging in the
pf.conf ruleset, the logged packets are written to this file in a modified tcpdump PCAP format.
You can read this file with something like
# tcpdump -tttt -nr /var/log/pflog | less
or save it in a text file with
# tcpdump -tttt -nr /var/log/pflog > ./pflog.txt
.
The output looks like:
Code:
# date(1) time(2) ty source(4) destination(5) header info (6)
# 2014-01-31 16:14:30.938665 IP 80.25.124.114 > 1.2.22.222: ICMP echo request, id 0, seq 0, length 64
# 2014-01-31 16:16:35.262293 IP 180.188.194.9.55459 > 1.2.22.222.25: Flags [S], seq 1118489574, win 14600, options [mss 1460,sackOK,TS[|tcp]>
To parse this with Perl I came up with the following subroutine using a long regular expression:
Code:
if ( /^ # at beginning of line
(\d{4}-\d{2}-\d{2}) # capture date yyyy-mm-dd
\s+ # one or more spaces
(\d{2}:\d{2}:\d{2}\.\d+) # hh:mm:sec.fractional
\s+
(\w+) # traffic type i.e. IP
\s+
(\d+\.\d+.\d+\.\d+ # source IP
(?: # non-capture grouping start
\.\d+ # a '.' and one of more digits as port number
)? # end of optional port number
) # end capture
\s+
>
\s+
(\d+\.\d+.\d+\.\d+ # destination IP address
(?: # non-capture grouping start
\.\d+ # optional port number
)? # end of optional port number
) # end capture
:\s+
(.+) # packet header info
$ # up to end of line
/x # allow comments and whitespace
)
After two or three tries it worked. Although it looks complicated, it actually is quite straightforward.
The only tricky thing was to use the non-capturing grouping
(?: ........ ) to match an optional port number.
tcpdump prefixes the port number with a period and appends it to the IP address. In
180.188.194.9.55459 > 1.2.22.222.25 the source IP is 180.188.194.9 using source port 55459, while the destination IP is 1.2.22.222 with port 25.
After a few days, after a walk with the dog, I found a much simpler method. Well actually two.