From dadb9bb181984dd52f0cfe631bfe7fc7c1098a4c Mon Sep 17 00:00:00 2001
From: Frederik Lindenaar <frederik@lindenaar.nl>
Date: Tue, 9 Mar 2021 21:48:55 +0100
Subject: [PATCH] First commit for check_dns_replication

---
 README.md                     |  87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 plugins/check_dns_replication | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+), 13 deletions(-)
 create mode 100755 plugins/check_dns_replication

diff --git a/README.md b/README.md
index 6330a6e..565d82d 100644
--- a/README.md
+++ b/README.md
@@ -12,12 +12,14 @@ encounter any issues or require changes.
 The latest versions, documentation and bugtracker available on my
 [GitLab instance](https://gitlab.lindenaar.net/scripts/nagios-plugins)
 
-Copyright (c) 2015 - 2019 Frederik Lindenaar. free for distribution under
+Copyright (c) 2015 - 2021 Frederik Lindenaar. free for distribution under
 the GNU General Public License, see [below](#license)
 
 contents
 ========
 This repository contains the following scripts:
+  * [check_dns_replication](#check_dns_replication)
+    check DNS zone replication by comparing zone serial numbers on DNS servers
   * [check_memory](#check_memory)
     patched version of nagios-plugins check_memory script for Linux procps v3.3+
   * [check_multiple_host_addresses](#host_addresses)
@@ -30,6 +32,66 @@ This repository contains the following scripts:
   * [nagiosstatus](#nagiosstatus)
     CGI-BIN script to report the status of nagios (to monitor nagios itself)
 
+
+<a name=check_dns_replication>plugins/check_dns_replication</a>
+---------------------------------------------------------------
+With this check plugin / script, Nagios can monitor the replication of DNS zones
+between the authoritative DNS server for a domain and one or more of it's slave
+(or secondary) DNS servers. The script can check one or multiple DNS zones and
+can be pointed at one ore more specific DNS slave server(s) or us the NS records
+of the zone to check all DNS servers of that domain (or a combination of this)
+
+The script expects a (comma separated list of) DNS zone(s) to validate as its
+first command line parameter. It optionally also accepts one or more DNS servers
+to check as further parameters (either separate parameters or comma separated).
+If no DNS Servers are provided or the `-n` command line option is passed it will
+lookup the DNS Servers from the NS records in de DNS zone.
+
+The script will first fetch the authoritative DNS server from the SOA record, so
+that server must be reachable. This first lookup will be done against the first
+DNS server, if provided, or the default nameserver of the host. Next it will
+fetch the DNS zone's SOA record from each server and compare it with the master.
+
+Installation is straightforward, after installing the script on your server, add
+the following to your `commands.cmd` configuration file to make it available:
+
+~~~
+# 'check-dns-replication' command definition to check DNS replication of one or more zones
+define command {
+        command_name    check-dns-replication
+        command_line    [install_path]/plugins/check_dns_replication -n '$ARG1$' '$HOSTADDRESS$'
+}
+
+# 'check-dns-slave' command to check DNS replication of one or more zones against a single server
+define command {
+        command_name    check-dns-slave
+        command_line    [install_path]/plugins/check_dns_replication '$ARG1$' '$HOSTADDRESS$'
+}
+~~~
+
+The example below shows how to check DNS zone replication  for the primary DNS
+server (which checks replication to all secondaries) and how to check an extra
+secondary DNS server that is not listed as NS record in the zone.
+
+~~~
+# check DNS replication for an DNS zone to ensure all secondaries are in sync
+define service {
+        host                   auth.dns.mydomain.tld
+        service_description    DNS Zone Replication
+        check_command          check-dns-replication!mydomain.tld
+        use                    generic-service
+}
+
+# check DNS replication to a specific secondary DNS server
+define service {
+        host                   sec1.dns.mydomain.tld
+        service_description    DNS Zone Replication to secondary
+        check_command          check-dns-slave!mydomain.tld
+        use                    generic-service
+}
+~~~
+
+
 <a name=check_memory>plugins/check_memory</a>
 ---------------------------------------------
 Nagios check script to monitor the memory on Linux systems. Due to changes in
@@ -54,23 +116,23 @@ Installation is straightforward, after installing the script on your server, add
 the following to your `commands.cmd` configuration file to make it available:
 
 ~~~
-  # 'check-host-alive' command definition for multi-homed/dual-stack servers
-  define command{
-        command_name    check-addresses-alive
-        command_line    [install_path]/plugins/check_multiplehost_addresses '$HOSTADDRESS$' '$_HOSTADDRESS6$'
-  }
+# 'check-host-alive' command definition for multi-homed/dual-stack servers
+define command {
+    command_name    check-addresses-alive
+    command_line    [install_path]/plugins/check_multiplehost_addresses '$HOSTADDRESS$' '$_HOSTADDRESS6$'
+}
 ~~~
 
 The example above assumes that the IPv6 address of the host is provided as part
 of the host configuration, i.e.:
 
 ~~~
-  define host {
-        ...
-        address         192.168.0.1
-        _address6       fdf8:f340:ab9d:c213::1
-	...
-  }
+define host {
+    ...
+    address         192.168.0.1
+    _address6       fdf8:f340:ab9d:c213::1
+    ...
+}
 ~~~
 
 To use the script either add `check_command check-addresses-alive`
@@ -431,4 +493,3 @@ General Public License for more details.
 
 You should have received a copy of the GNU General Public License along with
 this program.  If not, download it from <http://www.gnu.org/licenses/>.
-
diff --git a/plugins/check_dns_replication b/plugins/check_dns_replication
new file mode 100755
index 0000000..56e54d7
--- /dev/null
+++ b/plugins/check_dns_replication
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+# check_dns_replication - check DNS zone replication by comparing zone serials
+#
+# Version 1.0, latest version, documentation and bugtracker available at:
+#               https://gitlab.lindenaar.net/scripts/nagios-plugins
+#
+# Copyright (c) 2021 Frederik Lindenaar
+#
+# This script is free software: you can redistribute and/or modify it under the
+# terms of version 3 of the GNU General Public License as published by the Free
+# Software Foundation, or (at your option) any later version of the license.
+#
+# This script is distributed in the hope that it will be useful but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program.  If not, visit <http://www.gnu.org/licenses/> to download it.
+
+# Usage: check_dns_replication [-n] dns_zone[,dns_zone...] [dns_server...]
+
+if [ "$#" -eq 0 -o "$1" == "-n" -a "$#" -eq 1 ]; then
+    echo "DNSREPLICATION: UNKNOWN | missing parameter dns_zone"
+    exit 3
+elif [ "$1" == "-n" ]; then
+    DNS_SERVER_LOOKUP=$1
+    shift
+elif [ $1 == '-h' -o $1 == '--help' ]; then
+    cat << EOT
+`basename $0` - check DNS zone replication by comparing SOA serial(s)
+
+usage: $0 [-n] dns_zone[,dns_zone...] [dns_server...]
+
+parameters:
+    -n    when specified (or no dns_server provided) check domain's NS records
+    -h    this help
+    dns_zone[,dns_zone...]  list of DNS zones to check (comma separated!)
+    [dns_server...]         DNS server(s) to compare with authoratative server
+
+EOT
+    exit 3
+elif [[ "$1" = -* ]]; then
+    echo "DNSREPLICATION: UNKNOWN | invalid parameter, for help run $0 -h"
+    exit 3
+fi
+
+DNS_ZONES=${1//,/ }
+shift
+DNS_SERVERS=${*//,/ }
+
+n="
+"
+NAGIOS_STATE=OK
+NAGIOS_RESULT=0
+NAGIOS_DETAILS=
+
+for DNS_ZONE in $DNS_ZONES; do
+  read AUTH_NAMESERVER <<<$(host -t soa $DNS_ZONE ${DNS_SERVERS// .*/} | tail -1 | cut -d\  -f5 | sed "s/.$//")
+  [ -n "$AUTH_NAMESERVER" ] && read AUTH_SOA_SERIAL <<<$(host -t soa $DNS_ZONE $AUTH_NAMESERVER | tail -1 | cut -d\  -f7)
+  if [ -z "$AUTH_SOA_SERIAL" ]; then
+    NAGIOS_STATE=CRITICAL
+    NAGIOS_RESULT=2
+    NAGIOS_DETAILS="$NAGIOS_DETAILS$n$DNS_ZONE: unknown domain (unable to resolve)"
+  else
+    NAMESERVER_OK=
+    NAMESERVER_HIGHER=
+    NAMESERVER_LOWER=
+    NAMESERVER_EMPTY=
+    NAMESERVERS=$DNS_SERVERS
+    if [ -z "$DNS_SERVERS" -o "$DNS_SERVER_LOOKUP" == '-n' -o "$DNS_SERVERS" == "$AUTH_NAMESERVER" ]; then
+      NAMESERVERS="$NAMESERVERS $(host -t ns $DNS_ZONE $AUTH_NAMESERVER | fgrep -v : | sed "s/.* //;s/\.$//")"
+    fi
+    for NAMESERVER in $NAMESERVERS; do
+      if [ "$NAMESERVER" != "$AUTH_NAMESERVER" ]; then
+        SOA_SERIAL=$(host -t soa $DNS_ZONE $NAMESERVER | tail -1 | cut -d\  -f 7)
+        if [ -z "$SOA_SERIAL" ]; then
+          NAMESERVER_EMPTY="$NAMESERVER_EMPTY$NAMESERVER,"
+        elif [ "$SOA_SERIAL" -lt "$AUTH_SOA_SERIAL" ]; then
+          NAMESERVER_LOWER="$NAMESERVER_LOWER$NAMESERVER,"
+        elif [ "$SOA_SERIAL" -gt "$AUTH_SOA_SERIAL" ]; then
+          NAMESERVER_HIGHER="$NAMESERVER_HIGHER$NAMESERVER,"
+        else
+          NAMESERVER_OK="$NAMESERVER_OK$NAMESERVER,"
+        fi
+      fi
+    done
+    NAGIOS_DETAILS="$NAGIOS_DETAILS$n$DNS_ZONE: $AUTH_NAMESERVER($AUTH_SOA_SERIAL)"
+    [ -n "$NAMESERVER_OK" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS ok:$NAMESERVER_OK"
+    [ -n "$NAMESERVER_HIGHER" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS higher:$NAMESERVER_HIGHER"
+    [ -n "$NAMESERVER_LOWER" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS lower:$NAMESERVER_LOWER"
+    [ -n "$NAMESERVER_EMPTY" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS error:$NAMESERVER_EMPTY"
+    if [ -n "$NAMESERVER_HIGHER$NAMESERVER_LOWER$NAMESERVER_EMPTY" ]; then
+      NAGIOS_STATE=CRITICAL
+      NAGIOS_RESULT=2
+    fi
+    NAGIOS_DETAILS="${NAGIOS_DETAILS%,}"
+  fi
+done
+
+echo "DNSREPLICATION: $NAGIOS_STATE$NAGIOS_DETAILS"
+exit $NAGIOS_RESULT
--
libgit2 0.22.2