[PR #3491] DNSTAP logging support #3887

Open
opened 2026-03-16 12:08:07 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/hickory-dns/hickory-dns/pull/3491
Author: @jpds
Created: 3/10/2026
Status: 🔄 Open

Base: mainHead: feature/dnstap-support


📝 Commits (10+)

  • ded72f4 Add DNSTAP protobuf schema and build infrastructure
  • 0c38ab2 Implement Frame Streams protocol client for DNSTAP transport
  • 17a3558 Add DNSTAP protobuf message builder
  • 9acc750 Add DNSTAP client with async channel-based message sending
  • 2d212bc Integrate DNSTAP client into server request/response pipeline
  • b46c6ed Add DNSTAP integration tests
  • 7b00221 Add per-message-type DNSTAP configuration options
  • 5b5d867 Add DNSTAP documentation to example config, README, and rustdoc
  • e174e28 Add send_identity/send_version flags for DNSTAP
  • 110b6a3 Fix clippy errors in DNSTAP implementation

📊 Changes

28 files changed (+2892 additions, -42 deletions)

View changed files

📝 Cargo.lock (+215 -5)
📝 Cargo.toml (+7 -0)
📝 bin/Cargo.toml (+3 -1)
📝 bin/src/config/mod.rs (+125 -0)
📝 bin/src/hickory-dns.rs (+28 -16)
📝 bin/src/lib.rs (+47 -0)
crates/dnstap/Cargo.toml (+36 -0)
crates/dnstap/proto/dnstap.proto (+343 -0)
crates/dnstap/src/client.rs (+358 -0)
crates/dnstap/src/dnstap_message.rs (+261 -0)
crates/dnstap/src/framestream.rs (+200 -0)
crates/dnstap/src/layer.rs (+267 -0)
crates/dnstap/src/lib.rs (+78 -0)
crates/dnstap/src/proto.rs (+509 -0)
crates/dnstap/tests/generate_dnstap.rs (+48 -0)
📝 crates/server/Cargo.toml (+2 -0)
📝 crates/server/README.md (+2 -0)
📝 crates/server/src/lib.rs (+2 -0)
📝 crates/server/src/server/h2_handler.rs (+1 -1)
📝 crates/server/src/server/h3_handler.rs (+1 -1)

...and 8 more files

📄 Description

This PR implements DNSTAP support for structured DNS event logging for Hickory, gated behind a new dnstap Cargo feature flag.

It includes a vendored dnstap.proto schema with prost-build code generation, a Frame Streams protocol client for framing and transport, a protobuf message builder that captures query/response wire bytes, and a DNSTAP-client with automatic reconnection (TCP and Unix socket endpoints are supported as connection types).

The client is integrated into all server protocol handlers (UDP, TCP, DoH, DoH3, DoQ) and supports per-message-type enable flags for AUTH, CLIENT, and RESOLVER query/response events. Configuration is exposed via a new [dnstap] TOML section, end-to-end integration tests verify correct frame delivery against a mock collector.

The documentation has been updated in the README and example config.

The code was generated with the assistance of Claude, however - I have validated that the functionality works correctly by incorporating this into my existing nixpkgs integration test for Vector+DNSTAP here: https://github.com/NixOS/nixpkgs/compare/master...jpds:nixpkgs:nixos-tests-vector-dnstap-hickory and ensuring that the output which ends up in the ClickHouse database matches what Knot implements as well:

dnsclient: must succeed: dig @unbound www.hickory-dns.org
hickory # [   73.021227] hickory-dns[927]: 2026-03-10T20:29:09.267565Z  INFO hickory_server::server: request:43055 src:udp://192.168.1.5#20775 QUERY qflags:RD response:NoError rr:1/0/1 rflags:RD,AA
hickory # [   73.023387] hickory-dns[927]: 2026-03-10T20:29:09.267728Z  INFO hickory_server::server: query:www.hickory-dns.org.:A:IN
dnsclient: (finished: must succeed: dig @unbound www.hickory-dns.org, in 0.10 seconds)
...
clickhouse: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep -i 'hickory-dns 0.26'
clickhouse: (finished: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep -i 'hickory-dns 0.26', in 0.17 seconds)
clickhouse: 2026-03-10 20:29:09.267739  Message AuthResponse    \N      {"fullRcode":0,"header":{"aa":false,"ad":false,"anCount":0,"arCount":1,"cd":false,"id":43055,"nsCount":0,"opcode":0,"qdCount":1,"qr":0,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.hickory-dns.org.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"}        0.0.0.0 {"answers":[{"class":"IN","domainName":"www.hickory-dns.org.","rData":"127.0.0.1","recordType":"A","recordTypeId":1,"ttl":86400}],"fullRcode":0,"header":{"aa":true,"ad":false,"anCount":1,"arCount":1,"cd":false,"id":43055,"nsCount":0,"opcode":0,"qdCount":1,"qr":1,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.hickory-dns.org.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"}        53      hickory hickory-dns 0.26.0-alpha.1      INET    UDP     192.168.1.5     20775

clickhouse: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep 'Knot DNS 3.5.3'
clickhouse: (finished: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep 'Knot DNS 3.5.3', in 1.30 seconds)
clickhouse: 2026-03-10 20:29:09.093231  Message AuthResponse    \N      \N      192.168.1.4     {"answers":[{"class":"IN","domainName":"www.example.com.","rData":"192.0.2.1","recordType":"A","recordTypeId":1,"ttl":3600}],"fullRcode":0,"header":{"aa":true,"ad":false,"anCount":1,"arCount":1,"cd":false,"id":23748,"nsCount":0,"opcode":0,"qdCount":1,"qr":1,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.example.com.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"} 53      knot    Knot DNS 3.5.3  INET    UDP     192.168.1.5     56233

Fixes: #11


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/hickory-dns/hickory-dns/pull/3491 **Author:** [@jpds](https://github.com/jpds) **Created:** 3/10/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feature/dnstap-support` --- ### 📝 Commits (10+) - [`ded72f4`](https://github.com/hickory-dns/hickory-dns/commit/ded72f4f190c811f12aff2d988d587ab7c66e1c3) Add DNSTAP protobuf schema and build infrastructure - [`0c38ab2`](https://github.com/hickory-dns/hickory-dns/commit/0c38ab230919d51ccc0e1531223d001f4f34bfb3) Implement Frame Streams protocol client for DNSTAP transport - [`17a3558`](https://github.com/hickory-dns/hickory-dns/commit/17a3558853c2d473f0a40e2c02d02ed39e9f1ab2) Add DNSTAP protobuf message builder - [`9acc750`](https://github.com/hickory-dns/hickory-dns/commit/9acc7500e3225edf47d9aa65a196d9ccdc2835db) Add DNSTAP client with async channel-based message sending - [`2d212bc`](https://github.com/hickory-dns/hickory-dns/commit/2d212bc4e480e7f859b2f46a25e65b9769f6fa18) Integrate DNSTAP client into server request/response pipeline - [`b46c6ed`](https://github.com/hickory-dns/hickory-dns/commit/b46c6ed4d53df1b8ccef86d9f9c21dbe23e23fd4) Add DNSTAP integration tests - [`7b00221`](https://github.com/hickory-dns/hickory-dns/commit/7b002211f3744929d15d1c3639b1e5271422f823) Add per-message-type DNSTAP configuration options - [`5b5d867`](https://github.com/hickory-dns/hickory-dns/commit/5b5d867b1773282d6577952c31d9a4e51c84b3a7) Add DNSTAP documentation to example config, README, and rustdoc - [`e174e28`](https://github.com/hickory-dns/hickory-dns/commit/e174e28d57b29147a6710b4ac2fedb1cc9876990) Add send_identity/send_version flags for DNSTAP - [`110b6a3`](https://github.com/hickory-dns/hickory-dns/commit/110b6a305b6d4f969cbb0278db5a60f64ea7f197) Fix clippy errors in DNSTAP implementation ### 📊 Changes **28 files changed** (+2892 additions, -42 deletions) <details> <summary>View changed files</summary> 📝 `Cargo.lock` (+215 -5) 📝 `Cargo.toml` (+7 -0) 📝 `bin/Cargo.toml` (+3 -1) 📝 `bin/src/config/mod.rs` (+125 -0) 📝 `bin/src/hickory-dns.rs` (+28 -16) 📝 `bin/src/lib.rs` (+47 -0) ➕ `crates/dnstap/Cargo.toml` (+36 -0) ➕ `crates/dnstap/proto/dnstap.proto` (+343 -0) ➕ `crates/dnstap/src/client.rs` (+358 -0) ➕ `crates/dnstap/src/dnstap_message.rs` (+261 -0) ➕ `crates/dnstap/src/framestream.rs` (+200 -0) ➕ `crates/dnstap/src/layer.rs` (+267 -0) ➕ `crates/dnstap/src/lib.rs` (+78 -0) ➕ `crates/dnstap/src/proto.rs` (+509 -0) ➕ `crates/dnstap/tests/generate_dnstap.rs` (+48 -0) 📝 `crates/server/Cargo.toml` (+2 -0) 📝 `crates/server/README.md` (+2 -0) 📝 `crates/server/src/lib.rs` (+2 -0) 📝 `crates/server/src/server/h2_handler.rs` (+1 -1) 📝 `crates/server/src/server/h3_handler.rs` (+1 -1) _...and 8 more files_ </details> ### 📄 Description This PR implements [DNSTAP](https://dnstap.info/) support for structured DNS event logging for Hickory, gated behind a new `dnstap` Cargo feature flag. It includes a vendored `dnstap.proto` schema with prost-build code generation, a Frame Streams protocol client for framing and transport, a protobuf message builder that captures query/response wire bytes, and a DNSTAP-client with automatic reconnection (TCP and Unix socket endpoints are supported as connection types). The client is integrated into all server protocol handlers (UDP, TCP, DoH, DoH3, DoQ) and supports per-message-type enable flags for AUTH, CLIENT, and RESOLVER query/response events. Configuration is exposed via a new `[dnstap]` TOML section, end-to-end integration tests verify correct frame delivery against a mock collector. The documentation has been updated in the README and example config. The code was generated with the assistance of Claude, however - I have validated that the functionality works correctly by incorporating this into my existing `nixpkgs` integration test for Vector+DNSTAP here: https://github.com/NixOS/nixpkgs/compare/master...jpds:nixpkgs:nixos-tests-vector-dnstap-hickory and ensuring that the output which ends up in the ClickHouse database matches what Knot implements as well: ```console dnsclient: must succeed: dig @unbound www.hickory-dns.org hickory # [ 73.021227] hickory-dns[927]: 2026-03-10T20:29:09.267565Z INFO hickory_server::server: request:43055 src:udp://192.168.1.5#20775 QUERY qflags:RD response:NoError rr:1/0/1 rflags:RD,AA hickory # [ 73.023387] hickory-dns[927]: 2026-03-10T20:29:09.267728Z INFO hickory_server::server: query:www.hickory-dns.org.:A:IN dnsclient: (finished: must succeed: dig @unbound www.hickory-dns.org, in 0.10 seconds) ... clickhouse: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep -i 'hickory-dns 0.26' clickhouse: (finished: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep -i 'hickory-dns 0.26', in 0.17 seconds) clickhouse: 2026-03-10 20:29:09.267739 Message AuthResponse \N {"fullRcode":0,"header":{"aa":false,"ad":false,"anCount":0,"arCount":1,"cd":false,"id":43055,"nsCount":0,"opcode":0,"qdCount":1,"qr":0,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.hickory-dns.org.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"} 0.0.0.0 {"answers":[{"class":"IN","domainName":"www.hickory-dns.org.","rData":"127.0.0.1","recordType":"A","recordTypeId":1,"ttl":86400}],"fullRcode":0,"header":{"aa":true,"ad":false,"anCount":1,"arCount":1,"cd":false,"id":43055,"nsCount":0,"opcode":0,"qdCount":1,"qr":1,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.hickory-dns.org.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"} 53 hickory hickory-dns 0.26.0-alpha.1 INET UDP 192.168.1.5 20775 clickhouse: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep 'Knot DNS 3.5.3' clickhouse: (finished: waiting for success: cat /nix/store/y8j8h43lqsvbzqrhdffzs38d1i6r0p7v-select-auth-response.sql | clickhouse-client | grep 'Knot DNS 3.5.3', in 1.30 seconds) clickhouse: 2026-03-10 20:29:09.093231 Message AuthResponse \N \N 192.168.1.4 {"answers":[{"class":"IN","domainName":"www.example.com.","rData":"192.0.2.1","recordType":"A","recordTypeId":1,"ttl":3600}],"fullRcode":0,"header":{"aa":true,"ad":false,"anCount":1,"arCount":1,"cd":false,"id":23748,"nsCount":0,"opcode":0,"qdCount":1,"qr":1,"ra":false,"rcode":0,"rd":true,"tc":false},"opt":{"do":true,"ednsVersion":0,"extendedRcode":0,"udpPayloadSize":1232},"question":[{"class":"IN","domainName":"www.example.com.","questionType":"A","questionTypeId":1}],"rcodeName":"NoError"} 53 knot Knot DNS 3.5.3 INET UDP 192.168.1.5 56233 ``` Fixes: #11 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#3887
No description provided.