AfterGlow 1.x Manual

Introduction
Parsers
Invocation
Node Configuration - Graph Representation
Configuration File
Command Line Parameters
Functions

Introduction

AfterGlow is a collection of scripts which facilitate the process of generating link graphs. The tool is written in Perl and needs to be invoked via the command line. Sorry, there is no graphical interface, however using the tool is quite simple. As input, AfterGlow expects a CSV file. The file can either contain two or three columns of data. A common way of generating the CSV files are parsers which take a raw input file, analyze it and output a comma separated list of records based on the data they found. The output of AfterGlow is one of two formats. Either it generates a dot attributed graph language file - the input required by the graphviz library - or it can generate GDF files that can, for example, be visualized with
Gephi.

Parsers

AfterGlow provides a couple of example parsers to generate CSV input files. The first one to parse tcpdump output and the second one to parse sendmail log files. Here is an example of how to run the tcpdump parser file:
    tcpdump -vttttnneli eth0 | parsers/tcpdump2csv.pl "sip dip dport"
This command will invoke tcpdump on interface eth0 and pipe the input through the parser. We tell the parser that we are interested in the source IP (sip), the destination IP (dip) and the destination port (dport). To see what other fields are available, have a look at the parser. The output of this command is a comma separate list of sip, dip, dport pairs for each of the lines tcpdump outputs. For example, if the tcpdump output is the following:
    18:46:27.849292 IP 192.168.0.1.39559 > 127.0.0.1.80: S 1440554803:1440554803(0) win 32767 
    18:46:27.849389 IP 192.168.0.1.80 > 127.0.0.1.39559: S 1448343500:1448343500(0) ack 1440554804 win 32767 
the output would simply be:
    192.168.0.1,127.0.0.1,80
    192.168.0.1,127.0.0.1,80
You might wonder why the second entry shows the source and destination inverted, not following the exact output of tcpdump. Well, that's because the parser remembers the source of a communication and automatically inverts the responses to reflect that behavior. It outputs the direction of the communication (client to server) and not the direction of the packets. This is very useful when visualizing network traffic. Think about it!

Another possible way to generate input for AfterGlow is to use Microsoft Excel, manually enter the data and save the output as a CSV file.

Invocation

To generate a dot graph file for graphviz, run the following command:
    cat file.csv | perl afterglow.pl -c color.properties > file.dot
This file can then be used with dot or neato to render a graph.

Putting this all together, here is an example on how to generate a graph (gif file) from a saved pcap file:
    tcpdump -vttttnnelr /home/ram/defcon.tcpdump | ./tcpdump2csv.pl "sip dip dport" | \
    perl afterglow.pl -c color.properties | neato -Tgif -o test.gif
Invoking afterglow.pl, we specified a color property file. This file is used by AfterGlow to determine the colors of the edges and nodes in the graph. Read the section further down to find out more about that file.

Interesting Command Lines

Here are a couple of interesting ways of running AfterGlow:
    tshark -r file.pcap -e ip.dst -e ip.src -e tcp.srcport -T fields -E separator=, -R "tcp and tcp.flags.syn==1 and tcp.flags.ack==1" | sort | uniq > ipdst_ipsrc_tcpsrc.csv
This will invoke tshark on a file, extract connections that were successful and generate a CSV file with destination IP, source IP, and source port, which is really the destination port, because of the source/destination confusion.
    tshark -r file.pcap -e ip.src -e ip.dst -e tcp.dport -T fields -E separator=, -R "tcp and tcp.flags.syn==1 and tcp.flags.ack==0" | sort | uniq > ipdst_ipsrc_tcpsrc.csv
Not how the tcp.flags.ack is set to zero. These are connections that were not answered! Only a SYN was seen.

Node Configuration - Graph Representation

Depending on how many columns you feed AfterGlow, you can run it in two modes. either in two-column or three-column mode. In the former mode, you define nodes that are being connected with each other. Just what you would expect.

Two node configuration

If three columns are used as input, the graph output is represented with three nodes, where the first column represents the source node, the second one the event node and the third one the target node.

Three node configuration

Example output for a three node configuration:

Three node example graph

Make sure that when feeding AfterGlow only two columns, you use the -t parameter!

Configuration File

