[OpenBSD]

[Previous: Packet Tagging] [Contents] [Next: Performance]

PF: Logging


Table of Contents


Introduction

Packet logging in PF is done by pflogd(8) which listens on the pflog0 interface and writes packets to a log file (normally /var/log/pflog) in tcpdump(8) binary format. Filter rules that specify the log or log (all) keyword are logged in this manner.

Logging Packets

In order to log packets passing through PF, the log keyword must be used within NAT/rdr and filter rules. Note that PF can only log packets that it's blocking or passing; you cannot specify a rule that only logs packets.

The log keyword causes all packets that match the rule to be logged. In the case where the rule is creating state, only the first packet seen (the one that causes the state to be created) will be logged.

The options that can be given to the log keyword are:

all
Causes all matching packets, not just the initial packet, to be logged. Useful for rules that create state.
user
Causes the UNIX user-id and group-id that owns the socket that the packet is sourced from/destined to (whichever socket is local) to be logged along with the standard log information.

Options are given in parenthesis after the log keyword; multiple options can be separated by a comma or space.

pass in log (all) on $ext_if inet proto tcp to $ext_if port 22 keep state

Log all incoming packets destined to port 22.

Reading a Log File

The log file written by pflogd is in binary format and cannot be read using a text editor. Tcpdump must be used to view the log.

To view the log file:

# tcpdump -n -e -ttt -r /var/log/pflog

Note that using tcpdump(8) to watch the pflog file does not give a real-time display. A real-time display of logged packets is achieved by using the pflog0 interface:

# tcpdump -n -e -ttt -i pflog0

NOTE: When examining the logs, special care should be taken with tcpdump's verbose protocol decoding (activated via the -v command line option). Tcpdump's protocol decoders do not have a perfect security history. At least in theory, a delayed attack could be possible via the partial packet payloads recorded by the logging device. It is recommended practice to move the log files off of the firewall machine before examining them in this way.

Additional care should also be taken to secure access to the logs. By default, pflogd will record 96 bytes of the packet in the log file. Access to the logs could provide partial access to sensitive packet payloads (like telnet(1) or ftp(1) usernames and passwords).

Filtering Log Output

Because pflogd logs in tcpdump binary format, the full range of tcpdump features can be used when reviewing the logs. For example, to only see packets that match a certain port:
# tcpdump -n -e -ttt -r /var/log/pflog port 80

This can be further refined by limiting the display of packets to a certain host and port combination:

# tcpdump -n -e -ttt -r /var/log/pflog port 80 and host 192.168.1.3

The same idea can be applied when reading from the pflog0 interface:

# tcpdump -n -e -ttt -i pflog0 host 192.168.4.2

Note that this has no impact on which packets are logged to the pflogd log file; the above commands only display packets as they are being logged.

In addition to using the standard tcpdump(8) filter rules, OpenBSD's tcpdump filter language has been extended for reading pflogd output:

Example:

# tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0

This display the log, in real-time, of inbound packets that were blocked on the wi0 interface.

Packet Logging Through Syslog

In many situations it is desirable to have the firewall logs available in ASCII format and/or to send them to a remote logging server. All this can be accomplished with two small shell scripts, some minor changes of the OpenBSD configuration files, and syslogd(8), the logging daemon. Syslogd logs in ASCII and is also able to log to a remote logging server.

First we have to create a user, pflogger, with a /sbin/nologin shell. The easiest way to create this user is with adduser(8).

After creating the user pflogger, create the following two scripts:

/etc/pflogrotate

	#!/bin/sh
	FILE=/home/pflogger/pflog5min.$(date "+%Y%m%d%H%M")
	kill -ALRM $(cat /var/run/pflogd.pid)
	if [ $(ls -l /var/log/pflog | cut -d " " -f 8) -gt 24 ]; then
	   mv /var/log/pflog $FILE
	   chown pflogger $FILE
	   kill -HUP $(cat /var/run/pflogd.pid)
	fi

/home/pflogger/pfl2sysl

	#!/bin/sh
	# feed rotated pflog file(s) to syslog
	# do not start if another instance of this script is already running
	pgrep pfl2sysl >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
		for logfile in /home/pflogger/pflog5min* ; do
			if [ -f "$logfile" ] ; then
				tcpdump -n -e -ttt -r $logfile | logger -t pf -p local0.info
				rm $logfile
			fi
		done
	fi

Edit root's cron job:

# crontab -u root -e

Add the following two lines:

# rotate pf log file every 5 minutes
0-59/5 * * * * /bin/sh /etc/pflogrotate

Create a cron job for user pflogger:

# crontab -u pflogger -e

Add the following two lines:

# feed rotated pflog file(s) to syslog
0-59/5 * * * * /bin/sh /home/pflogger/pfl2sysl

Add the following line to /etc/syslog.conf:

local0.info     /var/log/pflog.txt

If you also want to log to a remote log server, add the line:

local0.info     @syslogger

Make sure host syslogger has been defined in the hosts(5) file.

Create the file /var/log/pflog.txt to allow syslog to log to that file.

# touch /var/log/pflog.txt

Make syslogd notice the changes by restarting it:

# kill -HUP $(cat /var/run/syslog.pid)

All logged packets are now sent to /var/log/pflog.txt. If the second line is added they are sent to the remote logging host syslogger as well.

The script /etc/pflogrotate now processes and then deletes /var/log/pflog so rotation of pflog by newsyslog(8) is no longer necessary and should be disabled. However, /var/log/pflog.txt replaces /var/log/pflog and rotation of it should be activated. Change /etc/newsyslog.conf as follows:

    #/var/log/pflog       600    3    250    *    ZB /var/run/pflogd.pid
    /var/log/pflog.txt    600    7    *      24

PF will now log in ASCII to /var/log/pflog.txt. If so configured in /etc/syslog.conf, it will also log to a remote server. The logging is not immediate but it can take up to about 5-6 minutes (the cron job interval) before the logged packets appear in the file.

[Previous: Packet Tagging] [Contents] [Next: Performance]


[back] www@openbsd.org
$OpenBSD: logging.html,v 1.26 2006/05/01 00:54:29 nick Exp $