Posts Tagged ‘syslog’

Juniper firewall syslog parser – Part 1

September 5th, 2009

I was recently tasked with the job of locking down the rules on a new Juniper SSG firewall installation. Rather than just jumping in with a series of educated guesses followed by a ‘deny all’ rule, and potentially breaking chunks of the network. My preference is to implement a list of rules based on educated guesses followed by an ‘allow all’ rule that logs anything that hits it. Periodically throughout the next Days/Weeks/Months (circumstances dependent) the syslogs are evaluated and rules are added above the ‘allow all’ rule as necessary. Eventually, no legitimate traffic will be hitting the ‘allow all’ rule. At this time you can safely convert the ‘allow all’ to a ‘deny all’.

Note: Before I get flamed. I am referring to outbound traffic only and not to traffic coming from the internet or from any DMZ. Traffic coming from non-trusted sources should be restricted as much as possible at all times.

Sounds great in theory right? But anyone that has ever looked over firewall syslogs realises the sheer quantity of information is completely overwhelming and would take a team of very dedicated (and boring) individuals to retrieve the relevant information by hand. Software products exist to do this sort of work, but I saw an opportunity to further hone my coding ability. Perl is my weapon of choice for this script as it has fantastic Regex capabilities that can be used to pull out all the required information. From here we will dump it all into a database where it can be manipulated at will.

The primary focus when starting this project was getting the Regular Expressions (Regex) correctly functioning. The original plan was to create one Regex that could do all the work for me… but as you can see in a second, this created an unwieldy beast. The Regex below was my first attempt (and it wasn’t even complete).

1
m/^.+?\=(.+?)\sproto\=(\d+?).+?\=(.+?)\s.+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?).+?\=(\d+?)/;

Breaking this up into manageable chunks seemed like a much smarter way of going about it. The next code revision, while taking up more lines, takes on a much nicer to read form. The code below simply grabs the info and prints it to the screen. This is my debugging measure to ensure that everything is working correctly before moving onto the next phase. Database..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/perl
use strict;
use warnings;

open(SYSLOG,"20090903-syslog");

foreach my $line (<SYSLOG>)
{
chomp($line);

# Sep  3 15:05:23 172.16.1.250 FW: NetScreen device_id=FW  [Root]system-notification-00257(traffic): start_time="2009-09-03 15:11:58" duration=60
$line =~ m/((.+?\s+?){3})(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+?([A-Z]+?):.+?"(.+?)".+?\=(\d+?)\s(.*)/;    #Grab Device Name, Start Time and Duration
print "Date: $1\tDevice Name: $3 $4\tStart_Time: $5\tDuration: $6\t\n";

if ($7)        # Ensures valid syslog entry.
{
$line = $7;

# policy_id=1 service=Network Time proto=17 src zone=Trust dst zone=Untrust
$line =~ m/^.+?\=(\d+?).+?\=(.+?)\sproto\=(\d+?)\s.+?\=(.+?)\s.+?\=(.+?)\s(.*)/;    # Grabs PolicyID, Service, Protocol, Src_Zone and Dst_Zone.
print "\nPolicy_ID: $1\tService: $2\tProto: $3\tSrc_Zone: $4\t\tDst_Zone: $5\n";
$line = $6;

#action=Permit sent=98 rcvd=94 src=172.16.1.2 dst=200.200.200.200 src_port=123 dst_port=123
$line =~ m/^.+?\=(.+?)\s.+?\=(\d+?)\s.+?\=(\d+?)\s.+?\=(\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})\s.+?\=(\d+?)\s.+?\=(\d+?)\s(.*)/; # Grabs Action, Sent, Rcvd, Src, Dst, Src_port and Dst_port
print "Action: $1\tSent: $2\tRcvd: $3\tSrc: $4\tDest: $5\tSrc_Port: $6\tDst_port: $7\n";
$line = $8;

#src-xlated ip=200.200.200.200 port=16221 dst-xlated ip=200.200.200.200 port=123 session_id=47889 reason=Close - AGE OUT
$line =~ m/^.+?\=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s.+?\=(\d+?)\s.+?\=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s.+?\=(\d+?)\s.+?(\d+?)\s.+?\=(.*)/; # Grabs Xlated src and dst ip's and ports, session id and reason
print "Xlate_src: $1\tXlate_src_port: $2\tXlate_dst: $3\tXlate_dst_port: $4\tSessionID: $5\tReason: $6\n";
}
}
close(SYSLOG);

I added a section of the syslog in comment form prior to each Regex so you can see what the program is currently working on.

Part 2 will see the move from screen print to database insertion as well as some more data manipulation to provide clear, concise rules to be added to the firewall rule set.

Check back soon to see Part 2 or add me to your RSS feed to be notified automatically.

I would love to hear comments from experienced coders on how they would have tackled this project.

Share