Graphing DNS with bind9stats and xymon

Abstract

I couldn't find a satisfying solution, so I wrote some ext script for bind9 stats to be used with my central monitoring xymon server.

I couldn't find a satisfactory solution, so I wrote some ext script for bind9 stats to be used with my central monitoring xymon server.

First of all we need statistical data. Put this bind9 config snippet in your servers configuration file:

zone-statistics yes;
statistics-file "/var/log/named.stats";

After that restart bind named to make the changes become effective.

Note

If you run bind chrooted you may need to create a symlink.

The next step was to extract useful data from the statistics file. My script /usr/local/bin/dns-awk.sh takes care of that:

#/bin/bash
/usr/bin/awk '
 BEGIN       {a=0;aaaa=0;any=0;cname=0;mx=0;ns=0;ptr=0;soa=0;srv=0;}
 /Incoming Queries/,/Outgoing Queries/ {
     if($2 == "A")     {a = $1}
     if($2 == "AAAA")  {aaaa = $1}
     if($2 == "ANY")   {any = $1}
     if($2 == "CNAME") {cname = $1}
     if($2 == "MX")    {mx = $1}
     if($2 == "NS")    {ns = $1}
     if($2 == "PTR")   {ptr = $1}
     if($2 == "SOA")   {soa = $1}
     if($2 == "SRV")   {srv = $1}
     if($2 == "SPF")   {spf = $1}
 }
 END         {print "a :" " " a "\n" "aaaa : " " " aaaa "\n" "any :" " " any "\n" "cname :" " " cname "\n" "mx :" " " mx "\n" "ns :" " " ns "\n" "ptr :" " " ptr "\n" "soa :" " " soa "\n" "srv :" " " srv "\n" "spf :" " " spf}'

The script should be executed by the xymon client. This requires special privileges. Permit sudo and/or add the hobbit/xymon user to bind's group:

Here's what I have in /etc/group:

...
adm:x:4:hobbit
...

Depending to the ownership of the stats file you may add the user hobbit or xymon to the group bind or named, too. May not be needed if you run the script with sudo as root.

Here's what I have in /etc/sudoers:

...
hobbit ALL=(root) NOPASSWD: /usr/sbin/rndc
hobbit ALL=(root) NOPASSWD: /bin/cat
hobbit ALL=(root) NOPASSWD: /usr/local/bin/dns-awk.sh
...

Once that has been prepared you can run the xymon client script. I called it /usr/lib/hobbit/client/ext/bind9stats.sh:

1
2
3
4
5
6
7
8
#/bin/bash
COLUMN=bind9stats
COLOR=green
sudo /usr/sbin/rndc stats
$BB $BBDISP "status $MACHINE.$COLUMN $COLOR `date`
`sudo /bin/cat /var/log/named.stats | /usr/local/bin/dns-awk.sh`
"
exit 0

Finally add the script in your /usr/lib/hobbit/client/etc/clientlaunch.cfg:

...
[bind9stats]
ENVFILE $HOBBITCLIENTHOME/etc/hobbitclient.cfg
CMD $HOBBITCLIENTHOME/ext/bind9stats.sh
LOGFILE /var/log/hobbit/bind9stats.log
INTERVAL 1m
...

On the xymon server, in /etc/xymon/graphs.cfg, you need to add the following code:

