Analyzing ACL Log Entries

Analyzing ACL Log Entries

Problem

You want to analyze the log entries created by logging ACLs.

Solution

The Perl script in Example 19-1 parses a router syslog file and builds a detailed report of packets that were denied by logging ACLs. By default, the script will parse every ACL log message that it finds in the syslog file on a server. You can also look for messages associated with a particular ACL by specifying the ACL number or name as a command-line argument.

Example 19-1. logscan.pl

#!/usr/local/bin/perl
#
# logscan.pl -- a script to extract ACL logs from a syslog file.
#
# Set behavior
$log="/var/log/cisco.log";
$ntop=10;
#
chomp ($acl=$ARGV[0]);
if ($acl == "") { $acl=".*"};

open(LOG , "<$log") or die;
while () {
if (/IPACCESSLOGP: list $acl denied ([tcpud]+) ([0-9.]+)\(([0-9]+)\) -> ([0-9.]+)\(([0-9]+)\), ([0-9]+) /) {
$x=$6;
$srca{$2}+=$x;
$foo=sprintf("%16s -> %16s %3s port %-6s",$2,$4,$1,$5);
$moo=sprintf("%3s port %-6s",$1,$5);
$quad{$foo}+=$x;
$port{$moo}+=$x;
}
}
$n=0;
printf ("Connection Summary:\n");
foreach $i (sort { $quad{$b} <=> $quad{$a} } keys %quad) {
if ($n++ >= $ntop) { last };
printf ("%6s:%s\n", $quad{$i},$i);
}
$n=0;
printf ("\nDestination Port Summary:\n");
foreach $i ( sort { $port{$b} <=> $port{$a} } keys %port) {
if ($n++ >= $ntop) { last };
printf ("%6s: %s\n", $port{$i},$i);
}
$n=0;
printf ("\nSource Address Summary:\n");
foreach $i ( sort { $srca{$b} <=> $srca{$a} } keys %srca) {
if ($n++ >= $ntop) { last };
printf ("%6s: %s\n", $srca{$i},$i);
}

Note that we have had to split the line that begins "if (/IPACCESSLOGP: list" across two lines so that it will fit on the page. If you decide to use this script, please type it as a single line.


Discussion

It's a good idea configure your access-lists so that they log all of the packets that they deny. This is particularly true for security-related ACLs. You can then use these log messages for security or audit purposes. Unfortunately, this level of logging can create a large number of messages, which makes analysis difficult. This Perl script automates the most difficult part of this analysis by parsing through a large file of ACL log messages and building a report that can help to identify potential problems.

The report produced by the script has three sections that summarize connections, destination ports, and source IP addresses. The connection report displays the top 10 most common connection denied attempts, including the source address, destination source, and destination port number. The destination port summary displays the top 10 most frequently denied destination ports. And the source address summary displays the 10 hosts whose connection attempts were most frequently denied. In each case, the script looks at both TCP and UDP ports.

The following is a sample report:

Freebsd%./logscan.pl
Connection Summary:
195: 172.25.1.1 -> 172.20.100.1 tcp port 23
13: 172.25.1.1 -> 172.20.100.1 tcp port 22
8: 172.20.1.2 -> 172.25.1.3 udp port 53
6: 172.20.1.2 -> 172.25.1.1 udp port 123
6: 172.25.1.1 -> 10.2.2.2 tcp port 23
4: 172.20.1.2 -> 172.25.1.1 udp port 162
4: 172.25.1.1 -> 172.20.100.1 tcp port 21
4: 172.20.1.2 -> 172.25.1.1 udp port 53
3: 172.25.1.1 -> 172.20.100.1 tcp port 80
2: 172.20.1.2 -> 172.25.1.3 udp port 123

Destination Port Summary:
206: tcp port 23
14: tcp port 22
12: udp port 53
8: udp port 123
4: tcp port 80
4: udp port 162
4: tcp port 21
2: tcp port 443
1: tcp port 6000
1: tcp port 79

Source Address Summary:
222: 172.25.1.1
24: 172.20.1.2
3: 172.25.1.6
1: 192.168.4.217
1: 172.25.1.9
1: 10.2.3.134
1: 172.25.1.4
1: 172.22.1.9
1: 10.23.55.121
1: 172.25.1.3
Freebsd%

This report should help to identify troubling behavior that warrants further investigation. For instance, you will notice that address 172.25.1.1 has attempted to Telnet to 172.20.100.1 195 times. This may not have been evident by scanning the log file by hand.

The script can also build a report based on the messages from a particular ACL number or name:

Freebsd%./logscan.pl 122
Connection Summary:
2: 172.25.1.6 -> 10.2.2.2 tcp port 443
1: 192.168.4.217 -> 10.2.2.2 tcp port 23
1: 172.22.1.9 -> 10.2.2.2 tcp port 6000
1: 10.2.3.134 -> 10.2.2.2 tcp port 23
1: 172.25.1.9 -> 10.2.2.2 tcp port 23
1: 10.23.55.121 -> 10.2.2.2 tcp port 79
1: 172.25.1.1 -> 10.2.2.2 tcp port 22
1: 172.25.1.6 -> 10.2.2.2 tcp port 23

Destination Port Summary:
4: tcp port 23
2: tcp port 443
1: tcp port 22
1: tcp port 6000
1: tcp port 79

Source Address Summary:
3: 172.25.1.6
1: 10.2.3.134
1: 172.22.1.9
1: 192.168.4.217
1: 172.25.1.1
1: 172.25.1.9
1: 10.23.55.121
Freebsd%

Before you can use this script you must modify the variable $log. This variable must contain the full directory and filename of the syslog file that you wish to scan. The script is then ready to launch. The only other variable you may want to modify is the $ntop variable. This variable defines how long each section of the report will be. By default, the script is set to display the top 10 matches in each category. However, you can set this number to any number you prefer. Also note that, as you can see in the above example, if there are fewer than $ntop matches in any category, the script will show only the matches that it actually finds.

For more information on logging and remote logging to a Syslog server, please see Chapter 18.

See Also