Most of the capabilities in AfterGlow are driven by the color.properties file that is used to configure the color output. The following is an example of a configuration file:
    # AfterGlow Color Property File
    #
    # @fields is the array containing the parsed values
    # color.source is the color for source nodes
    # color.event is the color for event nodes
    # color.target is the color for target nodes
    #
    # The first match wins
    #
    color.source="yellow" if ($fields[0]=~/^192\.168\..*/);
    color.source="greenyellow" if ($fields[0]=~/^10\..*/);
    color.source="lightyellow4" if ($fields[0]=~/^172\.16\..*/);
    color.source="red"
    color.event="yellow" if ($fields[1]=~/^192\.168\..*/)
    color.event="greenyellow" if ($fields[1]=~/^10\..*/)
    color.event="lightyellow4" if ($fields[1]=~/^172\.16\..*/)
    color.event="red"
    color.target="blue" if ($fields[2]<1024)
    color.target="lightblue"
    
This might look somewhat scary at first glance. It is not that bad! Before we are looking at the individual entries, we need to know what the input is that corresponds to this configuration. We are processing data which consists of three columns. The first two containing IP addresses and the third column representing ports. This means our input shows the source address for an event in the first column, the destination address in the second and the destination port in the third column. Now back to the configuration file. As you can see, there are basically three assignments: color.source, color.event, and color.target. Well, these values correspond to the three nodes in the Figure.



An assignment is a perl expression which has to return a color name. The expressions are evaluated top to bottom. As soon as an expression matches, the color for this node is assigned. Another important fact is that color configurations can reference the values of the current record, which are made available in the @fields array. The first column of the data is therefore accessible with $fields[0].

Getting back to our example, you should now understand what the first three lines are doing. Whenever the first column of the data ($fields[0]) starts with 192.168., the nodes is colored yellow. If it starts with 10., the node is greenyellow and if it starts with 172.16, it is colored in lightyellow4. If none of these conditions are true, red is the default color that will be used. The same logic is applies to the event nodes. This time referencing the second column ($fields[1]). For the target nodes, we want to color them blue if the target port is below 1024 and lightblue if it is equal or bigger than 1024. An example output graph with this configuration is shown below:



Command Line Parameters

This is a list of all the command line parameters that afterglow.pl understands:
    perl afterglow.pl [-adhnstv] [-b lines] [-c conffile] [-e length] [-f threshold ] [-g threshold] [-l lines] [-o threshold] [-p mode] [-x color] [-m maxsize]
-a           : turn off labelelling of the output graph with the configuration used
-b lines     : number of lines to skip (e.g., 1 for header line)
-c conffile  : color config file
-d           : print node count
-e length    : edge length
-f threshold : source fan out threshold
-g threshold : event fan out threshold (only in three node mode)
-h           : this (help) message
-l lines     : the maximum number of lines to read
-m           : the maximum size for a node
-n           : don't print node labels
-o threshold : omit threshold (minimum count for nodes to be displayed) 
               Non-connected nodes will be filtered too.
-p mode      : split mode for predicate nodes where mode is
                0 = only one unique predicate node (default)
                1 = one predicate node per unique subject node.
                2 = one predicate node per unique target node.
                3 = one predicate node per unique source/target node.
-s           : split subject and object nodes
-t           : two node mode (skip over objects)
-u           : export URL tags
-v           : verbose output
-x           : text label color

  • 0 = only one unique predicate node (once per common event)
  • 1 = one predicate node per unique subject node. (once per unique source)
  • 2 = one predicate node per unique target node. (once per unique target)
  • 3 = one predicate node per unique source/target node. (once per unique source and target)
    -s : split subject and object nodes
    -t : two node mode / only two input columns
    -v : verbose output
    -x color : text label color

    Functions

    In later versions of AfterGlow, functions have been introduced. These functions can be used in the property file to accomplish clustering, filtering and coloring. The functions are listed in the following:

    field() Returns the current field. For example:
                "red" if (field() eq "foo");
                
    match("regex") Matches the current field and returns 0 or 1, depending on whether the regular expression (regex) matched.
                match("[0-9]")
    
    regex_replace()
            return ($globalField =~ /$regex/)[0]; 
    			
    subnet()
            my ($value,$value2) = @_;
    
            my @temp = split(/\./,$value);
            # return if not an IP address
            return(0) if (scalar(@temp) != 4);      # very simplistic test!
    
            my $ip=unpack("N",pack("C4",@temp));
    
            my ($network,$mask) = $value2 =~ /([^\/]+)\/(.*)/;
            $network=unpack("N",pack("C4",split(/\./,$network)));
    
            $mask = (((1 << $mask) - 1) << (32 - $mask));
            $newNet = join(".",unpack("C4",pack("N",$ip & $mask)));
            $newNetwork = join(".",unpack("C4",pack("N",$network & $mask)));
    
            if ($newNetwork eq $newNet) {
                    return 1;
            } else {
                    return 0;
            }