153024Sguido#!perl.exe
253024Sguido
353024Sguido# Author: Chris Grant
453024Sguido# Copyright 1999, Codetalker Communications, Inc.
553024Sguido#
653024Sguido# This script takes a firewall log and breaks it into several
753024Sguido# different files. Each file is named based on the service that
853024Sguido# runs on the port that was recognized in log line. After
953024Sguido# this script has run, you should end up with several files.
1053024Sguido# Of course you will have the original log file and then files
1153024Sguido# such as web.log, telnet.log, pop3.log, imap.log, backorifice.log,
1253024Sguido# netbus.log, and unknown.log.
1353024Sguido#
1453024Sguido# The number of entries in unknown.log should be minimal. The
1553024Sguido# mappings of the port numbers and file names are stored in the bottom
1653024Sguido# of this file in the data section. Simply look at the ports being hit,
1753024Sguido# find out what these ports do, and add them to the data section.
1853024Sguido#
1953024Sguido# You may be wondering why I haven't simply parsed RFC1700 to come up
2053024Sguido# with a list of port numbers and files. The reason is that I don't
2153024Sguido# believe reading firewall logs should be all that automated. You
2253024Sguido# should be familiar with what probes are hitting your system. By
2353024Sguido# manually adding entries to the data section this ensures that I
2453024Sguido# have at least educated myself about what this protocol is, what
2553024Sguido# the potential exposure is, and why you might be seeing this traffic.
2653024Sguido
2753024Sguido%icmp = ();
2853024Sguido%udp = ();
2953024Sguido%tcp = ();
3053024Sguido%openfiles = ();
3153024Sguido$TIDBITSFILE = "unknown.log";
3253024Sguido
3353024Sguido# Read the ports data from the end of this file and build the three hashes
3453024Sguidowhile (<DATA>) {
3553024Sguido    chomp;                                # trim the newline
3653024Sguido    s/#.*//;                              # no comments
3753024Sguido    s/^\s+//;                             # no leading white
3853024Sguido    s/\s+$//;                             # no trailing white
3953024Sguido    next unless length;                   # anything left?
4053024Sguido    $_ = lc;                              # switch to lowercase
4153024Sguido    ($proto, $identifier, $filename) = m/(\S+)\s+(\S+)\s+(\S+)/;
4253024Sguido    SWITCH: {
4353024Sguido	if ($proto =~ m/^icmp$/) { $icmp{$identifier} = $filename; last SWITCH; };
4453024Sguido	if ($proto =~ m/^udp$/) { $udp{$identifier} = $filename; last SWITCH; };
4553024Sguido        if ($proto =~ m/^tcp$/) { $tcp{$identifier} = $filename; last SWITCH; };
4653024Sguido	die "An unknown protocol listed in the proto defs\n$_\n";
4753024Sguido    }
4853024Sguido}
4953024Sguido
5053024Sguido$filename = shift;
5153024Sguidounless (defined($filename)) { die "Usage: logfilter.pl <log file>\n"; }
5253024Sguidoopen(LOGFILE, $filename) || die "Could not open the firewall log file.\n";
5353024Sguido$openfiles{$filename} = "LOGFILE";
5453024Sguido
5553024Sguido$linenum = 0;
5653024Sguidowhile($line = <LOGFILE>) {
5753024Sguido
5853024Sguido    chomp($line);
5953024Sguido    $linenum++;
6053024Sguido
6153024Sguido    # determine the protocol - send to unknown.log if not found
6253024Sguido    SWITCH: {
6353024Sguido
6453024Sguido	($line =~ m /\sicmp\s/) && do {
6553024Sguido
6653024Sguido	    #
6753024Sguido	    # ICMP Protocol
6853024Sguido	    #
6953024Sguido	    # Extract the icmp packet information specifying the type.
7053024Sguido	    #
7153024Sguido	    # Note: Must check for ICMP first because this may be an ICMP reply
7253024Sguido	    #       to a TCP or UDP connection (eg Port Unreachable).
7353024Sguido
7453024Sguido	    ($icmptype) = $line =~ m/icmp (\d+)\/\d+/;
7553024Sguido
7653024Sguido	    $filename = $TIDBITSFILE;
7753024Sguido	    $filename = $icmp{$icmptype} if (defined($icmp{$icmptype}));
7853024Sguido
7953024Sguido	    last SWITCH;
8053024Sguido	  };
8153024Sguido
8253024Sguido	($line =~ m /\stcp\s/) && do {
8353024Sguido
8453024Sguido	    #
8553024Sguido	    # TCP Protocol
8653024Sguido	    #
8753024Sguido	    # extract the source and destination ports and compare them to
8853024Sguido	    # known ports in the tcp hash. For the first match, place this
8953024Sguido	    # line in the file specified by the tcp hash. Ignore one of the
9053024Sguido	    # port matches if both ports happen to be known services.
9153024Sguido
9253024Sguido	    ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/;
9353024Sguido	    #print "$line\n" unless (defined($sport) && defined($dport));
9453024Sguido
9553024Sguido	    $filename = $TIDBITSFILE;
9653024Sguido	    $filename = $tcp{$sport} if (defined($tcp{$sport}));
9753024Sguido	    $filename = $tcp{$dport} if (defined($tcp{$dport}));
9853024Sguido
9953024Sguido	    last SWITCH;
10053024Sguido	  };
10153024Sguido
10253024Sguido	($line =~ m /\sudp\s/) && do {
10353024Sguido
10453024Sguido	    #
10553024Sguido	    # UDP Protocol - same procedure as with TCP, different hash
10653024Sguido	    #
10753024Sguido
10853024Sguido	    ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/;
10953024Sguido
11053024Sguido	    $filename = $TIDBITSFILE;
11153024Sguido	    $filename = $udp{$sport} if (defined($udp{$sport}));
11253024Sguido	    $filename = $udp{$dport} if (defined($udp{$dport}));
11353024Sguido
11453024Sguido	    last SWITCH;
11553024Sguido	  };
11653024Sguido
11753024Sguido	#
11853024Sguido	# The default case is that the protocol was unknown
11953024Sguido	#
12053024Sguido	$filename = $TIDBITSFILE;
12153024Sguido    }
12253024Sguido
12353024Sguido    #
12453024Sguido    # write the line to the appropriate file as determined above
12553024Sguido    #
12653024Sguido    # check for filename in the openfiles hash. if it exists then write
12753024Sguido    # to the given handle. otherwise open a handle to the file and add
12853024Sguido    # it to the hash of open files.
12953024Sguido
13053024Sguido    if (defined($openfiles{$filename})) {
13153024Sguido	$handle = $openfiles{$filename};
13253024Sguido    } else {
13353024Sguido	$handle = "HANDLE" . keys %openfiles;
13453024Sguido	open ($handle, ">>".$filename) || die "Couldn't open|create the file $filename";
13553024Sguido	$openfiles{$filename} = $handle;
13653024Sguido    }
13753024Sguido    print $handle "#$linenum\t $line\n";
13853024Sguido
13953024Sguido}
14053024Sguido
14153024Sguido# close all open file handles
14253024Sguido
14353024Sguidoforeach $key (keys %openfiles) {
14453024Sguido    close($openfiles{$key});
14553024Sguido}
14653024Sguido
14753024Sguidoclose(LOGFILE);
14853024Sguido
14953024Sguido__DATA__
15053024Sguidoicmp    3         destunreach.log
15153024Sguidoicmp    8         ping.log
15253024Sguidoicmp    9         router.log
15353024Sguidoicmp    10        router.log
15453024Sguidoicmp    11        ttl.log
15553024Sguidotcp     23        telnet.log
15653024Sguidotcp     25        smtp.log
15753024Sguidoudp     25        smtp.log
15853024Sguidoudp     53        dns.log
15953024Sguidotcp     80        http.log
16053024Sguidotcp     110       pop3.log
16153024Sguidotcp     111       rpc.log
16253024Sguidoudp     111       rpc.log
16353024Sguidotcp     137       netbios.log
16453024Sguidoudp     137       netbios.log
16553024Sguidotcp     143       imap.log
16653024Sguidoudp     161       snmp.log
16753024Sguidoudp     370       backweb.log
16853024Sguidoudp     371       backweb.log
16953024Sguidotcp     443       https.log
17053024Sguidoudp     443       https.log
17153024Sguidoudp     512       syslog.log
17253024Sguidotcp     635       nfs.log           # NFS mount services
17353024Sguidoudp     635       nfs.log           # NFS mount services
17453024Sguidotcp     1080      socks.log
17553024Sguidoudp     1080      socks.log
17653024Sguidotcp     6112      games.log         # Battle net
17753024Sguidotcp     6667      irc.log
17853024Sguidotcp     7070      realaudio.log
17953024Sguidotcp     8080      http.log
18053024Sguidotcp     12345     netbus.log
181153877Sguidoudp     31337     backorifice.log