plugin/dnstap: feature: added incoming connection support (#8086)

* plugin/dnstap: added incoming connection support feature to dnstap plugin

Signed-off-by: Endre Szabo <git@end.re>

* fixed problems pointed out by ci linter

Signed-off-by: Endre Szabo <git@end.re>

---------

Signed-off-by: Endre Szabo <git@end.re>
This commit is contained in:
Endre Szabo
2026-05-20 04:23:53 +02:00
committed by GitHub
parent f4f767fb4e
commit ee7ff82cf5
7 changed files with 728 additions and 70 deletions

View File

@@ -44,6 +44,17 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) {
endpoint := args[0]
// Check if this is a 'listen' directive for incoming connections
isListener := endpoint == "listen"
if isListener {
if len(args) < 2 {
return nil, c.Errf("dnstap listen requires an endpoint argument")
}
endpoint = args[1]
// Shift args for listener mode
args = args[1:]
}
if len(args) >= 3 {
tcpWriteBuf := args[2]
v, err := strconv.Atoi(tcpWriteBuf)
@@ -68,26 +79,52 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) {
}
var dio *dio
if strings.HasPrefix(endpoint, "tls://") {
// remote network endpoint
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
var lstnr *listener
if isListener {
// Incoming connection listener
if strings.HasPrefix(endpoint, "tls://") {
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
lstnr = newListener("tls", endpointURL.Host)
d.listener = lstnr
} else if strings.HasPrefix(endpoint, "tcp://") {
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
lstnr = newListener("tcp", endpointURL.Host)
d.listener = lstnr
} else {
endpoint = strings.TrimPrefix(endpoint, "unix://")
lstnr = newListener("unix", endpoint)
d.listener = lstnr
}
dio = newIO("tls", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
} else if strings.HasPrefix(endpoint, "tcp://") {
// remote network endpoint
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
dio = newIO("tcp", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
} else {
endpoint = strings.TrimPrefix(endpoint, "unix://")
dio = newIO("unix", endpoint, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
// Outgoing connection
if strings.HasPrefix(endpoint, "tls://") {
// remote network endpoint
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
dio = newIO("tls", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
} else if strings.HasPrefix(endpoint, "tcp://") {
// remote network endpoint
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
dio = newIO("tcp", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
} else {
endpoint = strings.TrimPrefix(endpoint, "unix://")
dio = newIO("unix", endpoint, d.MultipleQueue, d.MultipleTcpWriteBuf)
d.io = dio
}
}
d.IncludeRawMessage = len(args) >= 2 && args[1] == "full"
@@ -100,7 +137,27 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) {
switch c.Val() {
case "skipverify":
{
dio.skipVerify = true
if isListener && lstnr != nil {
lstnr.skipVerify = true
} else if dio != nil {
dio.skipVerify = true
}
}
case "tls":
{
// TLS configuration for listeners: tls <cert> <key> [ca]
if !isListener || lstnr == nil {
return nil, c.Errf("tls directive only valid for listeners")
}
args := c.RemainingArgs()
if len(args) < 2 {
return nil, c.Errf("tls requires cert and key file paths")
}
lstnr.certFile = args[0]
lstnr.keyFile = args[1]
if len(args) >= 3 {
lstnr.caFile = args[2]
}
}
case "identity":
{
@@ -139,19 +196,38 @@ func setup(c *caddy.Controller) error {
for i := range dnstaps {
dnstap := dnstaps[i]
c.OnStartup(func() error {
if err := dnstap.io.(*dio).connect(); err != nil {
log.Errorf("No connection to dnstap endpoint: %s", err)
// Start outgoing connection if configured
if dnstap.io != nil {
if err := dnstap.io.(*dio).connect(); err != nil {
log.Errorf("No connection to dnstap endpoint: %s", err)
}
}
// Start listener if configured
if dnstap.listener != nil {
if err := dnstap.listener.listen(); err != nil {
log.Errorf("Failed to start dnstap listener: %s", err)
}
}
return nil
})
c.OnRestart(func() error {
dnstap.io.(*dio).close()
if dnstap.io != nil {
dnstap.io.(*dio).close()
}
if dnstap.listener != nil {
dnstap.listener.close()
}
return nil
})
c.OnFinalShutdown(func() error {
dnstap.io.(*dio).close()
if dnstap.io != nil {
dnstap.io.(*dio).close()
}
if dnstap.listener != nil {
dnstap.listener.close()
}
return nil
})