#!/usr/local/bin/perl # # fwtable.pl ver 1.1beta # # Created by Lance Spitzner, lance@spitzner.net # July 3, 1999 # # Modified June 10. 2000 # Address Translation Tables, large part by # Brett Eldridge, beldridg@best.com # # Distributed under the terms of this General Public License # http://www.gnu.org/copyleft/gpl.html # # Converts FW-1 Connections table to readable format # # The purpose of this PERL script is to help you gain a better # understanding of Check Point FW-1's stateful inspection table. This # table is where FW-1 maintains all concurrent connections. When # marketing is talking about "stateful inspection", this table is # the heart of that. Check Point provides a tool to look at this # table, unfortunately it is extremelly cyptic, as it is in hex. # This script makes it easier to read by converting the hex to decimal. # The script also allows you to convert connections tables from remote # FWs, or tables you have already outputed to a file. # # Output has 9 columns, described as follows: # # NOTE: This script was written for FW-1, ver 4.1. Only the first 5 columns are # valid for ver 3.0. # # Src_IP = Source IP address # Src_Prt = Source Port # Dst_IP = Destination IP address # Dst_Prt = Destination Port # IP_prot = IP protocol (6 is TCP, 17 is UDP) # Kbuf = I THINK this means Kernel buffer memory used for this connection ?? # Type = I don't know # Flags = I don't know, maybe header flags? # Timeout = how much time is left / how much the total Timeout value is ############################################################# # SCRIPT BEGINS # ############################################################# ### Set variables $FWDIR="/etc/fw"; chomp($thispl = `basename $0`); ### Table definitions for connections ### Taken from $FWDIR/lib/table.def # ############################################################# # Get options from user # ############################################################# use Getopt::Std; getopts('hpsxc:i:t:'); ### Usage if ($opt_h) { &usage; exit(5); } if(!$opt_s && !$opt_x){ &usage; exit(5); } ### How many connections user wants to query if (defined($opt_c)) {$max = $opt_c;} else {$max = "500";} ### Which target user wants to query if (defined($opt_t)) {$target = $opt_t;} else {$target = "localhost";} ################################## ### Stateful Connections Table ### ################################## if (defined($opt_s)) { ### Get connections tabe from FW or an existing file. if (defined($opt_i)) { $fwfile="$opt_i"; open(INFILE, $fwfile) or die "FW file could not be found\n"; } else { open(INFILE, "$FWDIR/bin/fw tab -t connections -max $max $target | "); } $LineCount=0; print "\n\t\t\t\t ---- FW-1 CONNECTIONS STATE TABLE ---\n\n\n"; print "Src_IP \tSrc_Prt\tDst_IP \tDst_Prt\tIP_prot\tKbuf\tType\tFlags \tTimeout\n\n"; while() { ### Skip first four lines if($LineCount <= "3") { $LineCount +=1; next }; ### Grab a line, and start munging the data. $TheLine = $_; chomp($TheLine); ### Uncomment this if you want to see the raw data also. #print "$TheLine\n"; ### Set variables for each column. $src = substr($TheLine,1,8); $sport = hex(substr($TheLine,11,8)); $dst = substr($TheLine,21,8); $dport = hex(substr($TheLine,31,8)); $ip_p = hex(substr($TheLine,41,8)); $kbuf = hex(substr($TheLine,51,8)); $type = hex(substr($TheLine,61,8)); $flags = substr($TheLine,71,8); $timeout = substr($TheLine,81,9); $timeout =~ s/>//; # remove trailing > ### Convert protocols and and ports if ran with '-p' option. $ip_p=&ip_proto_name($ip_p); $dport=&portname($dport, $ip_p); ### Print out each column, per line. &convert($src); print "$sport\t"; &convert($dst); print "$dport\t"; print "$ip_p\t"; print "$kbuf\t"; print "$type\t"; print "$flags\t"; print "$timeout\n"; } } ########################################### ### Network Adddress Translation tables ### ########################################### ### Forward Address Translation Table if (defined($opt_x)) { $LineCount=0; # print the header for the data print "\n\n\t\t\t\t --- FORWARD ADDRESS TRANSLATION TABLE --- \n\n\n"; print "-------------- Original Packet --------------- ------------- Translated Packet -------------\n"; print "Src_IP Src_Pt Dst_IP Dst_Pt Src_IP Src_Pt Dst_IP Dst_Pt Timeout\n\n"; open(FWX_FORW, "$FWDIR/bin/fw tab -t fwx_forw -max $max $target | "); while() { ### Skip first four lines if($LineCount <= "3") { $LineCount += 1; next }; ### Grab a line, and start munging the data. $TheLine = $_; chomp($TheLine); #print "$TheLine\n"; # Uncomment to print raw data ### parse the line $orig_src = substr($TheLine,1,8); $orig_sport = hex(substr($TheLine,11,8)); $orig_dst = substr($TheLine,21,8); $orig_dport = hex(substr($TheLine,31,8)); $orig_ip_p = hex(substr($TheLine,41,8)); $xlate_src = substr($TheLine,51,8); # Note: the first and second character in the translated ports string # don't belong with the actual port. Is it an index? # We want to discard the first and second character. After all, we only # need one 4 bit number to represent all 65,535 ports. # Therefore, yank from column 63 not 61 and 83 not 81. $xlate_sport = hex(substr($TheLine,63,7)); $xlate_dst = substr($TheLine,71,8); $xlate_dport = hex(substr($TheLine,83,7)); $xlate_ip_p = hex(substr($TheLine,91,8)); $timeout = substr($TheLine,101,9); $timeout =~ s/>//; # remove trailing > ### Convert protocols and and ports if ran with '-p' option. $orig_ip_p=&ip_proto_name($orig_ip_p); $orig_sport=&portname($orig_sport, $orig_ip_p); $orig_dport=&portname($orig_dport, $orig_ip_p); $xlate_sport=&portname($xlate_sport, $orig_ip_p); $xlate_dport=&portname($xlate_dport, $orig_ip_p); ### print the line $orig_src=&convert($orig_src); print "$orig_sport\t"; $orig_dst=&convert($orig_dst); print "$orig_dport\t"; $xlate_src=&convert($xlate_src); print "$xlate_sport\t"; $xlate_dst=&convert($xlate_dst); print "$xlate_dport\t"; print "$timeout\n"; } ### Time for the reverse translation table # print the header for the data print "\n\n\n\n\n\t\t\t --- REVERSE ADDRESS TRANSLATION TABLE --- \n\n\n"; print "--------------- Original Packet ------------- -------------- Translated Packet ------------\n"; print "Src_IP Src_Pt Dst_IP Dst_Pt Src_IP Src_Pt Dst_IP Dst_Pt\n\n"; $LineCount = 0; # print the output header open(FWX_BACKW, "$FWDIR/bin/fw tab -t fwx_backw -max $max $target | "); while() { if($LineCount <= "3") { # skip first 4 lines $LineCount += 1; next }; $TheLine = $_; # grab a line and start munging chomp($TheLine); #print "$TheLine\n"; # parse the line $orig_src = substr($TheLine,1,8); $orig_sport = hex(substr($TheLine,11,8)); $orig_dst = substr($TheLine,21,8); $orig_dport = hex(substr($TheLine,31,8)); $orig_ip_p = hex(substr($TheLine,41,8)); $xlate_src = substr($TheLine,51,8); # Note: the first and second character in the translated ports string # don't belong with the actually port. Is it an index? # We want to discard the first and second character. After all, we only # need one 4 bit number to represent all 65,535 ports. $xlate_sport = hex(substr($TheLine,63,7)); $xlate_dst = substr($TheLine,71,8); $xlate_dport = hex(substr($TheLine,83,7)); $xlate_ip_p = hex(substr($TheLine,91,8)); $timeout = substr($TheLine,101,9); $timeout =~ s/>//; # remove trailing > ### Convert protocols and and ports if ran with '-p' option. $orig_ip_p=&ip_proto_name($orig_ip_p); $orig_sport=&portname($orig_sport, $orig_ip_p); $orig_dport=&portname($orig_dport, $orig_ip_p); $xlate_sport=&portname($xlate_sport, $orig_ip_p); $xlate_dport=&portname($xlate_dport, $orig_ip_p); # print the line $orig_src=&convert($orig_src); print "$orig_sport\t"; $orig_dst=&convert($orig_dst); print "$orig_dport\t"; $xlate_src=&convert($xlate_src); print "$xlate_sport\t"; $xlate_dst=&convert($xlate_dst); print "$xlate_dport\n"; } $LineCount=0; } ############################################################# # Sub-routines # ############################################################# ### routine to convert ip_address from hex to dec ### Big thanks to DEAN Ivan , ### who sent me this routine, and gave me the idea for ### this PERL script! sub convert { my ($source) = @_; $octet1 = substr($source,0,2); $octet2 = substr($source,2,2); $octet3 = substr($source,4,2); $octet4 = substr($source,6,2); $dec1 = hex($octet1); $dec2 = hex($octet2); $dec3 = hex($octet3); $dec4 = hex($octet4); print "$dec1.$dec2.$dec3.$dec4\t"; } ### Convert IP protocol number to name using /etc/protocols ### Input: protocol number ($ip_p) ### Output: protocol name ($ip_p_name) if resolvable ### Brett Eldridge, beldridg@best.com sub ip_proto_name { ($ip_p) = @_; if ($opt_p eq 1) { if ($ip_p_name = (getprotobynumber($ip_p))) { } else { $ip_p_name = $ip_p; } } else { $ip_p_name = $ip_p; } return ($ip_p_name); } # Convert tcp or udp portnumber to service name using # /etc/services. # input: port number, ip protocol name # output: service name if resolvable, original number if not # Brett Eldridge, beldridg@best.com sub portname { ($portnumber, $ip_p) = @_; if ($opt_p eq 1) { if ($port = getservbyport($portnumber, $ip_p)) { } else { $port = $portnumber; } } else { $port = $portnumber; } return ($port); } ### You figure this one out :) sub usage { print < http://www.enteract.com/~lspitz/papers.html Usage: $thispl -s|x -c <# of connections> -i -t $thispl converts a FireWall-1 connections table or address translation table to readable format. It must be run with at least the -s or -x option. By default, $thispl queries the local machine for the FireWall-1 state table, and converts the first 500 connections. You have the following options: Required -------- -s: Query the Stateful Connections Table. or -x: Query the Network Address Translation table. Thanks to Brett Eldridge, beldridg\@best.com for this feature. Optional -------- -c: Number of connections you want to query from the Firewall. The default is 500. This option dos NOT work with the '-i' option. -i: Instead of querying a Firewall for the connections table, convert an existing file . -p: Convert protocol and port numbers to their standard names. Thanks to Brett Eldridge, beldridg\@best.com for this. -t: Query a remote Firewall for the connections table. EOT ; } ############################################################# # SCRIPT ENDS # #############################################################