dnstap tls support (#5917)

Signed-off-by: dmachard <5562930+dmachard@users.noreply.github.com>
This commit is contained in:
Denis MACHARD 2023-02-21 00:34:48 +01:00 committed by GitHub
parent 66df12d980
commit 83fc3bb5da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 6 deletions

View file

@ -18,6 +18,7 @@ Every message is sent to the socket as soon as it comes in, the *dnstap* plugin
dnstap SOCKET [full] {
[identity IDENTITY]
[version VERSION]
[skipverify]
}
~~~
@ -25,6 +26,7 @@ dnstap SOCKET [full] {
* `full` to include the wire-format DNS message.
* **IDENTITY** to override the identity of the server. Defaults to the hostname.
* **VERSION** to override the version field. Defaults to the CoreDNS version.
* `skipverify` to skip tls verification during connection. Default to be secure
## Examples
@ -61,6 +63,14 @@ dnstap /tmp/dnstap.sock {
}
~~~
Log to a remote TLS endpoint.
~~~ txt
dnstap tls://127.0.0.1:6000 full {
skipverify
}
~~~
You can use _dnstap_ more than once to define multiple taps. The following logs information 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.

View file

@ -1,6 +1,7 @@
package dnstap
import (
"crypto/tls"
"net"
"sync/atomic"
"time"
@ -14,6 +15,8 @@ const (
tcpTimeout = 4 * time.Second
flushTimeout = 1 * time.Second
skipVerify = false // by default, every tls connection is verified to be secure
)
// tapper interface is used in testing to mock the Dnstap method.
@ -31,6 +34,7 @@ type dio struct {
quit chan struct{}
flushTimeout time.Duration
tcpTimeout time.Duration
skipVerify bool
}
// newIO returns a new and initialized pointer to a dio.
@ -42,14 +46,32 @@ func newIO(proto, endpoint string) *dio {
quit: make(chan struct{}),
flushTimeout: flushTimeout,
tcpTimeout: tcpTimeout,
skipVerify: skipVerify,
}
}
func (d *dio) dial() error {
conn, err := net.DialTimeout(d.proto, d.endpoint, d.tcpTimeout)
if err != nil {
return err
var conn net.Conn
var err error
if d.proto == "tls" {
config := &tls.Config{
InsecureSkipVerify: d.skipVerify,
}
dialer := &net.Dialer{
Timeout: d.tcpTimeout,
}
conn, err = tls.DialWithDialer(dialer, "tcp", d.endpoint, config)
if err != nil {
return err
}
} else {
conn, err = net.DialTimeout(d.proto, d.endpoint, d.tcpTimeout)
if err != nil {
return err
}
}
if tcpConn, ok := conn.(*net.TCPConn); ok {
tcpConn.SetWriteBuffer(tcpWriteBufSize)
tcpConn.SetNoDelay(false)

View file

@ -30,17 +30,26 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) {
endpoint = args[0]
if strings.HasPrefix(endpoint, "tcp://") {
var dio *dio
if strings.HasPrefix(endpoint, "tls://") {
// remote network endpoint
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, c.ArgErr()
}
dio := newIO("tcp", endpointURL.Host)
dio = newIO("tls", endpointURL.Host)
d = Dnstap{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 = Dnstap{io: dio}
} else {
endpoint = strings.TrimPrefix(endpoint, "unix://")
dio := newIO("unix", endpoint)
dio = newIO("unix", endpoint)
d = Dnstap{io: dio}
}
@ -52,6 +61,10 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) {
for c.NextBlock() {
switch c.Val() {
case "skipverify":
{
dio.skipVerify = true
}
case "identity":
{
if !c.NextArg() {

View file

@ -44,6 +44,7 @@ func TestConfig(t *testing.T) {
{"dnstap.sock", true, "unix", []byte("NAME"), []byte("VER")},
{"127.0.0.1:6000", false, "tcp", []byte("NAME2"), []byte("VER2")},
}},
{"dnstap tls://127.0.0.1:6000", false, []results{{"127.0.0.1:6000", false, "tls", []byte(hostname), []byte("-")}}},
}
for i, tc := range tests {
c := caddy.NewTestController("dns", tc.in)