View Single Post
  #1   (View Single Post)  
Old 9th February 2014
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 3,503
Default Simplifying pflog file parsing

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.
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump

Last edited by J65nko; 9th February 2014 at 06:33 PM.
Reply With Quote