Tool to read/parse Cisco Pix/FWSM Config into excel

Is there a tool that will sort out the running config on the firewall module with the return of the show access-list to correlate hit counters?

See below, rule/line 578 is associated with acl 65, rule/line 633 is associated with acl 47

Some rules that use objects actually have many acls but they all have the same acl number.

How can I correlate this data easily?

line: 578 access-list acl_ppc_inside_access extended deny udp any any eq 222
line: 633 access-list acl_ppc_outside_access extended deny udp any any eq 222

access-list acl_ppc_inside_access line 65 extended deny udp any any eq 222 (hitcnt=3) 0x901d0980
access-list acl_ppc_outside_access line 47 extended deny udp any any eq 222 (hitcnt=0) 0x944c193a  
LVL 6
DooglaveAsked:
Who is Participating?
 
Jody LemoineConnect With a Mentor Network ArchitectCommented:
You're not going to be able to do this easily *within* the PIX/ASA, but if you capture the running configuration and the output of the "show access-lists" command into text files, you can do it with standard Unix/Linux utilities.

One thing to clarify with your scenario is this: In the example you give above, line 578 isn't associated with ACL 65, but with element 65 of ACL acl_ppc_inside_access.  Similarly, line 633 isn't associated with ACL 47, but with element 47 of ACL acl_ppc_outside_access.  This makes a difference because you are likely to have dissimilar ACLs with the same element numbers and if you don't take the ACL names into account, you're going to have unrelated rules bundled together.

Once you have the output of "show access-lists" in a text file, you can go through the list and search it against the running configuration.  A nested grep or small perl script would do the job nicely.  The first part is to do a line-numbered search of the running-configuration for occurrences of the "access-list " followed by the ACL name.  A second search of this output for the portion of the "show access-lists" output following the element number and terminating before " (hitcount" will give you the configuration line that is associated with the element.

So, if you throw the output of a "show running-config" into /tmp/1 and the output from a "show access-lists" into /tmp/2, you would do the following:

$ cat /tmp/2
access-list acl_ppc_inside_access line 65 extended deny udp any any eq 222 (hitcnt=3) 0x901d0980
access-list acl_ppc_outside_access line 47 extended deny udp any any eq 222 (hitcnt=0) 0x944c193a  
$ grep -n acl_ppc_inside_access /tmp/1 | grep 'extended deny udp any any eq 222'
578:access-list acl_ppc_inside_access extended deny udp any any eq 222
$ grep -n acl_ppc_inside_access /tmp/1 | grep 'extended deny udp any any eq 222' | awk -F: '{print $1;}'
578

Obviously, you'll want to automate that to do a line-by line search and correlate the hit counts with the line numbers, but that's a beginning.

Sorry I don't have anything pre-built to offer.
0
 
Steve JenningsConnect With a Mentor IT ManagerCommented:
If you are comfortable with PERL, here's a start for you . . .

Good luck,
SteveJ
#!/usr/bin/perl 

$DEBUG =0;


#--------------- Subroutines ----------------

