BIND’s detailed logging is surprisingly flexible, letting you dial in exactly what information you want, from DNS query details down to the packet level, without necessarily grinding your server to a halt.

Let’s see it in action. Imagine a request for www.example.com. With BIND’s logging configured, you can watch it traverse the server:

# dig www.example.com @127.0.0.1

# tail -f /var/log/named/queries.log
...
2023-10-27 10:00:01.123456 client 192.168.1.10#54321: query: www.example.com IN A + (example.com)
2023-10-27 10:00:01.123457 default_resolver: info: received query for www.example.com IN A from 192.168.1.10#54321
2023-10-27 10:00:01.123458 default_resolver: info: sending response for www.example.com IN A to 192.168.1.10#54321
...

This is just the tip of the iceberg. BIND’s logging is controlled via the logging stanza in named.conf. It’s a powerful system that allows you to define channels (where the logs go) and categorys (what gets logged).

The channel directive specifies the destination for log messages. You can send them to a file, to syslog, or even to the console. A common setup involves sending specific categories to different files for easier analysis.

logging {
    channel queries_log {
        file "/var/log/named/queries.log" versions 3 size 5m;
        severity info;
        print-time yes;
        print-severity yes;
        print-category yes;
    };

    channel general_log {
        file "/var/log/named/general.log" versions 3 size 5m;
        severity dynamic; // Can be adjusted at runtime
        print-time yes;
    };

    category queries { queries_log; };
    category default { general_log; };
};

Here, queries_log is set up to capture messages of info severity and above, rotating old logs after 3 versions or when they reach 5MB. general_log captures dynamic severity, meaning you can change its level without restarting BIND.

The category directive is where you map specific BIND operations to your defined channels. BIND has a rich set of categories, each targeting a different aspect of its operation:

  • queries: Logs every incoming query and outgoing response. This is your bread and butter for tracking DNS traffic.
  • default: Catches anything not matched by other categories. Good for general server status.
  • resolver: Logs the server’s behavior as a resolver, including cache hits/misses and upstream queries.
  • network: Details network socket operations.
  • dnssec: For logging DNSSEC-related events.
  • packet: Logs the raw DNS packets. Use with extreme caution; this can generate massive amounts of data.

You can specify multiple channels for a single category, or multiple categories for a single channel. The severity level is crucial: critical, error, warning, notice, info, debug, and all. The dynamic severity level allows you to adjust the logging level for a category on the fly using rndc log.

For example, to increase the logging level for the resolver category to debug without restarting BIND:

rndc log resolver debug

And to set it back to info:

rndc log resolver info

The packet category is where things get truly granular. Enabling packet logging for a specific channel will log the raw UDP/TCP packets BIND sends and receives. This is invaluable for debugging complex network issues or understanding exactly what BIND is doing at the wire level. However, it’s also the fastest way to fill up your disk.

logging {
    channel packet_debug {
        file "/var/log/named/packets.log" versions 1 size 10m;
        severity debug; // Must be debug or higher to see packet data
        print-time yes;
        print-category yes;
        print-severity yes;
    };
    category packet { packet_debug; };
};

When you’re troubleshooting a specific issue, you might temporarily redirect queries and resolver to a packet logging channel. Once done, remember to switch them back to a less verbose channel and reduce the severity.

One of the most powerful, yet often overlooked, aspects of BIND logging is the ability to use syslog as a channel destination. This allows you to integrate BIND’s logs with your existing syslog infrastructure, centralizing your logging and leveraging syslog’s filtering and forwarding capabilities.

logging {
    channel syslog_queries {
        syslog daemon; // Or local0, local1, etc.
        severity info;
        print-time yes;
        print-severity yes;
        print-category yes;
    };
    category queries { syslog_queries; };
};

This sends all queries category messages to the daemon facility in syslogd. You’d then configure syslogd (or rsyslog/syslog-ng) to handle these messages, perhaps writing them to a dedicated file or forwarding them to a central log server.

The flexibility extends to print-xyz options. You can control whether BIND prepends the timestamp, severity level, or category name to each log message. This is essential for making logs readable and easily parsable by log analysis tools.

This granular control means you can tailor your logging to your specific needs, whether it’s deep packet inspection for a tricky network problem or just a high-level overview of DNS traffic.

After configuring detailed logging, the next hurdle is often parsing and analyzing the sheer volume of data produced, especially when debugging at the debug or packet level.

Want structured learning?

Take the full Bind course →