...
[bind9stats]
TITLE bind9stats
YAXIS #
DEF:a=bind9stats.rrd:a:AVERAGE
DEF:aaaa=bind9stats.rrd:aaaa:AVERAGE
DEF:any=bind9stats.rrd:any:AVERAGE
DEF:cname=bind9stats.rrd:cname:AVERAGE
DEF:mx=bind9stats.rrd:mx:AVERAGE
DEF:ns=bind9stats.rrd:ns:AVERAGE
DEF:ptr=bind9stats.rrd:ptr:AVERAGE
DEF:soa=bind9stats.rrd:soa:AVERAGE
DEF:srv=bind9stats.rrd:srv:AVERAGE
DEF:spf=bind9stats.rrd:spf:AVERAGE
LINE2:a#00CCCC:a
LINE2:aaaa#FF0000:aaaa
LINE2:any#C29B00:any
LINE2:cname#DD0000:cname
LINE2:mx#00AA00:mx
LINE2:ns#555555:ns
LINE2:ptr#330000:ptr
LINE2:soa#440000:soa
LINE2:srv#660000:srv
LINE2:spf#880000:spf
GPRINT:a:LAST:a \: %5.1lf%s (cur)
GPRINT:a:MAX: \: %5.1lf%s (max)
GPRINT:a:MIN: \: %5.1lf%s (min)
GPRINT:a:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:aaaa:LAST:aaaa \: %5.1lf%s (cur)
GPRINT:aaaa:MAX: \: %5.1lf%s (max)
GPRINT:aaaa:MIN: \: %5.1lf%s (min)
GPRINT:aaaa:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:any:LAST:any \: %5.1lf%s (cur)
GPRINT:any:MAX: \: %5.1lf%s (max)
GPRINT:any:MIN: \: %5.1lf%s (min)
GPRINT:any:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:cname:LAST:cname \: %5.1lf%s (cur)
GPRINT:cname:MAX: \: %5.1lf%s (max)
GPRINT:cname:MIN: \: %5.1lf%s (min)
GPRINT:cname:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:mx:LAST:mx \: %5.1lf%s (cur)
GPRINT:mx:MAX: \: %5.1lf%s (max)
GPRINT:mx:MIN: \: %5.1lf%s (min)
GPRINT:mx:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:ns:LAST:ns \: %5.1lf%s (cur)
GPRINT:ns:MAX: \: %5.1lf%s (max)
GPRINT:ns:MIN: \: %5.1lf%s (min)
GPRINT:ns:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:ptr:LAST:ptr \: %5.1lf%s (cur)
GPRINT:ptr:MAX: \: %5.1lf%s (max)
GPRINT:ptr:MIN: \: %5.1lf%s (min)
GPRINT:ptr:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:soa:LAST:soa \: %5.1lf%s (cur)
GPRINT:soa:MAX: \: %5.1lf%s (max)
GPRINT:soa:MIN: \: %5.1lf%s (min)
GPRINT:soa:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:srv:LAST:srv \: %5.1lf%s (cur)
GPRINT:srv:MAX: \: %5.1lf%s (max)
GPRINT:srv:MIN: \: %5.1lf%s (min)
GPRINT:srv:AVERAGE: \: %5.1lf%s (avg)\n
GPRINT:spf:LAST:spf \: %5.1lf%s (cur)
GPRINT:spf:MAX: \: %5.1lf%s (max)
GPRINT:spf:MIN: \: %5.1lf%s (min)
GPRINT:spf:AVERAGE: \: %5.1lf%s (avg)\n
...

I didn't get the graph data right the first time. After a few iterations things began to work for me (I was only interested in seeing trends). I finally ended up with this config in /etc/xymon/xymonserver.cfg:

NCV_bind9stats="*:COUNTER" # DERIVE might be better ,your choice
...
TEST2RRD="...,bind9stats=ncv"
GRAPHS="...,bind9stats
...

Once you restart the server and the client you should see a monitoring graph like this which continues growing:

Note

If you need alarms and other bind9 data you may fetch if from this output:

$ /usr/sbin/rndc stats

Caution!

Apply logrotation on named.stats as it may grow very large over time. It may may result in graphs being reset, which I consider the minor problem compared to a full partition.

This logrotate job in /etc/logrotate.d/bind9 might fit your requirements:

/usr/named/var/log/named.stats
{
 rotate 4
 daily
 missingok
 notifempty
 create 644 bind bind
 compress
 delaycompress
 sharedscripts
 postrotate
         /etc/init.d/bind9 reload > /dev/null
 endscript
 }
Robert Schetterer, 25. January 2013