#--------- Reads in the config via an array and returns an array of hashes for all interfaces
sub findint (@) {
print "\nSubroutine findint started\n" if $DEBUG;
my @cfg = @_;
my @interfaces = ();
my $line = "";
my $intnum = 0;
my $intinfo = {};
foreach $line (@cfg) {
	chomp $line;
	print "Line is $line\n" if $DEBUG;
	if ($line =~ m/^(interface)\s*(\S*)(.*)$/) {
		push @interfaces, $intinfo;
		$intinfo = {};
		$intinfo->{'intname'} = $2;
		}
	if ($line =~ m/^(\s*ip address )(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(.*)$/) {
		push @{$$intinfo{'ipaddress'}}, $2;
		push @{$$intinfo{'subnetmask'}}, $3;
 
		}
	if ($line =~ m/^(\s*description)\s*(.*)$/) {
		$intinfo->{'description'} = $2;
		}
	if ($line =~ m/^(\s*encapsulation\s*)(.*)$/) {
		if ($2 =~ m/.*frame-relay.*/) {
			$intinfo->{'encapsulation'} = "Frame-Relay"; }
		}
}
push @interfaces, $intinfo;

print "\nSubroutine findint executed\n" if $DEBUG;
shift @interfaces;
return @interfaces;
}

#--------- Reads in the config via an array and returns a scaler with hostname
sub findhostname (@) {
print "Subroutine findhostname started\n" if $DEBUG;
my @cfg = @_;
my $hostname = "";
my $line = "";

foreach $line (@cfg) {
chomp $line;
print "The line is: ", $line, "\n" if $DEBUG;
if ($line =~ m/^(hostname)\s(.*)$/) {
	$hostname = $2;
	print "Hostname is: ", $hostname, "\n" if $DEBUG;
	return $hostname;
}
}
print "Subroutine findhostname did not find hostname\n" if $DEBUG;
return 0;
}

#--------- Reads in the config via an array and returns a hash with con, aux, vty and enable passwords
sub findpasswd (@) {
print "\nSubroutine findpasswd started\n" if $DEBUG;
my @cfg = @_;
my %passwords = (
	vty => "",
	con => "",
	aux => "",
	enable => ""
);
my $line = "";
my $store = "";

foreach $line (@cfg) {
chomp $line;
print "The line is $line\n" if $DEBUG;

if ($line =~ m/^(enable\s\S*\s)(\d?)\s?(.*)$/) {
	if ($2 == "7") {$passwords{enable} = decrypt ($3);}
	else {
	$passwords{enable} = $3;}
	print "enablepass is $passwords{enable}\n" if $DEBUG;
}
if ($line =~ m/^(\s*snmp-server\s*community\s*)(\S*\s*R[OW]).*$/) {
	$passwords{'snmp'} = $2;
	}
if ($line =~ m/^(line con .*)$/) {
	$store = "con";
}
if ($line =~ m/^(line aux .*)$/) {
	$store = "aux";
}
if ($line =~ m/^(line vty .*)$/) {
        $store = "vty";
}

if ($line =~ m/^(\s*password\s)(\d?)\s?(.*)$/) {
	if ($2 == "7") {$passwords{$store} = decrypt ($3);}
	else {
	$passwords{$store} = $3;}
	$store = "";
	print "Password is  $passwords{$store}\n" if $DEBUG;
}

}
print "Subroutine findpasswd executed\n" if $DEBUG;
return %passwords;
}


#---- This subroutiene decrypts Cisco Level 7 passwords
sub decrypt ($) {
my $s = "";
my $e = "";
my $ep = "";
my $i = "";
my @xlat = ( 0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41,
          0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c,
          0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53 , 0x55, 0x42 );
my $passstring = @_[0];
        $ep = $passstring; $dp = "";
        ($s, $e) = ($passstring =~ /^(..)(.+)/o);
        for ($i = 0; $i < length($e); $i+=2) {
                $dp .= sprintf "%c",hex(substr($e,$i,2))^$xlat[$s++];
                }
	print "The Encrypted String is $ep\nThe Decrypted String is $dp\n" if $DEBUG;
        return $dp;
}

#---- This subroutiene finds and stores access-lists in a hash of arrays
sub findaccesslist (@) {
my @cfg = @_;
my $line = "";
my %accesslists;
foreach $line (@cfg) {
	chomp $line;
	if ($line =~ m/^(\s*access-list\s*)(\d{1,5}).*$/) {
	print "$line\n" if $DEBUG;
	print "$2\n" if $DEBUG;
	print "The keys are ", (keys %accesslists), "\n" if $DEBUG;
	push @{$accesslists{$2}}, $line;
	}
}
return %accesslists;
}

#---- This subroutiene finds and stores the routing protocal information
sub findrouting (@) {
my @cfg = @_;
my $line = "";
my @protos;
foreach $line (@cfg) {
 chomp $line;
 if ($line =~ m/^\s*(router)\s(eigrp)\s(\d*).*$/) {
	print "$line\n" if $DEBUG;
	push @protos, "IP-EIGRP";
	}
 if ($line =~ m/^\s*(router)\s(ospf)\s(\d*).*$/) {
	print "$line\n" if $DEBUG;
	push @protos, "IP-OSPF";
	}
 if ($line =~ m/^\s*(router)\s(rip).*$/) {
	print "$line\n" if $DEBUG;
	push @protos, "IP-RIP";
	}
 if ($line =~ m/^\s*(router)\s(igrp)\s(\d*).*$/) {
	print "$line\n" if $DEBUG;
	push @protos, "IP-IGRP";
	}
 if ($line =~ m/^\s*(router)\s(bgp)\s(\d*).*$/) {
	print "$line\n" if $DEBUG;
	push @protos, "IP-BGP";
	}


}
return @protos;
}


#---- This subroutiene finds and stores the static routes
sub findstatic (@) {
my @cfg = @_;
my $line = "";
my @routes;
foreach $line (@cfg) {
 chomp $line;
 if ($line =~ m/^\s*(ip\s+route\s+.*)$/) {
	print "$line\n" if $DEBUG;
	push @routes, $1;
	}

}
return @routes;
}


#--------------- Main Program ---------------
die "Usage: $0 configfile\n" unless (@ARGV);

$configfile = $ARGV[0];

open(CFG_FILE, $configfile) or die "Can not open file, $!";
while (<CFG_FILE>) {
push @org_config, $_;
}
close (CFG_FILE) or die "Can not close file correctly";


print "Dump of $configfile\n\n", @org_config, "\n" if $DEBUG;

$hostname = findhostname (@org_config);
print "Device,$hostname,";

%password = findpasswd (@org_config);
print "$password{con},";
print "$password{vty},";
print "$password{aux},";
print "$password{enable},";
print "$password{snmp}\n";

@interfaces = findint (@org_config);
foreach $int (@interfaces) {
print "Interface,$$int{'intname'},";
print "$$int{'encapsulation'}\n";
#print "Description is $$int{'description'}\n";
if (@{$$int{'ipaddress'}}) {
foreach $n (0..(@{$$int{'ipaddress'}} - 1)) {
	print "IP,${$$int{'ipaddress'}}[$n],";
	print "${$$int{'subnetmask'}}[$n]\n";
}
}

}

%acl = findaccesslist (@org_config);
foreach $key (keys %acl) {
	print "Access List,$key,";
	foreach $aclline (@{$acl{$key}}) {
	print "$aclline~";}
print "\n";
}

@routingproto = findrouting (@org_config);
foreach $proto (@routingproto) {
print "Routing Protocol,$proto\n";
}

@staticroutes = findstatic (@org_config);
if (@staticroutes) {
print "Routing Protocol,IP-STATIC,";
foreach $sroute (@staticroutes) {
	print "$sroute~";}
print "\n";
}


#------------End Main Program--------------------

Open in new window

0
 
DooglaveAuthor Commented:
Awesome, this is going to take me a long time to figure out and learn. I know VBA but that's about it at this point.
0
 
gavvingCommented:
FireGen is a syslog analyzer for PIX firewalls.  Maybe it will provide the data you need?

http://www.eventid.net/firegen/firegenpix2.asp

0
 
Steve JenningsIT ManagerCommented:
Wish I'd written it . . . I hacked it up some to run against Cisco switch configs. You'll need to make a couple of fairly simple changes to some search strings and string formating to produce a comma delmited output file for the ACLs.

Good luck,
SteveJ
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.