0. Prerequisites
- Zabbix Server 7.0+
- Zabbix Agent (classic or agent2) running on the DNS host
- Utilities:
curland one of the XML tools:xmllint(from libxml2) orxmlstarlet - On Alma/RHEL 9/10:
dnf install -y curl libxml2 xmlstarlet - On Debian/Ubuntu:
apt-get install -y curl libxml2-utils xmlstarlet
On AlmaLinux 10, the
xml2package is often missing — usexmllintorxmlstarletinstead.
1. Enable statistics in BIND and secure access
Add this configuration in named.conf (outside of any view, or inside the specific view if you use them):
// Enable statistics over HTTP (XML/JSON, depending on BIND version)
statistics-channels {
inet 127.0.0.1 port 8053 allow { 127.0.0.1; <IP_ZABBIX_SERVER>; };
};
// Recommendations for an authoritative NS
options {
directory "/var/named"; // or /var/cache/bind on Debian
recursion no; // on authoritative servers
allow-query { any; }; // or your ACL
// … your other options …
};
Then check and reload:
named-checkconf -z systemctl reload named # or named-chroot / named-pkcs11 etc., depending on your package
Verify that statistics are working:
curl -fsS http://127.0.0.1:8053/ | head
If BIND is behind a reverse proxy and you receive a
307 Temporary Redirect, disable redirection for127.0.0.1or access the port directly (8053).
2. Option A (quick): use a ready-made “BIND9 statistics by HTTP” template
- Import the community template Template Bind9-stat by HTTP (Zabbix 7.0) in the Zabbix UI (this template reads statistics via HTTP).
- On the host running BIND:
- Ensure
curland eitherxmllintorxmlstarletare installed. - In
zabbix_agentd.conf, remove deprecated lines such as:# EnableRemoteCommands=1 <-- deprecatedAnd add the permission only for the specific key:AllowKey=system.run[*] - Restart the agent:
systemctl restart zabbix-agent
- Ensure
- Link the template to your BIND host. If the template expects a macro for the statistics URL, set it to
http://127.0.0.1:8053/. - In the frontend (Latest data → filter by host), you should see counters per query types (A / AAAA / NS / …).
If the import fails, confirm you selected the version for Zabbix 7.0 (YAML export format changed in 7.0).
3. Option B (minimal custom): 3 metrics via UserParameter
This is a backup — a custom minimalist approach using xmllint / xmlstarlet. We’ll write a small parsing script and agent keys.
3.1 Parsing script
Create /usr/local/bin/bindstat.sh:
#!/bin/bash
set -euo pipefail
# URL of BIND statistics interface
URL="${BINDSTAT_URL:-http://127.0.0.1:8053/}"
WHAT="${1:-queries-in}" # queries-in | queries-out | counter
QTYPE="${2:-A}" # e.g. A, AAAA, MX …
DATA="$(curl -fsS "$URL")"
extract_rdtype() {
local dir="$1" q="$2"
if command -v xmllint >/dev/null; then
xmllint --xpath "string(//${dir}/rdtype[@name='${q}'])" - 2>/dev/null || true
elif command -v xmlstarlet >/dev/null; then
xmlstarlet sel -t -v "//${dir}/rdtype[@name='${q}']" 2>/dev/null || true
else
grep -oP "<${dir}[^>]*>.*?<rdtype name=[\"']${q}[\"']>([0-9]+)</rdtype>.*?</${dir}>" -m1 \
| grep -oP "(?<=<rdtype name=[\"']${q}[\"']>)[0-9]+"
fi
}
case "$WHAT" in
queries-in)
echo "$DATA" | extract_rdtype "queries-in" "$QTYPE"
;;
queries-out)
echo "$DATA" | extract_rdtype "queries-out" "$QTYPE"
;;
counter)
# Example: counter server/nsstat/Requestv4 (custom usage)
# echo "$DATA" | xmllint --xpath 'string(//server/counters[@type="nsstat"]/counter[@name="Requestv4"])' -
;;
*)
echo "Unsupported" >&2
exit 1
;;
esac
Make it executable:
chmod +x /usr/local/bin/bindstat.sh
3.2 Agent UserParameter configuration
In /etc/zabbix/zabbix_agentd.d/bind.conf:
# Note: Ensure in zabbix_agentd.conf you have AllowKey=system.run[*] # Incoming queries for QTYPE (A, AAAA, MX…) UserParameter=bind.queries.in[*],/usr/local/bin/bindstat.sh queries-in "$1" # Outgoing (recursive / forwarding) queries for QTYPE — usually 0 on authoritative UserParameter=bind.queries.out[*],/usr/local/bin/bindstat.sh queries-out "$1"
Then restart the agent:
systemctl restart zabbix-agent
Test from the Zabbix server:
zabbix_get -s <IP_DNS> -k "bind.queries.in[A]"
Create in Zabbix your own “mini-template” with two items:
bind.queries.in[A](Type: Zabbix agent, value type: Numeric (unsigned), update: 60s)bind.queries.in[AAAA]… and so on (or use LLD for query types)
Then add simple triggers, e.g. “no queries in 10 min” or “abnormally many NXDOMAIN”.
4. Security recommendations
- Keep
statistics-channelsbound to127.0.0.1and query it locally via the agent. - If remote access is needed — open the port only to the Zabbix Server’s IP via firewall, or place an Nginx reverse proxy with basic authentication.
- SELinux:
- For zone directories (if you’re also monitoring slave/master files) use the
named_zone_tcontext. - For statistics itself, typically no additional SELinux config is needed.
- For zone directories (if you’re also monitoring slave/master files) use the
5. Common errors and how to catch them
- 404 or 307 Temporary Redirect — you’re hitting the wrong endpoint (due to reverse proxy or prefix). Verify
curl http://127.0.0.1:8053/. - xml2: command not found — install
libxml2(givesxmllint) orxmlstarlet, and switch to Option B or updated template. - No data in Latest data — check
journalctl -u zabbix-agent -n 100, or test viazabbix_get.
6. What to monitor exactly
- Queries in, by QTYPE: A / AAAA / MX / NS / SOA — illustrates traffic behavior
- SERVFAIL / FORMERR / NXDOMAIN (if you pull counters) — resolution errors
- Zone transfers (IXFR / AXFR counters) — for authoritative clusters
- Recursive / forwarding responses — applicable to recursive servers
Summary
The easiest way is to enable statistics-channels in BIND, import the ready-made Bind9 statistics by HTTP template for Zabbix 7.0, and ensure curl + xmllint/xmlstarlet are available on your server. If you prefer control and minimalism, then 2–3 UserParameter metrics with a small parsing script will give you the essential graphs in about 10 minutes.
