#! /usr/bin/perl # # Purpose: # FlowGrapher_Main.cgi permits a Web user to analyze Net Flow data stored in # flow tools format and create a graph and partial listing of flows. # # Description: # The script responds to an HTML form from the user in order to collect # parameters that will control the analysis (e.g., router, time-period, ip # addresses etc.) Upon receipt of the form input the script creates a flow tools # filter file which controls the selection of the data via the invocation of # additional flow tools utilities. A graph is then created using the GD graphics # package. # # Input arguments (received from the form): # Name Description # ----------------------------------------------------------------------- # device_name An identifying name of the device (e.g. router1) # flow_select Identifies which flows to include wrt time period # start_date Start date of analysis period # start_time Start time of analysis period # end_date End date of analysis period # end_time End time of analysis period # source_addresses Constrain flows examined to these source IP addresses # source_ports Constrain flows examined to these source ports # source_ifs Constrain flows examined to these input interfaces # source_ases Constrain flows examined to these source ASes # dest_addresses Constrain flows examined to these dest. IP addresses # dest_ports Constrain flows examined to these dest. ports # dest_ifs Constrain flows examined to these output interfaces # dest_ases Constrain flows examined to these dest. ASes # tos_fields Constrain flows examined by specified TOS field values # tcp_flags Constrain flows examined by specified TCP flag values # protocols Constrain flows examined to these protocols # detail_lines Limit of detailed flow lines to print out for graphs # sample_time Amount of time for each graphing 'bucket' # graph_multiplier Multiplier of standard width for presented graph # resolve_addresses Whether or not to resolve IP addresses # # Modification history: # Author Date Vers. Description # ----------------------------------------------------------------------- # J. Loiacono 01/01/2006 2.0 Original released version # J. Loiacono 01/16/2006 2.1 Fixed compute of concatenation date, # end-of-year problem # J. Loiacono 01/26/2006 2.2 New flow_select to determine inclusion, # adjusted processing for flow_select # J. Loiacono 04/15/2006 2.3 Minimized use of timelocal for epoch to # speed things up ten-fold # J. Loiacono 05/31/2006 2.3.1 Fixed last bucket problem; caused spikes # (thanks Mark Foster) # J. Loiacono 07/04/2006 3.0 Changed name for reorganization # Resolve address option (thanks Mark Foster) # Single script for GDBM/NDBM (thanks Ed Ravin) # J. Loiacono 12/25/2006 3.1 Changes for MIN/MAX, more than 30 days # J. Loiacono 02/22/2007 3.2 [No Change to this module] # J. Loiacono 04/01/2007 3.2 Fixes to bucket alignment (removed rounding) # (thanks Dario La Guardia) # J. Loiacono 05/01/2007 3.2 Fixed FlowGrapher first, last buckets # #$Author$ #$Date$ #$Header$ # ########################################################################### # # BEGIN EXECUTABLE STATEMENTS # use FlowViewer_Configuration; use FlowViewer_Utilities; use GD; use GD::Graph::linespoints; use GD::Graph::mixed; use GD::Graph::bars; if ($debug_grapher eq "Y") { open (DEBUG,">$work_directory/DEBUG_GRAPHER"); } # Tie in the 'names' file which saves IP address resolved names if (eval 'local $SIG{"__DIE__"}= sub { }; use GDBM_File; tie %host_names, "GDBM_File", "$names_directory/names", GDBM_WRCREAT, 0666;' ) { if ($debug_grapher eq "Y") { print DEBUG "Using GDBM\n"; } }; if (eval 'local $SIG{"__DIE__"}= sub { }; use NDBM_File; use Fcntl; tie %host_names, "GDBM_File", "$names_directory/names", GDBM_WRCREAT, 0666;' ) { if ($debug_grapher eq "Y") { print DEBUG "Using NDBM\n"; } }; # Set up graphing colors GD::Graph::colour::read_rgb("FlowGrapher_Colors") or die "cannot read colors"; # Retrieve the form inputs read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $FORM{$name} = $value; } # Clean up input $FORM{source_address} =~ s/\s+//g; $FORM{source_address} =~ s/,/, /g; $FORM{source_port} =~ s/\s+//g; $FORM{source_port} =~ s/,/, /g; $FORM{source_if} =~ s/\s+//g; $FORM{source_if} =~ s/,/, /g; $FORM{source_as} =~ s/\s+//g; $FORM{source_as} =~ s/,/, /g; $FORM{dest_address} =~ s/\s+//g; $FORM{dest_address} =~ s/,/, /g; $FORM{dest_port} =~ s/\s+//g; $FORM{dest_port} =~ s/,/, /g; $FORM{dest_if} =~ s/\s+//g; $FORM{dest_if} =~ s/,/, /g; $FORM{dest_as} =~ s/\s+//g; $FORM{dest_as} =~ s/,/, /g; $FORM{protocols} =~ s/\s+//g; $FORM{protocols} =~ s/,/, /g; $FORM{tos_fields} =~ s/\s+//g; $FORM{tos_fields} =~ s/,/, /g; $FORM{tcp_flags} =~ s/\s+//g; $FORM{tcp_flags} =~ s/,/, /g; # Parameters for generating a FlowGrapher graph $device_name = $FORM{'device_name'}; $flow_select = $FORM{'flow_select'}; $start_date = $FORM{'start_date'}; $start_time = $FORM{'start_time'}; $end_date = $FORM{'end_date'}; $end_time = $FORM{'end_time'}; $source_addresses = $FORM{'source_address'}; $source_ports = $FORM{'source_port'}; $source_ifs = $FORM{'source_if'}; $source_ases = $FORM{'source_as'}; $dest_addresses = $FORM{'dest_address'}; $dest_ports = $FORM{'dest_port'}; $dest_ifs = $FORM{'dest_if'}; $dest_ases = $FORM{'dest_as'}; $protocols = $FORM{'protocols'}; $tcp_flags = $FORM{'tcp_flags'}; $tos_fields = $FORM{'tos_fields'}; $detail_lines = $FORM{'detail_lines'}; $sample_time = $FORM{'sample_time'}; $graph_multiplier = $FORM{'graph_multiplier'}; $resolve_addresses = $FORM{'resolve_addresses'}; # Build call string to provide filter parameters to either FlowGrapher or FlowTracker $call_string = "device_name=$device_name&"; $call_string .= "start_date=$start_date&"; $call_string .= "start_time=$start_time&"; $call_string .= "end_date=$end_date&"; $call_string .= "end_time=$end_time&"; $call_string .= "source_addresses=$source_addresses&"; $call_string .= "source_ports=$source_ports&"; $call_string .= "source_ifs=$source_ifs&"; $call_string .= "source_ases=$source_ases&"; $call_string .= "dest_addresses=$dest_addresses&"; $call_string .= "dest_ports=$dest_ports&"; $call_string .= "dest_ifs=$dest_ifs&"; $call_string .= "dest_ases=$dest_ases&"; $call_string .= "protocols=$protocols&"; $call_string .= "tcp_flags=$tcp_flags&"; $call_string .= "tos_fields=$tos_fields&"; $call_string =~ s/\s+//g; $save_file = "$device_name"; # Start the web page output print "Content-type:text/html\n\n"; print "
"; print ""; print ""; print "
";
print "| "; print HTML " | ";
print HTML " "; print HTML " "; printf HTML " Report: %-28s Sample Time: %-4s\n", $report_title, $sample_time; printf HTML " Start Time: %-28s End Time: %-28s\n", $start_flows, $end_flows; $html_file = "$work_directory/$save_filename"; print_formatted_parameters(%FORM,$html_file); printf HTML "Detail Lines: %-28s Graph Multiplier: %-28s\n", $detail_lines, $graph_multiplier; printf HTML " Include if: %-28s\n", $flow_select_manner; print HTML "\n"; print HTML " | ";
print HTML ""; print HTML " |
"; print HTML ""; if ($resolve_addresses eq "Y") { printf "%-9s %-9s %6s %-25s %-6s %-25s %-6s %14s %7s\n\n", "Start", "End", "Len", "Source Host", "Port", "Destination Host", "Port", "Total Bytes", "Mbps"; printf HTML "%-9s %-9s %6s %-25s %-6s %-25s %-6s %14s %7s\n\n", "Start", "End", "Len", "Source Host", "Port", "Destination Host", "Port", "Total Bytes", "Mbps"; } else { printf "%-9s %-9s %6s %-20s %-6s %-20s %-6s %14s %7s\n\n", "Start", "End", "Len", "Source Host", "Port", "Destination Host", "Port", "Total Bytes", "Mbps"; printf HTML "%-9s %-9s %6s %-20s %-6s %-20s %-6s %14s %7s\n\n", "Start", "End", "Len", "Source Host", "Port", "Destination Host", "Port", "Total Bytes", "Mbps"; } foreach $big_flow (@biggest_flows) { $big_flow = substr($big_flow,23,120); } @biggest_flows = sort(@biggest_flows); for ($m=0;$m<=$detail_lines;$m++) { if ($biggest_flows[$m] eq "") { next; } ($big_flow_key,$big_flow_bits,$big_flow_length) = split(/&/,$biggest_flows[$m]); if ($big_flow_length < 1) { $big_flow_length = 1; } $big_flow_rate = ($big_flow_bits / $big_flow_length) / 1000000; $big_flow_bytes = int ($big_flow_bits / 8); $formatted_bytes = format_number($big_flow_bytes); ($s_epoch,$s_tm,$e_tm,$sip,$sp,$dip,$dp) = split(/;/,$big_flow_key); if ($resolve_addresses eq "Y") { $sip = dig($sip); $dip = dig($dip); } if ($resolve_addresses eq "Y") { printf "%-9s %-9s %6.1f %-25.25s %-6s %-25.25s %-6s %14s %7.3f\n", $s_tm, $e_tm, $big_flow_length, $sip, $sp, $dip, $dp, $formatted_bytes, $big_flow_rate; printf HTML" %-9s %-9s %6.1f %-25.25s %-6s %-25.25s %-6s %14s %7.3f\n", $s_tm, $e_tm, $big_flow_length, $sip, $sp, $dip, $dp, $formatted_bytes, $big_flow_rate; } else { printf "%-9s %-9s %6.1f %-20.20s %-6s %-20.20s %-6s %14s %7.3f\n", $s_tm, $e_tm, $big_flow_length, $sip, $sp, $dip, $dp, $formatted_bytes, $big_flow_rate; printf HTML "%-9s %-9s %6.1f %-20.20s %-6s %-20.20s %-6s %14s %7.3f\n", $s_tm, $e_tm, $big_flow_length, $sip, $sp, $dip, $dp, $formatted_bytes, $big_flow_rate; } } } print "\n"; print HTML "\n"; print ""; print HTML "