| #!perl.exe |
| |
| # Author: Chris Grant |
| # Copyright 1999, Codetalker Communications, Inc. |
| # |
| # This script takes a firewall log and breaks it into several |
| # different files. Each file is named based on the service that |
| # runs on the port that was recognized in log line. After |
| # this script has run, you should end up with several files. |
| # Of course you will have the original log file and then files |
| # such as web.log, telnet.log, pop3.log, imap.log, backorifice.log, |
| # netbus.log, and unknown.log. |
| # |
| # The number of entries in unknown.log should be minimal. The |
| # mappings of the port numbers and file names are stored in the bottom |
| # of this file in the data section. Simply look at the ports being hit, |
| # find out what these ports do, and add them to the data section. |
| # |
| # You may be wondering why I haven't simply parsed RFC1700 to come up |
| # with a list of port numbers and files. The reason is that I don't |
| # believe reading firewall logs should be all that automated. You |
| # should be familiar with what probes are hitting your system. By |
| # manually adding entries to the data section this ensures that I |
| # have at least educated myself about what this protocol is, what |
| # the potential exposure is, and why you might be seeing this traffic. |
| |
| %icmp = (); |
| %udp = (); |
| %tcp = (); |
| %openfiles = (); |
| $TIDBITSFILE = "unknown.log"; |
| |
| # Read the ports data from the end of this file and build the three hashes |
| while (<DATA>) { |
| chomp; # trim the newline |
| s/#.*//; # no comments |
| s/^\s+//; # no leading white |
| s/\s+$//; # no trailing white |
| next unless length; # anything left? |
| $_ = lc; # switch to lowercase |
| ($proto, $identifier, $filename) = m/(\S+)\s+(\S+)\s+(\S+)/; |
| SWITCH: { |
| if ($proto =~ m/^icmp$/) { $icmp{$identifier} = $filename; last SWITCH; }; |
| if ($proto =~ m/^udp$/) { $udp{$identifier} = $filename; last SWITCH; }; |
| if ($proto =~ m/^tcp$/) { $tcp{$identifier} = $filename; last SWITCH; }; |
| die "An unknown protocol listed in the proto defs\n$_\n"; |
| } |
| } |
| |
| $filename = shift; |
| unless (defined($filename)) { die "Usage: logfilter.pl <log file>\n"; } |
| open(LOGFILE, $filename) || die "Could not open the firewall log file.\n"; |
| $openfiles{$filename} = "LOGFILE"; |
| |
| $linenum = 0; |
| while($line = <LOGFILE>) { |
| |
| chomp($line); |
| $linenum++; |
| |
| # determine the protocol - send to unknown.log if not found |
| SWITCH: { |
| |
| ($line =~ m /\sicmp\s/) && do { |
| |
| # |
| # ICMP Protocol |
| # |
| # Extract the icmp packet information specifying the type. |
| # |
| # Note: Must check for ICMP first because this may be an ICMP reply |
| # to a TCP or UDP connection (eg Port Unreachable). |
| |
| ($icmptype) = $line =~ m/icmp (\d+)\/\d+/; |
| |
| $filename = $TIDBITSFILE; |
| $filename = $icmp{$icmptype} if (defined($icmp{$icmptype})); |
| |
| last SWITCH; |
| }; |
| |
| ($line =~ m /\stcp\s/) && do { |
| |
| # |
| # TCP Protocol |
| # |
| # extract the source and destination ports and compare them to |
| # known ports in the tcp hash. For the first match, place this |
| # line in the file specified by the tcp hash. Ignore one of the |
| # port matches if both ports happen to be known services. |
| |
| ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/; |
| #print "$line\n" unless (defined($sport) && defined($dport)); |
| |
| $filename = $TIDBITSFILE; |
| $filename = $tcp{$sport} if (defined($tcp{$sport})); |
| $filename = $tcp{$dport} if (defined($tcp{$dport})); |
| |
| last SWITCH; |
| }; |
| |
| ($line =~ m /\sudp\s/) && do { |
| |
| # |
| # UDP Protocol - same procedure as with TCP, different hash |
| # |
| |
| ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/; |
| |
| $filename = $TIDBITSFILE; |
| $filename = $udp{$sport} if (defined($udp{$sport})); |
| $filename = $udp{$dport} if (defined($udp{$dport})); |
| |
| last SWITCH; |
| }; |
| |
| # |
| # The default case is that the protocol was unknown |
| # |
| $filename = $TIDBITSFILE; |
| } |
| |
| # |
| # write the line to the appropriate file as determined above |
| # |
| # check for filename in the openfiles hash. if it exists then write |
| # to the given handle. otherwise open a handle to the file and add |
| # it to the hash of open files. |
| |
| if (defined($openfiles{$filename})) { |
| $handle = $openfiles{$filename}; |
| } else { |
| $handle = "HANDLE" . keys %openfiles; |
| open ($handle, ">>".$filename) || die "Couldn't open|create the file $filename"; |
| $openfiles{$filename} = $handle; |
| } |
| print $handle "#$linenum\t $line\n"; |
| |
| } |
| |
| # close all open file handles |
| |
| foreach $key (keys %openfiles) { |
| close($openfiles{$key}); |
| } |
| |
| close(LOGFILE); |
| |
| __DATA__ |
| icmp 3 destunreach.log |
| icmp 8 ping.log |
| icmp 9 router.log |
| icmp 10 router.log |
| icmp 11 ttl.log |
| tcp 23 telnet.log |
| tcp 25 smtp.log |
| udp 25 smtp.log |
| udp 53 dns.log |
| tcp 80 http.log |
| tcp 110 pop3.log |
| tcp 111 rpc.log |
| udp 111 rpc.log |
| tcp 137 netbios.log |
| udp 137 netbios.log |
| tcp 143 imap.log |
| udp 161 snmp.log |
| udp 370 backweb.log |
| udp 371 backweb.log |
| tcp 443 https.log |
| udp 443 https.log |
| udp 512 syslog.log |
| tcp 635 nfs.log # NFS mount services |
| udp 635 nfs.log # NFS mount services |
| tcp 1080 socks.log |
| udp 1080 socks.log |
| tcp 6112 games.log # Battle net |
| tcp 6667 irc.log |
| tcp 7070 realaudio.log |
| tcp 8080 http.log |
| tcp 12345 netbus.log |
| udp 31337 backorifice.log |