DNS Monitor Using Dig

Problem this snippet solves:

This monitor uses dig to verify an expected response from load balanced DNS servers. It accepts 2 command-line arguments: the name to be looked up, and a string found in the expected response.

NOTE: Use external monitors only when a built-in monitor won't do the trick. This example is intended to demonstrate the basic use of dig in an external monitor to test UDP-based name services.

How to use this snippet:

Implementation

  1. Create a new file containing the code below on the LTM filesystem. Recommended location is /config/eav. Permissions on the file must be 700 or better, giving root rwx access to the file. 2. Create a monitor profile of type "External" with the following values:

    • External Program: . . the name of the script file created in step 1
    • Arguments:
    • * " ", where string has x.x.x.x format for A lookup and ::::::: format for AAAA lookups
    • 3. Adjust the interval and timeout as appropriate for your application

Alternative Monitor Uses dig(1) More Efficiently

The Alternative Monitor Script below allows you to adjust dig(1) query type, timeout, and retry count.

The dig(1) utility normally waits just 5 seconds for a response to each DNS query, and retries failed queries twice. 5 seconds is too short for many queries across the Internet. Suppose you have DNS servers using different Internet gateways and wish to load-balance client DNS queries (received on a virtual server address) to your DNS servers. You can monitor DNS server and Internet gateway availability at the same time by querying each DNS server for a short-TTL RR from somewhere out on the Internet (short TTL so local caching won't mask gateway failure). In this scenario (and in other cases not discussed here) you may wish to allow a longer dig(1) timeout and limit the number of retries.

Some more implementation notes appear as comments in the script.

#!/bin/bash
#
# Script 'dns-monitor' brought to you by COSTCO WHOLESALE CORP.
# Prepared 2010-04-23 by Mark Seecof for Costco Wholesale Corp.

# LTM gives every external-monitor program the target
# node's IP address and port as arguments $1 $2
# We must strip off IPV6 notation
node="${1#::ffff:}"
port="${2}"

# (To save time in the normal case we omit to validate
# arguments, though it would not be difficult to do so.)
#
# When you setup your external monitor, give as 'arguments':
# $3, the DNS name to query;
# $4, the type of its RR (e.g., 'A');
# $5, a grep(1) pattern which will match a successful
# (dig +short) result but not a failed one;
# $6, the query timeout in seconds (at least 2 seconds less
# than the monitor's overall timeout).
#
# $7 (optional) if you wish an unanswered query retried (only
# needed with a lossy network or overloaded DNS server), give
# the retry count as $7--and reduce your $6 query timeout
# proportionally (i.e., if you double the number of queries,
# cut query timeouts in half, because you must make the sum
# of query timeouts less than the monitor's overall timeout).
#
# EXAMPLE MONITOR SETUP:
# Suppose a working DNS server will respond within 10 seconds
# maximum to queries for the following RR:
#example.comNSns1.example.com
#
# Copy this script to /config/monitors/dns-monitor (on both
# LTM's in a failover pair) and make executable (chmod +x).
# For this example, we will check on the DNS server 3 times
# per minute.  Create an 'external' monitor, set 'external
# program' to "/config/monitors/dns-monitor".  Set 'interval'
# to 20 seconds, 'timeout' to 15 seconds, and set 'arguments'
# to "example.com NS ns1.example.com 10".  The padding in the
# various timeouts allows for variations in system load
# affecting real response times.
#
# ('.' is a regex operator so the pattern "ns1.example.com"
# is ambiguous-- but unlikely to cause trouble.  If you will
# never need to test mildly-variable query results, you may
# change "grep -q" to "grep -q -F" below...)
#
query="${3}"
type="${4}"
want="${5}"
timeout="${6:-5}"
retry="${7:-0}"

if /usr/bin/dig "@${node}" -p "${port}" +short \
-t "${type}" -q "${query}" "+time=${timeout}" \
"+retry=${retry}" | /bin/grep -q "${want}" 2>/dev/null ; then
 echo "UP" ;
 exit 0 ;
fi
exit 1

#bottom of file

Code :

#!/bin/sh
# (c) Copyright 1996-2007 F5 Networks, Inc.
#
# This software is confidential and may contain trade secrets that are the
# property of F5 Networks, Inc.  No part of the software may be disclosed
# to other parties without the express written consent of F5 Networks, Inc.
# It is against the law to copy the software.  No part of the software may
# be reproduced, transmitted, or distributed in any form or by any means,
# electronic or mechanical, including photocopying, recording, or information
# storage and retrieval systems, for any purpose without the express written
# permission of F5 Networks, Inc.  Our services are only available for legal
# users of the program, for instance in the event that we extend our services
# by offering the updating of files via the Internet.
#
#
# these arguments supplied automatically for all external monitors:
# $1 = IP (nnn.nnn.nnn.nnn notation or hostname)
# $2 = port (decimal, host byte order) -- not used in this monitor, assumes default port 53
# $3 = name to be looked up
# $4 = string in expected response

node_ip=`echo $1 | sed 's/::ffff://'`

pidfile="/var/run/`basename $0`.$node_ip..$2.pid"
if [ -f $pidfile ]
then
   kill -9 `cat $pidfile` > /dev/null 2>&1
fi
echo "$$" > $pidfile

dig @${node_ip} ${3} | egrep -v '^$|^;' | grep ${4} > /dev/null 2>&1

# For AAAA lookups, use this instead
# dig @${node_ip} ${3} AAAA| egrep -v '^$|^;' | grep ${4} > /dev/null 2>&1

status=$?
if [ $status -eq 0 ]
then
    rm -f $pidfile
    echo "UP"
else 
    rm -f $pidfile
fi
Published Mar 12, 2015
Version 1.0
  • Great EAV given the supplied DNS monitor profile only supports query types "a" and "aaaa". Using this to look up the NS for root on my resolvers. Thanks!