BSD DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Subscribe to BSD Subscribe to Newsletters

Securing Small Networks with OpenBSD Managing Advanced PF Logs

by Jacek Artymiak
08/22/2002

Welcome back.

In part 6 and part 7 we learned how to send logs over an ssh connection and how to make that connection more secure. We also did some math to find out how much storage space we'll need to keep old logs for analysis. Today we need to roll up our sleeves again, and do some coding in Perl, because the pflog fifo pipe created on the monitoring station's hard disk in part 6 is a bit like an oil well, gushing with black stuff that needs some additional piping to turn it into an orderly flow.

Catching and taming that wild stream of data is the job of the readpflog script. Written in Perl, it runs in the background and does three basic things: 1) reads pf logs from the pflog fifo pipe, 2) archives logs on the monitoring firewall, and 3) sends them to another fifo pipe so that log analysis software can pick them up for analysis.

#!/usr/bin/perl -W
#
#                                   Copyright 2002 Jacek Artymiak
#                                                License: XFree86
#----------------------------------------------------------------
# section  1: basic setup  

use Fcntl;
use POSIX qw(:errno_h);

$rdelay = 3600;  # log archiving delay (in seconds, 0 turns off); 

#----------------------------------------------------------------
# section  2: check if readpflog.pid exists

if (-e "/home/scooter/readpflog.pid") {

    print "Looks like readpflog is already running, if it is " . 
               "not running, delete /home/scooter/readpflog.pid";
    exit;
}

#----------------------------------------------------------------
# section  3: open readpflog.log --  the log used by readpflog to 
#                                              store its messages

open (LOG, ">> /home/scooter/readpflog.log"); 
select (LOG);
$|=1;

#----------------------------------------------------------------
# section  4: define the logme function used to write messages to 
#                                                   readpflog.log

sub logme {

 $datetime = `date`;
 chop $datetime;

 $logentry = $datetime . ": readpflog[$$]: $_[0]" . "\n";

 print LOG $logentry;
}

#----------------------------------------------------------------
# section  5: define the loganddie function used to clean up 
#                                           before readpflog dies 
 
sub loganddie {

 $datetime = `date`;
 chop $datetime;

 $logentry = $datetime
                      . ": readpflog[$$]: Fatal error: $_[0]" 
        . ": Exiting ...\n";

 print LOG $logentry;

 $logentry = $datetime 
                      . ": readpflog[$$]: Closing pflog ...\n";

 print LOG $logentry;

 close (INFILE);

 $logentry = $datetime 
              . ": readpflog[$$]: Closing pflog-current ...\n";

 print LOG $logentry;

 close (OUTFILE);

 $logentry = $datetime 
              . ": readpflog[$$]: Removing readpflog.pid ...\n";

 print LOG $logentry;

 `rm ~/readpflog.pid`;

 $logentry = $datetime 
              . ": readpflog[$$]: Exiting.\n";

 print LOG $logentry;

 die ($logentry);
}

#----------------------------------------------------------------
# section  6: define the rotatelogs function, which closes and
#                                         reopens ~/readpflog.log
 
sub rotatelogs() {

 logme ("Closing readpflog.log.");

 close (LOG);

 open (LOG, ">> /home/scooter/readpflog.log");
 select (LOG);
 $|=1;

 logme ("readpflog.log rotated.");
}

#----------------------------------------------------------------
# section  7: we're waking up 

logme ("Starting readpflog ...");

#----------------------------------------------------------------
# section  8: write the current process ID (PID) to 
#                                                 ~/readpflog.pid

logme ("Creating readpflog.pid ...");

open (PIDFILE, "> /home/scooter/readpflog.pid") or 
       loganddie ("Unable to create readpflog.pid: " . $! . '.');

logme ("Writing PID to readpflog.pid ...");

syswrite PIDFILE, $$;

logme ("Closing readpflog.pid");

close PIDFILE;

#----------------------------------------------------------------
# section  9: open ~/pflog for reading

sub opensource {

    logme ("Trying to open pflog ...");

    open (INFILE, "< /home/scooter/pflog") or 
                 loganddie ("Unable to open pflog: " . $! . '.');

    logme ("pflog opened successfully.");

    select (INFILE);
    $|=1;
}

#----------------------------------------------------------------
# section 10: open ~/pflog-current for writing

sub opentarget {

    logme ("Trying to open pflog-current ...");

    open (OUTFILE, ">> /home/scooter/pflog-current") or 
         loganddie ("Unable to open pflog-current: " . $! . '.');

    logme ("pflog-current opened successfully.");

    select (OUTFILE);
    $|=1;

    alarm $rdelay;
}

#----------------------------------------------------------------
# section 11: rotate ~/pflog-* archive

sub rotatetarget {

    close (OUTFILE);

    $d_t = `date "+%Y-%m-%d-%H-%M-%S"`; 

    unless (fork) {
        system ("mv /home/scooter/pflog-current /home/scooter/pflog-" . $d_t);
        system ("gzip -9 /home/scooter/pflog-" . $d_t);
        exit;
    }

    opentarget();
}

#----------------------------------------------------------------
# section  12: opens ~/pflog-pipe fifo pipe for writing 
#

sub openpipe {

    sysopen(LPIPE, "/home/scooter/pflog-pipe", O_NONBLOCK|O_RDWR)
                                  or die "Can't open pipe: $!\n";

    select (LPIPE);
    $|=1;
}

#----------------------------------------------------------------
# section  13: 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';
$SIG{ALRM} = 'rotatetarget';

#----------------------------------------------------------------
# section  14: open input and output files

opensource();
opentarget();
openpipe();

#----------------------------------------------------------------
# section  15: read ~/pflog, write it to ~/pflog-current, and 
#                                                    ~/pflog-pipe

for (;;) {

    while (<INFILE>) {

        if (length ($_) != 0) {

            $buf = $_;

            if (!(syswrite OUTFILE, $buf)) {

                close (OUTFILE);
                opentarget();
            }

            if (!(syswrite LPIPE, $buf)) {

               close (LPIPE);
               openpipe();
            }
        }

    }

    sleep 1;
    seek (INFILE, 0, 1);
}

Pages: 1, 2

Next Pagearrow




Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com