Mapping OSSEC Alerts with AfterGlow

AfterGlowThis week is the third annual OSSEC week! A good initiative to promote this open source log management solution. This post is my first contribution to the OSSEC community, I hope to publish more posts if I’ve enough time. OSSEC is a excellent tool to collect and analyze the events generated by your (multiple) hosts and applications. But, being based on a command line interface, OSSEC lacks of “visibility” (IMHO). As you know, “one picture is worth a thousands words“. That’s why displaying a “map” of your alerts could be very helpful to quickly detect suspicious activity or to analyze security incidents. My goal was to add a feature like the one presents in the ArcSight ESM tool (called “Event Graph“).

OSSEC proposes for a while an interface with Picviz. Picviz is a nice tool but the integration is very basic and does not allow to filter some events.  The generated graphs can become quickly unreadable if you have a lot of alerts. I’m a big fan of another visualization tool called AfterGlow. Basically, this tool helps to understand the relations that you have between “objects“. In the context of OSSEC, the useful objects are:

  • The attackers (source IP address or user)
  • The alert description
  • The destination (the OSSEC location based on the agent name / log source)

Some examples:

  [] -> [Attempt to access forbidden file or directory.] -> [web1->/var/log/apahe2/access.log]
  [] -> [SSHD authentication success.] -> [unix1->/var/log/auth.log]
  [] -> [Access attempt blocked by Mod Security.] -> [web1->/var/log/apahe2/error.log]

My first idea was to add an interface like the one implemented for Picviz (using a named pipe). But the required information is already available in the OSSEC MySQL database (if you enabled this feature). To feed Afterglow with OSSEC data, I’m using a Perl script which read the database. The script syntax is:

  Usage: ./ --dbpass=password [--dbhost=] [--dbport=3306]
     [--dbname=ossec] [--dbuser=ossec] [--logfile=./alerts2afterglow.log]
     [--exclude-alerts=id1[,id2,...]] [--time-interval="30 minute"]
     [--do-reverse] [--show-duplicate] [--help] [--debug]

The most important parameters are:

  • –time-interval” allows to specify the amount of alerts to export starting from now(). Supported values are “second”, “minute”, “hour”, “day” or “week”.
  • –exclude-alert” allows to exclude a list of OSSEC alert IDs. This is useful to remove “noise” from your graphs. IDs are separated by commas.
  • –do-reverse” allows to perform a reverse DNS lookup of all IP addresses extracted from the database. Sometimes, it’s easier to interpret the source of the attacks

To generate a complete graph, combine the Perl script with Afterglow and a dot rendering tool:

  $ ./ --dbpass=xxx \
                          --exclude-alerts=3302,3303 \
                          --time-interval="1 hour" \
        | ./ -c \
        | circo -v -Tgif -o /var/www/ossec-alerts-1h.gif

And here are some examples of generated maps:

OSSEC Alerts
(Click to enlarge)
OSSEC Alerts 2
(Click to enlarge)

The Perl script is available here. Comments and contributions are welcome!


  1. Hello Nik,
    Here is mine:

    # 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
    # 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.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””blue” if ($fields[2]<1024)"lightblue"




  2. Hi, maybe I just over read it, but where can I find the file? I dont want to read all this afterglow config stuff…
    I would appreciate if you post it somewhere, preferably with the

  3. @xme,

    Do you know of a way to segment source IPs into zones / networks? I’m visually a left to right person and document least trusted zones (Internet in this example) on the left, to most trusted zones on the right.


  4. Hi Raffael,
    Thank you for the comment and suggestions, really appreciated coming for a guy like you!
    Question: Do you know if it’s possible to increase the size of the attacker box based, eg on the number of occurence (like in ArcSight)


  5. Fantastic. I love it! Quick suggestion: Run afterglow with “-e 1.2” This will change the default edge length to 1.2 instead of 2, which brings the nodes a bit closer together. You may also want to be careful with circo. Circo doesn’t scale very well. It is perfect for just a few nodes, but for more, you may wanna use neato.
    I’d encourage you to post this on also!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.