COREDNS-DNSTAP(7)
π COREDNS-DNSTAP π
okay so bestie, you're in the CoreDNS Plugins section 7 and this is COREDNS-DNSTAP(7) β the dnstap page. buckle up π
β¨ NAME β¨
dnstap β literally just enables logging to dnstap. that's the whole vibe.
πΈ DESCRIPTION πΈ
so dnstap is this flexible, structured binary log format for DNS software β go look at https://dnstap.info for the lore. with this plugin you make CoreDNS output dnstap logging. no cap. π₯
every message gets sent to the socket as soon as it comes in, and the dnstap plugin keeps a buffer of 10000 messages. above that number? dnstap messages will be dropped π and yes, that drop gets logged. it's giving "we tried".
π¦ SYNTAX π¦
π OUTGOING CONNECTIONS (CONNECT TO SINK)
dnstap SOCKET [full] [writebuffer] [queue] {
[identity IDENTITY]
[version VERSION]
[extra EXTRA]
[skipverify]
}
SOCKETβ this is the socket (path) you hand over to the dnstap command line tool.fullβ include the wire-format DNS message. yes, the whole thing πwritebufferβ sets the TCP write buffer multiplier in MiB. valid range:[1, 1024].queueβ sets the queue multiplier, applied to 10,000 messages. valid range:[1, 4096]. so it multiplies, periodt.IDENTITYβ override the identity of the server. defaults to the hostname (so it just uses whatever the host is called, cute).VERSIONβ override the version field. defaults to the CoreDNS version.EXTRAβ define the "extra" field in the dnstap payload. the metadata replacement is available right here (that's the../metadata/thing).skipverifyβ skip TLS verification during the connection. default is to be secure π (like, stay safe out there)
π©· INCOMING CONNECTIONS (ACCEPT FROM SINKS)
dnstap listen SOCKET [full] {
[identity IDENTITY]
[version VERSION]
[extra EXTRA]
[tls CERT KEY [CA]]
[skipverify]
}
listenβ this little keyword is saying "hi yes this is a listening socket that accepts incoming connections from dnstap sinks". main character energy fr fr.SOCKETβ the socket address to listen on. liketcp://127.0.0.1:6000orunix:///tmp/dnstap.sock.fullβ include the wire-format DNS message.IDENTITYβ override the identity of the server. defaults to the hostname.VERSIONβ override the version field. defaults to the CoreDNS version.EXTRAβ define the "extra" field in the dnstap payload. metadata replacement is available here too (../metadata/).tls CERT KEY [CA]β enable TLS for the listener.CERTandKEYare paths to the server certificate and key files. the optionalCAis the path to the CA certificate for client verification.skipverifyβ skip client certificate verification. default is to verify client certificates. it's equivalent to theCAoption above being unspecified.
β οΈ note bestie: incoming connections use unbuffered channels to broadcast events. if a connected sink becomes slow or disconnected, messages are dropped for that sink only, and the connection is closed. so it's not a whole-server situation, it's a that-one-sink situation π
π EXAMPLES π
log info about client requests and responses to /tmp/dnstap.sock:
dnstap /tmp/dnstap.sock
log info about client requests and responses with a custom TCP write buffer (1024 MiB) and queue capacity (2048 x 10000):
dnstap /tmp/dnstap.sock full 1024 2048
log info including the wire-format DNS message about client requests and responses to /tmp/dnstap.sock:
dnstap unix:///tmp/dnstap.sock full
log to a remote endpoint:
dnstap tcp://127.0.0.1:6000 full
log to a remote endpoint by FQDN:
dnstap tcp://example.com:6000 full
log to a socket while overriding the default identity and version:
dnstap /tmp/dnstap.sock {
identity my-dns-server1
version MyDNSServer-1.2.3
}
log to a socket and customize the "extra" field in the dnstap payload. you may use metadata provided by other plugins in the extra field π«Ά
forward . 8.8.8.8
metadata
dnstap /tmp/dnstap.sock {
extra "upstream: {/forward/upstream}"
}
log to a remote TLS endpoint:
dnstap tls://127.0.0.1:6000 full {
skipverify
}
listen for incoming dnstap sink connections on a Unix socket:
dnstap listen /tmp/dnstap.sock full
listen for incoming dnstap sink connections on TCP:
dnstap listen tcp://127.0.0.1:6000 full
listen for incoming dnstap sink connections on TLS with mTLS client authentication:
dnstap listen tls://127.0.0.1:6000 full {
tls /path/to/server-cert.pem /path/to/server-key.pem /path/to/ca.pem
}
listen for incoming dnstap sink connections on TLS without client certificate verification:
dnstap listen tls://127.0.0.1:6000 full {
tls /path/to/server-cert.pem /path/to/server-key.pem
skipverify
}
you can use dnstap more than once to define multiple taps π the following logs info including the wire-format DNS message about client requests and responses to /tmp/dnstap.sock, and also sends client requests and responses without wire-format DNS messages to a remote FQDN:
dnstap /tmp/dnstap.sock full
dnstap tcp://example.com:6000
and yes you can absolutely combine outgoing connections with incoming listeners:
dnstap tcp://remote-collector.example.com:6000 full
dnstap listen tcp://127.0.0.1:6001 full
π§ COMMAND LINE TOOL π§
dnstap has a command line tool that can be used to inspect the logging. it lives on GitHub at https://github.com/dnstap/golang-dnstap. it's written in Go. slay.
the following command listens on the given socket and decodes messages to stdout:
$ dnstap -u /tmp/dnstap.sock
the following command listens on the given socket and saves message payloads to a binary dnstap-format log file:
$ dnstap -u /tmp/dnstap.sock -w /tmp/test.dnstap
listen for dnstap messages on port 6000:
$ dnstap -l 127.0.0.1:6000
β USING DNSTAP IN YOUR PLUGIN β
in your setup function, collect and store a list of all dnstap plugins loaded in the config:
x := ExamplePlugin{}
c.OnStartup(func() error {
if taph := dnsserver.GetConfig(c).Handler("dnstap"); taph != nil {
for tapPlugin, ok := taph.(*dnstap.Dnstap); ok; tapPlugin, ok = tapPlugin.Next.(*dnstap.Dnstap) {
x.tapPlugins = append(x.tapPlugins, tapPlugin)
}
}
return nil
})
and then in your plugin:
import (
"github.com/coredns/coredns/plugin/dnstap/msg"
"github.com/coredns/coredns/request"
tap "github.com/dnstap/golang-dnstap"
)
func (x ExamplePlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
for _, tapPlugin := range x.tapPlugins {
q := new(msg.Msg)
msg.SetQueryTime(q, time.Now())
msg.SetQueryAddress(q, w.RemoteAddr())
if tapPlugin.IncludeRawMessage {
buf, _ := r.Pack() // r has been seen packed/unpacked before, this should not fail
q.QueryMessage = buf
}
msg.SetType(q, tap.Message_CLIENT_QUERY)
// if no metadata interpretation is needed, just send the message
tapPlugin.TapMessage(q)
// OR: to interpret the metadata in "extra" field, give more context info
tapPlugin.TapMessageWithMetadata(ctx, q, request.Request{W: w, Req: query})
}
// ...
}
π₯ SEE ALSO π₯
the website https://dnstap.info has info on the dnstap protocol. also the forward plugin's dnstap.go uses dnstap to tap messages sent to an upstream β iykyk π
π«Ά and that's the whole page bestie, no crumbs left. this was COREDNS-DNSTAP(7) from the CoreDNS gang, dated October 2026. go forth and tap those messages πβ¨π
π¦ where this page comes from
- opensuse-leap 16.0: coredns-extras 1.15.0-bp160.1.1 Β· Apache-2.0 AND MPL-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms