#! @PERL@ -w # vim:syntax=perl use strict; use lib '@LR_PERL5LIBDIR@'; use Lire::Syslog; use Lire::DlfSchema; use Lire::Program qw/ :msg :dlf /; use Lire::Firewall qw/ firewall_number2names /; init_dlf_converter('firewall'); my $schema = eval { Lire::DlfSchema::load_schema( "firewall" ) }; lr_err( "failed to load firewall schema: $@" ) if $@; my $dlf_maker = $schema->make_hashref2asciidlf_func( qw/time rule action protocol from_ip from_port rcv_intf rcv_hwaddr to_ip to_port msg count/ ); my ($lines, $dlflines, $errorlines) = (0, 0, 0); my $parser = new Lire::Syslog(); while (<>) { lire_chomp(); $lines++; # Skip empty lines next if /^\s*$/; my $log = eval { $parser->parse( $_ ) }; if ( $@ ) { lr_warn( $@ ); lr_warn( "failed to parse line $. as a syslog line" ); $errorlines++; next; } # Skip entries missing a process next unless defined $log->{process}; # Apr 24 10:55:35 router 113613: 5d23h: %SEC-6-IPACCESSLOGP: list bigcompany # permitted tcp 10.2.108.1(0) -> 10.72.251.5(0), 80 packets # Apr 29 03:28:17 192.168.1.1 39724: 2w2d: %SEC-6-IPACCESSLOGP: list 102 # denied udp 192.168.1.169(13991) (Ethernet0 0004.ac38.4d3e) -> # 192.168.3.250(13991), 1 packet # Apr 29 03:30:17 192.168.1.1 39725: 2w2d: %SEC-6-IPACCESSLOGP: list 102 # denied udp 192.168.1.163(13991) (Ethernet0 ) -> 192.168.3.200(13991), 1 # packet # router 113613: 5d23h: %SEC-6-IPACCESSLOGP: list bigcompany permitted # tcp 10.2.108.1(0) -> 10.72.251.5(0), 80 packets # 192.168.1.1 39724: 2w2d: %SEC-6-IPACCESSLOGP: list 102 denied udp # 192.168.1.169(13991) (Ethernet0 0004.ac38.4d3e) -> 192.168.3.250(13991), # 1 packet # 192.168.1.1 39725: 2w2d: %SEC-6-IPACCESSLOGP: list 102 denied udp # 192.168.1.163(13991) (Ethernet0 ) -> 192.168.3.200(13991), 1 packet # %SEC-6-IPACCESSLOGP: list bigcompany permitted tcp 10.2.108.1(0) -> # 10.72.251.5(0), 80 packets # %SEC-6-IPACCESSLOGP: list 102 denied udp 192.168.1.169(13991) # (Ethernet0 0004.ac38.4d3e) -> 192.168.3.250(13991), 1 packet # %SEC-6-IPACCESSLOGP: list 102 denied udp 192.168.1.163(13991) # (Ethernet0 ) -> 192.168.3.200(13991), 1 packet my %dlf; if ( $log->{process} eq '%SEC-6-IPACCESSLOGP' ) { ( $dlf{'rule'}, $dlf{'action'}, $dlf{'protocol'}, $dlf{'from_ip'}, $dlf{'from_port'}, $dlf{'rcv_intf'}, $dlf{'rcv_hwaddr'}, $dlf{'to_ip'}, $dlf{'to_port'}, $dlf{'count'} ) = $log->{content} =~ m!^ list\s # list ([\w-]+)\s # access list name (\w+)\s # action (\w+)\s # protocol ([\d.]+) # Source address \((\d+)\) # Source port (?:\s\( # Optional ([^ \)]+)\s? # Receiving interface ([^\)]*) # MAC Address \))? \s->\s ([\d.]+) # Dest address \((\d+)\) # Dest port ,\s (\d+) # Number of packets \spackets? \s*$!x; unless (defined $dlf{'rule'} ) { $errorlines++; lr_warn( "failed to parse %SEC-6-IPACCESSLOGP record at line $." ); next; } } elsif ( $log->{process} eq '%SEC-6-IPACCESSLOGDP' ) { # %SEC-6-IPACCESSLOGDP: list bigcompany permitted icmp 10.2.108.1 -> # 10.68.187.5 (0/0), 2 packets # router 113614: 5d23h: %SEC-6-IPACCESSLOGDP: list bigcompany permitted # icmp 10.2.108.1 -> 10.68.187.5 (0/0), 2 packets # Apr 24 10:55:35 router 113614: 5d23h: %SEC-6-IPACCESSLOGDP: list bigcompany # permitted icmp 10.2.108.1 -> 10.68.187.5 (0/0), 2 packets ( $dlf{'rule'}, $dlf{'action'}, $dlf{'protocol'}, $dlf{'from_ip'}, $dlf{'rcv_intf'}, $dlf{'rcv_hwaddr'}, $dlf{'to_ip'}, $dlf{'from_port'}, $dlf{'to_port'}, $dlf{'count'} ) = $log->{content} =~ m!^ list\s # list ([\w-]+)\s # access list name (\w+)\s # action (\w+)\s # protocol ([\d.]+) # Source address (?:\s\( # Optional ([^ \)]+)\s? # Receiving interface ([^\)]*) # MAC Address \))? \s->\s ([\d.]+)\s # Dest address \((\d+)/(\d+)\) # ICMP Type/Code ,\s (\d+) # Number of packets \spackets? \s*$!x; unless (defined $dlf{'rule'} ) { $errorlines++; lr_warn( "failed to parse %SEC-6-IPACCESSLOGDP record at line $." ); next; } } elsif ( substr( $log->{process}, 0, 1) eq '%') { # Create msg record for 'unknown' Cisco messages # unless it's a PIX record next if $log->{process} =~ /^%PIX/; $dlf{'msg'} = $log->{process} . ": " . $log->{content}; } else { # Skip non Cisco messages next } $dlf{'time'} = $log->{timestamp}; my $dlf = eval { firewall_number2names( \%dlf ); $dlf_maker->( \%dlf ) }; if ( $@ ) { lr_warn( $@ ); lr_warn("cannot convert %dlf to dlf, skipping\n"); $errorlines++; next; } print join( " ", @$dlf ), "\n"; $dlflines++; } end_dlf_converter( $lines, $dlflines, $errorlines ); exit 0; __END__ =pod =head1 NAME cisco_ios2dlf - convert cisco logs to dlf format =head1 SYNOPSIS B =head1 DESCRIPTION This script expects syslog-type logs from a CISCO IOS router on stdin. These look like e.g. Jul 3 00:00:39 router 40108: 4d09h: %SEC-6-IPACCESSLOGP: list FR_VA_in permitted udp 192.168.19.1(137) (Serial0/0.2 DLCI 120) -> 192.168.19.255(137), 2 packets Jul 3 00:02:39 router 40109: 4d09h: %SEC-6-IPACCESSLOGP: list FR_VA_in permitted udp 192.168.80.42(138) (Serial0/0.2 DLCI 120) -> 192.60.60.148(138), 1 packet Jul 3 00:02:39 router 40110: 4d09h: %SEC-6-IPACCESSLOGDP: list FR_VA_in permitted icmp 192.168.80.82 (Serial0/0.2 DLCI 120) -> 149.1.1.1 (8/0), 1 packet or Aug 19 04:02:34 gateway.foo.bar 218963: Aug 19 04:02:32.977: %LINEPROTO-5-UPDOWN: Line protocol on Interface BRI0:1, changed state to down Aug 19 04:02:34 gateway.foo.bar 218964: Aug 19 04:02:33.262: %ISDN-6-DISCONNECT: Interface BRI0:1 disconnected from 172605440 acme, call lasted 42 seconds Aug 19 04:02:35 gateway.foo.bar 218965: Aug 19 04:02:33.266: %LINK-3-UPDOWN: Interface BRI0:1, changed state to down Aug 19 04:02:38 gateway.foo.bar 218966: Aug 19 04:02:36.103: %SEC-6-IPACCESSLOGP: list 102 denied tcp 100.198.139.148(4652) -> 100.193.176.49(80), 1 packet Aug 19 04:02:45 gateway.foo.bar 218967: Aug 19 04:02:43.543: %ISDN-6-LAYER2DOWN: Layer 2 for Interface BR0, TEI 86 changed to down Aug 19 04:02:53 gateway.foo.bar 218968: Aug 19 04:02:51.471: %SEC-6-IPACCESSLOGP: list 102 denied tcp 100.74.103.1(2162) -> 100.193.176.98(80), 1 packet The outputted dlf files look like: 994118619 permitted icmp 192.168.80.9 - Serial0/0.2 DLCI_120 192.168.19.1 - 1 994118619 permitted udp 192.168.19.1 138 Serial0/0.2 DLCI_120 192.168.19.255 138 1 =head1 EXAMPLES To process a log as produced by Cisco IOS: $ cisco_ios2dlf < cisco.log cisco_ios2dlf will be rarely used on its own, but is more likely called by lr_log2report: $ lr_log2report cisco_ios < /var/log/cisco.log =head1 AUTHORS Francis J. Lacoste based on initial code by Joost Bekkers =head1 VERSION $Id: cisco_ios2dlf.in,v 1.8 2006/07/23 13:16:35 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Joost Bekkers Copyright (C) 2002 Stichting LogReport Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut # Local Variables: # mode: cperl # End: