BSD DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Archiving PF Firewall Logs
Pages: 1, 2, 3

Configuring the firewall

Before you start rebuilding your network, it would be a good idea to test the software side of this configuration without touching the hardware, that way you will have fewer things to debug. After you have the software working, reconfiguring the hardware is rather easy. Also, to avoid the risk choking your network with log transfers during the testing, either choose a time when the traffic is low or log only a small fraction of traffic, just to test things on a smaller scale before you let the whole thing run on full power.



To limit the size of logs, copy /etc/pf.conf to /etc/pf.conf_old, open /etc/pf.conf in a text editor, and add the log-all keyword to one of the pass out rules for the external interface. That way you will be logging only the outbound traffic leaving the external interface and originating from your private network. For example, change this rule

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

to this

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

You can begin logging all traffic again, when you are sure that the monitoring station is receiving logs.

While you are editing the pf configuration file, you should also add a line that prevents pf from logging packets sent from the firewall to the monitoring station to port 22, where you should have ssh listening for connections. If you don't do that, you will create a loop which will bring your network to a halt (the packets carrying the logs will be logged and sent to the monitoring station and logged again, and sent to the monitoring station, and so on ...).

The following rule should be added at the end of the pf rule section for the internal private network segment interface (you may need to modify it to match your network configuration, but don't add the log or log-all keywords):

# allow pfloggin on a remote host 
# (there are two lines below) 
 
pass  out on $PrvIF inet proto tcp  from xxx.xxx.xxx.xxx 
		to yyy.yyy.yyy.yyy port 22 modulate state 
 
pass  out on $PrvIF inet proto udp  from xxx.xxx.xxx.xxx 
		to yyy.yyy.yyy.yyy port 22 keep state

Save the modified /etc/pf.conf and reload it with

# pfctl -R /etc/pf.conf

Your firewall is now logging only the outbound traffic. It is not sending the logs to the monitoring station, for that we need to use a script, which we'll write in Perl. Using Perl is not a requirement, you could use shell, AWK, or any other language, but since the Perl interpreter is installed as a part of the default OpenBSD configuration, there is little point to not use it.

Sendpflog

We are now ready to write the script that sends the logs to the firewall. For the sake of simplicity, we will try to make as little changes to the default setup as possible. The only intrusion will be one small change in /etc/newsyslog.conf and the addition of the sendpflog script. The following script will handle the rest of the work:

#!/usr/bin/perl -W 
# 
#                                   Copyright 2002 Jacek Artymiak 
#                                                License: XFree86 
#---------------------------------------------------------------- 
# section  1: open sendpflog.log -- the log used by sendpflog to 
#                                              store its messages 
 
open (LOG, ">> /var/log/sendpflog.log"); 
select (LOG); 
$|=1; 
 
#---------------------------------------------------------------- 
# section  2: define the logme function used to write messages to 
#                                                   sendpflog.log 
 
sub logme { 
 
$datetime = `date`; 
chop $datetime; 
 
$logentry = $datetime . ": sendpflog[$$]: $_[0]" . "\n"; 
 
print LOG $logentry; 
} 
 
#---------------------------------------------------------------- 
# section  3: define the loganddie function used to clean up 
#                                           before sendpflog dies 
 
sub loganddie { 
 
$datetime = `date`; 
chop $datetime; 
 
$logentry = $datetime . ": sendpflog[$$]: Fatal error: $_[0]" 
. ": Exiting ...\n"; 
 
print LOG $logentry; 
 
$logentry = $datetime 
. ": sendpflog[$$]: Closing pflog ...\n"; 
 
print LOG $logentry; 
 
close (INFILE); 
 
$logentry = $datetime 
. ": sendpflog[$$]: Closing output stream ...\n"; 
 
print LOG $logentry; 
 
close (OUTFILE); 
 
$logentry = $datetime 
. ": sendpflog[$$]: Removing sendpflog.pid ...\n"; 
 
print LOG $logentry; 
 
`rm /var/run/sendpflog.pid`; 
 
$logentry = $datetime 
. ": sendpflog[$$]: Exiting.\n"; 
 
print LOG $logentry; 
 
die ($logentry); 
} 
 
#---------------------------------------------------------------- 
# section  4: define the rotatelogs function, which closes 
#             /var/log/pflog and /var/log/sendpflog.log, 
#             sends SIGHUP to pflogd, and reopens /var/log/pflog 
#                                      and /var/log/sendpflog.log 
 
sub rotatelogs() { 
 
logme ("Closing rotated pflog."); 
 
close (INFILE); 
 
logme ("Closing sendpflog.log."); 
 
close (LOG); 
 
open (LOG, ">> /var/log/sendpflog.log"); 
select (LOG); 
$|=1; 
 
logme ("sendpflog.log rotated."); 
 
logme ("Sending SIGHUP to pflogd."); 
 
kill HUP => `cat /var/run/pflogd.pid`; 
 
logme ("Trying to open new pflog ..."); 
 
open (INFILE, "< /var/log/pflog") or 
loganddie( "Could not open pflog:" . $! . '.'); 
 
logme ("pflog opened."); 
} 
 
#---------------------------------------------------------------- 
# section  5: define the open_output function which connects to 
#             the monitoring station 
 
sub open_output { 
 
logme ("Trying to open output stream ..."); 
 
open (OUTFILE, 
'| ssh -q -2 -l username xxx.xxx.xxx.xxx "cat >> pflog"') 
or loganddie ("Could not open output stream: " . $! . '.'); 
 
sleep(5); 
select (OUTFILE); 
$|=1; 
 
logme ("Output stream opened successfully."); 
} 
 
#---------------------------------------------------------------- 
# section  6: set signal handlers 
 
$SIG{HUP}  = 'rotatelogs'; 
$SIG{INT}  = 'loganddie'; 
$SIG{QUIT} = 'loganddie'; 
$SIG{KILL} = 'loganddie'; 
$SIG{TERM} = 'loganddie'; 
$SIG{STOP} = 'loganddie'; 
$SIG{TSTP} = 'loganddie'; 
$SIG{PIPE} = 'IGNORE'; 
 
#---------------------------------------------------------------- 
# section  7: we're waking up 
 
logme ("Starting sendpflog ..."); 
 
#---------------------------------------------------------------- 
# section  8: write the current process ID (PID) to 
#                                          /var/run/sendpflog.pid 
 
logme ("Creating sendpflog.pid ..."); 
 
open (PIDFILE, "> /var/run/sendpflog.pid") or 
loganddie ("Unable to create sendpflog.pid: " . $! . '.'); 
 
logme ("Writing PID to sendpflog.pid ..."); 
 
syswrite PIDFILE, $$; 
 
logme ("Closing sendpflog.pid"); 
 
close PIDFILE; 
 
#---------------------------------------------------------------- 
# section  9: open /var/log/pflog for reading 
 
logme ("Trying to open pflog ..."); 
 
open (INFILE, "< /var/log/pflog") or 
loganddie ("Unable to open pflog: " . $! . '.'); 
 
logme ("pflog opened successfully."); 
 
#---------------------------------------------------------------- 
# section  10: read /var/log/pflogand send it to the monitoring 
#                                                         station 
 
open_output(); 
 
for (;;) { 
while (<INFILE>) { 
if (!(syswrite OUTFILE, $_)) { 
logme("The monitoring station is not responding"); 
close (OUTFILE); 
open_output(); 
} 
} 
 
sleep 1; 
seek (INFILE, 0, 1); 
}

Pages: 1, 2, 3

Next Pagearrow





Sponsored by: