Securing Small Networks with OpenBSD, Part 4

First of all, I'd like to thank you for all of the mail I've been receiving from you recently. Your questions and comments are a great source of inspiration! I also hope that the praises are deserved. As promised in the last installment of "Securing Small Networks with OpenBSD," today we'll have a closer look at logging packets with pf.

Packet logging is a good network administration practice, because it lets us spot problems with communication and early signs of break-in attempts. Of course, logging packets alone won't help; we need to learn how to analyze and manage log files generated by pf. But first things first.

Enabling Packet Logging in pf

Packet logging is enabled when the log keyword is included in a pf rule. Therefore, all we have to do is edit /etc/pf.conf and put the log keyword after either the in or out keywords. For example

# block all incoming packets
block in on $ExtIF all

becomes

# block and log all incoming packets
block in log on $ExtIF all

Next, save changes made to /etc/pf.conf and update pf rules with

# /sbin/pfctl -R /etc/pf.conf

The packets caught by the modified rule are now sent to the pflog0 interface, where they're picked up by the pflogd daemon, which stores them in /var/log/pflog.

Because pf log files are binary files unfit for viewing with human eyes, we need a tool that translates them into plain text. That tool is the venerable tcpdump utility, one of the essential UNIX network monitoring programs. We can use it to watch pf logs in real time with

# /usr/sbin/tcpdump -i pflog0

(Typing the full access path to the binary you want to run, as I do above, is a little paranoid, but it is not a bad thing to be paranoid, when it comes to security.)

You can ignore the warning (tcpdump prints it, because the pflog interface does not have an IP address, which it doesn't need) and wait for packets to fall into your carefully planted honey pot. It is quite likely that you will not see any packets at all, for a long time. What went wrong? Nothing, actually. You are lucky and your firewall is not a target of a port scan or a cracking attempt. A series of repeated attempts to connect to unavailable ports is a sign that somebody might be trying to "probe" your machine for open ports. They are not necessarily trying to break in (they may be network researchers, or even your ISP), but you should be alert and if such attempts occur frequently, you might need to investigate them more closely. However, before you raise an alarm and call the authorities, make sure that these attempted connections are not responses to your own connection attempts!

It's a good feeling to know that all is quiet on the blocked ports, but I bet you'd like to see some action, if only to check that everything is working right. All right, open /etc/pf.conf again and add the log keyword to the pass out rules for the external interface. We can change

# allow TCP IPv4 connections to the outside world, keep state
pass out on $ExtIF inet proto tcp all flags S/SA modulate state
pass out on $ExtIF inet proto { udp, icmp } all keep state

to

# allow and log TCP IPv4 connections to the outside world, keep state
pass out log on $ExtIF inet proto tcp all flags S/SA modulate state
pass out log on $ExtIF inet proto { udp, icmp } all keep state

Save the changes and replace the old pf ruleset as described above. Then run tcpdump again, and point your Web browser to any external page. Now you should see a stream of packets similar to the one shown below:

What you see above is a group of packets sent from the network located behind a firewall to the O'Reilly Network servers, in a successful attempt to retrieve the previous installment of this series. The packets sent in response to that request are missing from the above list, because we did not ask pf to log them.

If you want to make sense of the data printed by tcpdump, it's a good idea to start with "Tools of the Trade," written by Carl Constantine. For your information, foo.foo.bar is the name of an imaginary host connected to the Internet, and dns.barab.fof is the name of an imaginary DNS server located outside of the network from which the lookup request was sent. The xxx.xxx.xxx.xxx and yyy.yyy.yyy.yyy strings are IP addresses of the oreillynet.com servers. In your case, all of these will have real names and numbers and be quite likely totally different from another reader's results.

If you are on a small network and only you are generating the traffic, the rate at which information will scroll before your eyes should not make it difficult to follow the flow of datagrams. But if you have more users actively surfing the Internet, then you will almost certainly not be able to catch up with the traffic. Fortunately, there are ways to manage that flood of packets.