BIND9 is the most widely deployed DNS server in the world, powering authoritative and recursive DNS for domains ranging from personal homelab zones to enterprise infrastructure. When BIND9 fails or degrades — whether from a crashed daemon, a corrupted zone file, or a DNSSEC key rollover gone wrong — every service that depends on name resolution fails with it. Applications can't reach databases, browsers can't resolve your website, and internal services lose contact with each other. Vigilmon adds the external observability layer BIND9 doesn't have built-in: probing DNS query responses, zone transfer health, the RNDC management interface, and DNSSEC validity from outside the server itself.
What You'll Set Up
- DNS query response health monitor (port 53)
- TCP connectivity probe for zone transfers
- RNDC management interface monitor (port 953)
- DNSSEC signing service validation
- Zone file validity heartbeat
- Query rate and NXDOMAIN rate tracking
- Recursive resolver connectivity check
Prerequisites
- BIND9 (
named) running on Linux - At least one authoritative zone configured
- RNDC configured with
rndc.keyor equivalent - A free Vigilmon account
Why DNS Monitoring Requires External Probes
The fundamental problem with self-monitoring DNS is that a broken DNS server can't tell you it's broken through DNS. Internal health checks that rely on localhost queries miss the class of failures that matter most:
- UDP packet loss at the network layer —
namedis running but queries from the internet never get responses - Zone loading failures —
namedstarts cleanly but refuses to serve a zone that failed to load - DNSSEC validation failures — your zones are signed but with expired keys, causing SERVFAIL for validating resolvers
- Recursive resolver poisoning — cache integrity issues that only show up when you query specific names
External probes from Vigilmon's global check network catch all of these because they query your DNS server the same way real clients do.
Step 1: Monitor DNS Query Response Health
The most important check: can BIND9 answer queries?
Vigilmon supports DNS-type monitors directly. Add one for each authoritative zone:
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
DNS. - Enter your DNS server's IP address.
- Set the Query name to a hostname in your authoritative zone (e.g.,
www.example.com). - Set Expected record type to
A. - Set Expected response to your server's expected IP address.
- Set Check interval to
1 minute. - Click Save.
This catches:
namedprocess crash (SERVFAIL or timeout)- Zone load failure (NXDOMAIN for a name that should exist)
- Wrong answer due to cache poisoning or misconfiguration
Add a second DNS monitor querying a different record type to broaden coverage:
- MX record for your mail domain — catches zone sections that load independently
- NS record for the zone apex — validates NS delegation
Step 2: Monitor TCP Port 53 for Zone Transfers
BIND9 uses TCP for zone transfers (AXFR/IXFR) and for responses exceeding 512 bytes. A firewall rule that blocks TCP/53 will silently break zone transfers from primary to secondary servers.
- Click Add Monitor → TCP Port.
- Host:
your-bind-host. - Port:
53. - Set Check interval to
5 minutes. - Click Save.
Also add a UDP connectivity check if Vigilmon offers one, or use the DNS monitor (Step 1) which exercises UDP/53 by default.
For secondary (slave) DNS servers, add a zone transfer health check:
#!/bin/bash
# /usr/local/bin/check-zone-transfer.sh
# Run on the secondary — checks that the zone SOA serial matches primary
PRIMARY_SOA=$(dig @primary-ns SOA example.com +short | awk '{print $3}')
SECONDARY_SOA=$(dig @localhost SOA example.com +short | awk '{print $3}')
if [ "$PRIMARY_SOA" = "$SECONDARY_SOA" ]; then
echo '{"zone_transfer": "in_sync"}'
exit 0
else
echo "{\"zone_transfer\": \"stale\", \"primary\": $PRIMARY_SOA, \"secondary\": $SECONDARY_SOA}"
exit 1
fi
Expose this and monitor the endpoint.
Step 3: Monitor the RNDC Management Interface
RNDC (Remote Name Daemon Control) lets you reload zones, flush the cache, and check server status without restarting named. If RNDC becomes unreachable, you lose the ability to push zone updates without a full restart.
RNDC listens on TCP port 953 by default, bound to localhost. To monitor it externally, create a health-check wrapper:
#!/bin/bash
# /usr/local/bin/rndc-health.sh — expose rndc status as HTTP
if rndc status > /dev/null 2>&1; then
echo -e 'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{"rndc": "ok"}'
else
echo -e 'HTTP/1.1 503 Service Unavailable\r\nContent-Type: application/json\r\n\r\n{"rndc": "error"}'
fi
Run with a minimal HTTP listener:
# /etc/systemd/system/rndc-health.service
[Unit]
Description=RNDC Health Check HTTP Endpoint
After=named.service
[Service]
ExecStart=/bin/bash -c 'while true; do \
echo -e "GET / HTTP/1.1\r\n" | nc -l -p 8053 -q1 | bash /usr/local/bin/rndc-health.sh; \
done'
Restart=always
Monitor http://your-bind-host:8053/ with Vigilmon expecting status 200.
rndc status returns non-zero if named is not responding to its control channel — even if named appears to be running as a process.
Step 4: Validate DNSSEC Signing Service
DNSSEC failures are particularly dangerous because they cause SERVFAIL responses for all validating resolvers — silently breaking your domain for users on ISPs that enforce DNSSEC validation. The failures are often invisible until you check from a validating resolver specifically.
Create a DNSSEC validation health check:
#!/bin/bash
# /usr/local/bin/dnssec-health.sh
ZONE="example.com"
NS="localhost"
# Check DNSKEY record exists and is valid
DNSKEY=$(dig @$NS DNSKEY $ZONE +dnssec +short 2>/dev/null)
if [ -z "$DNSKEY" ]; then
echo '{"dnssec": "error", "reason": "no DNSKEY found"}'
exit 1
fi
# Check RRSIG is not expired (within 7 days of expiry)
EXPIRY=$(dig @$NS A www.$ZONE +dnssec +short 2>/dev/null | grep RRSIG | awk '{print $9}')
# Parse YYYYMMDDHHmmSS format
EXPIRY_TS=$(date -d "${EXPIRY:0:8} ${EXPIRY:8:2}:${EXPIRY:10:2}:${EXPIRY:12:2}" +%s 2>/dev/null)
NOW_TS=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_TS - NOW_TS) / 86400 ))
if [ "$DAYS_LEFT" -lt 7 ]; then
echo "{\"dnssec\": \"warning\", \"rrsig_expires_days\": $DAYS_LEFT}"
exit 1
fi
echo "{\"dnssec\": \"ok\", \"rrsig_expires_days\": $DAYS_LEFT}"
Expose this via a simple HTTP server and monitor it with Vigilmon on a 1-hour check interval.
Also add an external DNSSEC validation check by monitoring a DNS query with DNSSEC validation enabled — some monitoring services support this natively.
Step 5: Zone File Validity Heartbeat
Zone file errors (syntax errors, expired SOA, invalid records) cause BIND9 to reject the zone on reload. If you're using automated zone management or DDNS, a bad update can silently remove a zone from service.
Add a zone validity check cron job:
#!/bin/bash
# /etc/cron.d/bind9-zone-check
*/15 * * * * root /usr/local/bin/check-all-zones.sh
# /usr/local/bin/check-all-zones.sh
ERRORS=0
for ZONE_FILE in /etc/bind/zones/*.db; do
if ! named-checkzone $(basename $ZONE_FILE .db) $ZONE_FILE > /dev/null 2>&1; then
echo "Zone file error: $ZONE_FILE" >&2
ERRORS=$((ERRORS + 1))
fi
done
if [ $ERRORS -eq 0 ]; then
curl -s https://vigilmon.online/heartbeat/your-zone-check-id
fi
Configure the Vigilmon heartbeat with a 30-minute interval (twice the cron frequency gives one failure tolerance before alerting).
Step 6: Monitor Query Rate and NXDOMAIN Rate
High NXDOMAIN rates can indicate DNS-based DDoS amplification attempts or misconfigured clients hammering your server. BIND9 logs query statistics — monitor them with a heartbeat that fails when rates spike:
Enable BIND9 statistics:
# /etc/bind/named.conf.options
statistics-channels {
inet 127.0.0.1 port 8080 allow { 127.0.0.1; };
};
Then monitor the statistics endpoint:
- Click Add Monitor → HTTP / HTTPS.
- URL:
http://localhost:8080/xml/v3/server. - Check interval:
5 minutes. - Expected status:
200. - Click Save.
This confirms the statistics service is running. For rate alerting, add a script that parses NXDOMAIN counts and compares to a threshold:
#!/bin/bash
# /usr/local/bin/bind9-nxdomain-check.sh
NXDOMAIN=$(curl -s http://localhost:8080/xml/v3/server | \
grep -oP 'nxdomain[^>]*>\K[0-9]+' | head -1)
THRESHOLD=1000
if [ "$NXDOMAIN" -gt "$THRESHOLD" ]; then
echo "{\"status\": \"warning\", \"nxdomain_count\": $NXDOMAIN}"
exit 1
fi
echo "{\"status\": \"ok\", \"nxdomain_count\": $NXDOMAIN}"
Step 7: Monitor the Recursive Resolver
If BIND9 is running as a recursive resolver (caching nameserver) in addition to or instead of an authoritative server, add a check that confirms it can recursively resolve external names:
#!/bin/bash
# /usr/local/bin/recursive-health.sh
# Check that the recursive resolver can reach the internet
if dig @localhost +time=5 +tries=1 A vigilmon.online > /dev/null 2>&1; then
echo -e 'HTTP/1.1 200 OK\r\n\r\n{"recursive": "ok"}'
else
echo -e 'HTTP/1.1 503 Service Unavailable\r\n\r\n{"recursive": "failed"}'
fi
Monitor this endpoint. A failure here means your recursive resolver can't reach root nameservers or has outbound UDP blocked.
Step 8: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add Slack, email, or PagerDuty.
- Recommended thresholds:
| Monitor | Failures before alert | Urgency | |---|---|---| | DNS query response | 1 | Critical | | TCP port 53 | 2 | High | | RNDC interface | 2 | Medium | | DNSSEC validity | 1 | High | | Zone file validity | 1 | High | | NXDOMAIN rate | 1 | Medium | | Recursive resolver | 1 | Critical |
DNS failures cascade instantly to all dependent services — use single-failure alerting for query response monitors.
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| DNS query response | UDP/53 DNS check | named crash, zone load failure |
| TCP port 53 | TCP/53 | Zone transfer blocked |
| RNDC interface | Local health endpoint | Control channel broken |
| DNSSEC validity | RRSIG expiry check | Signing key rotation failure |
| Zone file validity | Cron heartbeat | Syntax errors, invalid records |
| NXDOMAIN rate | Statistics endpoint | DDoS amplification, misconfig |
| Recursive resolver | External resolution | Outbound DNS blocked |
BIND9's role in your infrastructure means that when it fails, everything fails — silently and immediately. With Vigilmon probing DNS responses from outside your network, you'll detect service degradation in seconds rather than discovering it when users report that your website "just doesn't load."