1#!perl.exe 2 3# Author: Chris Grant 4# Copyright 1999, Codetalker Communications, Inc. 5# 6# This script takes a firewall log and breaks it into several 7# different files. Each file is named based on the service that 8# runs on the port that was recognized in log line. After 9# this script has run, you should end up with several files. 10# Of course you will have the original log file and then files 11# such as web.log, telnet.log, pop3.log, imap.log, backorifice.log, 12# netbus.log, and unknown.log. 13# 14# The number of entries in unknown.log should be minimal. The 15# mappings of the port numbers and file names are stored in the bottom 16# of this file in the data section. Simply look at the ports being hit, 17# find out what these ports do, and add them to the data section. 18# 19# You may be wondering why I haven't simply parsed RFC1700 to come up 20# with a list of port numbers and files. The reason is that I don't 21# believe reading firewall logs should be all that automated. You 22# should be familiar with what probes are hitting your system. By 23# manually adding entries to the data section this ensures that I 24# have at least educated myself about what this protocol is, what 25# the potential exposure is, and why you might be seeing this traffic. 26 27%icmp = (); 28%udp = (); 29%tcp = (); 30%openfiles = (); 31$TIDBITSFILE = "unknown.log"; 32 33# Read the ports data from the end of this file and build the three hashes 34while (<DATA>) { 35 chomp; # trim the newline 36 s/#.*//; # no comments 37 s/^\s+//; # no leading white 38 s/\s+$//; # no trailing white 39 next unless length; # anything left? 40 $_ = lc; # switch to lowercase 41 ($proto, $identifier, $filename) = m/(\S+)\s+(\S+)\s+(\S+)/; 42 SWITCH: { 43 if ($proto =~ m/^icmp$/) { $icmp{$identifier} = $filename; last SWITCH; }; 44 if ($proto =~ m/^udp$/) { $udp{$identifier} = $filename; last SWITCH; }; 45 if ($proto =~ m/^tcp$/) { $tcp{$identifier} = $filename; last SWITCH; }; 46 die "An unknown protocol listed in the proto defs\n$_\n"; 47 } 48} 49 50$filename = shift; 51unless (defined($filename)) { die "Usage: logfilter.pl <log file>\n"; } 52open(LOGFILE, $filename) || die "Could not open the firewall log file.\n"; 53$openfiles{$filename} = "LOGFILE"; 54 55$linenum = 0; 56while($line = <LOGFILE>) { 57 58 chomp($line); 59 $linenum++; 60 61 # determine the protocol - send to unknown.log if not found 62 SWITCH: { 63 64 ($line =~ m /\sicmp\s/) && do { 65 66 # 67 # ICMP Protocol 68 # 69 # Extract the icmp packet information specifying the type. 70 # 71 # Note: Must check for ICMP first because this may be an ICMP reply 72 # to a TCP or UDP connection (eg Port Unreachable). 73 74 ($icmptype) = $line =~ m/icmp (\d+)\/\d+/; 75 76 $filename = $TIDBITSFILE; 77 $filename = $icmp{$icmptype} if (defined($icmp{$icmptype})); 78 79 last SWITCH; 80 }; 81 82 ($line =~ m /\stcp\s/) && do { 83 84 # 85 # TCP Protocol 86 # 87 # extract the source and destination ports and compare them to 88 # known ports in the tcp hash. For the first match, place this 89 # line in the file specified by the tcp hash. Ignore one of the 90 # port matches if both ports happen to be known services. 91 92 ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/; 93 #print "$line\n" unless (defined($sport) && defined($dport)); 94 95 $filename = $TIDBITSFILE; 96 $filename = $tcp{$sport} if (defined($tcp{$sport})); 97 $filename = $tcp{$dport} if (defined($tcp{$dport})); 98 99 last SWITCH; 100 }; 101 102 ($line =~ m /\sudp\s/) && do { 103 104 # 105 # UDP Protocol - same procedure as with TCP, different hash 106 # 107 108 ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/; 109 110 $filename = $TIDBITSFILE; 111 $filename = $udp{$sport} if (defined($udp{$sport})); 112 $filename = $udp{$dport} if (defined($udp{$dport})); 113 114 last SWITCH; 115 }; 116 117 # 118 # The default case is that the protocol was unknown 119 # 120 $filename = $TIDBITSFILE; 121 } 122 123 # 124 # write the line to the appropriate file as determined above 125 # 126 # check for filename in the openfiles hash. if it exists then write 127 # to the given handle. otherwise open a handle to the file and add 128 # it to the hash of open files. 129 130 if (defined($openfiles{$filename})) { 131 $handle = $openfiles{$filename}; 132 } else { 133 $handle = "HANDLE" . keys %openfiles; 134 open ($handle, ">>".$filename) || die "Couldn't open|create the file $filename"; 135 $openfiles{$filename} = $handle; 136 } 137 print $handle "#$linenum\t $line\n"; 138 139} 140 141# close all open file handles 142 143foreach $key (keys %openfiles) { 144 close($openfiles{$key}); 145} 146 147close(LOGFILE); 148 149__DATA__ 150icmp 3 destunreach.log 151icmp 8 ping.log 152icmp 9 router.log 153icmp 10 router.log 154icmp 11 ttl.log 155tcp 23 telnet.log 156tcp 25 smtp.log 157udp 25 smtp.log 158udp 53 dns.log 159tcp 80 http.log 160tcp 110 pop3.log 161tcp 111 rpc.log 162udp 111 rpc.log 163tcp 137 netbios.log 164udp 137 netbios.log 165tcp 143 imap.log 166udp 161 snmp.log 167udp 370 backweb.log 168udp 371 backweb.log 169tcp 443 https.log 170udp 443 https.log 171udp 512 syslog.log 172tcp 635 nfs.log # NFS mount services 173udp 635 nfs.log # NFS mount services 174tcp 1080 socks.log 175udp 1080 socks.log 176tcp 6112 games.log # Battle net 177tcp 6667 irc.log 178tcp 7070 realaudio.log 179tcp 8080 http.log 180tcp 12345 netbus.log 181udp 31337 backorifice.log 182