Up to now we have not mentioned much about logging. To my mind logging and by extension keeping track of what goes on in your network, or at least having the ability to get the information easily is an important part of staying in control of the network. Fortunately PF provides the opportunity to log exactly what you want by adding the log keyword to the rules you want logged. You may want to limit the amount of data a bit by specifying one interface where the logging is to be done. You do this by adding
set loginterface $ext_if
and then editing the rules you want to log, such as
pass out log from <clients> to any port $email \ label client-email keep state
This causes the traffic to be logged in a binary format which is really only intended to be used as tcpdump input. Note that log here only logs the packet which sets up the connection. If you want to log all traffic matching the rule, you use log (all) in the rule instead[1] .
The label part creates a new set of counters for various statistics for the rule. This can be quite convenient if you are invoicing others for bandwidth use, for example.
It is worth noting that from OpenBSD 4.1, the pflog interface is cloneable, which means you can configure as many as you need. At the same time, the log syntax for each rule was extended to let you specify on a per rule basis which pflog interface to log to, ie
pass log (all, to pflog2) inet proto tcp from $mailserver to any port smtp
to log outgoing SMTP traffic from the host $mailserver to elsewhere, with the log data ending up at the pflog2 interface.
Once you have enabled logging in one or more rules, PF logs via the pflog0 interface, and stores binary log data in the log file /var/log/pflog. The log file is useful for a permanent record and for those cases where you want to periodically convert some of the data to other formats. However, if you want to look at your traffic in real time, you can tell tcpdump to look at the pflog0 log interface instead.
Here is what the output from a couple of log rules can look like on a lazy Thursday afternoon:
$ doas tcpdump -n -e -ttt -i pflog0 tcpdump: WARNING: pflog0: no IPv4 address assigned tcpdump: listening on pflog0, link-type PFLOG Feb 16 16:43:20.152187 rule 0/(match) block in on ep0: 194.54.59.189.2559 > 194.54.107.19.139: [|tcp] (DF) Feb 16 16:48:26.073244 rule 27/(match) pass in on ep0: 61.213.167.236 > 194.54.107.19: icmp: echo request Feb 16 16:49:09.563448 rule 0/(match) block in on ep0: 61.152.249.148.80 > 194.54.107.19.55609: [|tcp] Feb 16 16:49:14.601022 rule 0/(match) block in on ep0: 194.54.59.189.3056 > 194.54.107.19.139: [|tcp] (DF) Feb 16 16:53:10.110110 rule 0/(match) block in on ep0: 68.194.177.173 > 194.54.107.19: [|icmp] Feb 16 16:55:54.818549 rule 27/(match) pass in on ep0: 61.213.167.237 > 194.54.107.19: icmp: echo request Feb 16 16:57:55.577782 rule 27/(match) pass in on ep0: 202.43.202.16 > 194.54.107.19: icmp: echo request Feb 16 17:01:27.108404 rule 0/(match) block in on ep0: 194.54.59.189.4520 > 194.54.107.19.139: [|tcp] (DF) Feb 16 17:11:02.137310 rule 0/(match) block in on ep0: 222.73.4.154.80 > 194.54.107.19.55609: [|tcp] Feb 16 17:14:05.739403 rule 0/(match) block in on ep0: 194.54.174.246.3970 > 194.54.107.19.135: [|tcp] (DF) Feb 16 17:14:08.715163 rule 0/(match) block in on ep0: 194.54.174.246.3970 > 194.54.107.19.135: [|tcp] (DF) Feb 16 17:14:09.308355 rule 0/(match) block in on ep0: 194.54.174.246.3970 > 194.54.107.19.135: [|tcp] (DF) Feb 16 17:19:01.853730 rule 27/(match) pass in on ep0: 203.84.214.5 > 194.54.107.19: icmp: echo request
The PF User Guide has a section devoted to logging which contains a number of very useful suggestions. Combined with among other things the tcpdump man pages, you should be able to extract any log data you will find useful.
[1] | In PF implementations based on OpenBSD 3.7 and earlier, the keyword for this was log-all. |