aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar peiranliushop <33286233+peiranliushop@users.noreply.github.com> 2019-03-23 05:45:21 -0400
committerGravatar Miek Gieben <miek@miek.nl> 2019-03-23 09:45:20 +0000
commit403d42ce200f3c2074c521e4287728f2b8d2bf0d (patch)
tree3dc24dbdd66299fa85da8bc550034190ed35ae85
parent0e137b23f152c70590e82f0b5985b2faf104c8e0 (diff)
downloadcoredns-403d42ce200f3c2074c521e4287728f2b8d2bf0d.tar.gz
coredns-403d42ce200f3c2074c521e4287728f2b8d2bf0d.tar.zst
coredns-403d42ce200f3c2074c521e4287728f2b8d2bf0d.zip
Support logging to dnstap in forward plugin (#2703)
-rw-r--r--plugin/dnstap/test/helpers.go7
-rw-r--r--plugin/forward/dnstap.go61
-rw-r--r--plugin/forward/dnstap_test.go63
-rw-r--r--plugin/forward/forward.go7
4 files changed, 128 insertions, 10 deletions
diff --git a/plugin/dnstap/test/helpers.go b/plugin/dnstap/test/helpers.go
index 4f71a5a83..5f498d59f 100644
--- a/plugin/dnstap/test/helpers.go
+++ b/plugin/dnstap/test/helpers.go
@@ -1,7 +1,6 @@
package test
import (
- "context"
"net"
"reflect"
@@ -10,12 +9,6 @@ import (
tap "github.com/dnstap/golang-dnstap"
)
-// Context is a message trap.
-type Context struct {
- context.Context
- TrapTapper
-}
-
// TestingData returns the Data matching coredns/test.ResponseWriter.
func TestingData() (d *msg.Builder) {
d = &msg.Builder{
diff --git a/plugin/forward/dnstap.go b/plugin/forward/dnstap.go
new file mode 100644
index 000000000..7866aa39b
--- /dev/null
+++ b/plugin/forward/dnstap.go
@@ -0,0 +1,61 @@
+package forward
+
+import (
+ "context"
+ "time"
+
+ "github.com/coredns/coredns/plugin/dnstap"
+ "github.com/coredns/coredns/plugin/dnstap/msg"
+ "github.com/coredns/coredns/request"
+
+ tap "github.com/dnstap/golang-dnstap"
+ "github.com/miekg/dns"
+)
+
+func toDnstap(ctx context.Context, host string, f *Forward, state request.Request, reply *dns.Msg, start time.Time) error {
+ tapper := dnstap.TapperFromContext(ctx)
+ if tapper == nil {
+ return nil
+ }
+ // Query
+ b := msg.New().Time(start).HostPort(host)
+ opts := f.opts
+ t := ""
+ switch {
+ case opts.forceTCP: // TCP flag has precedence over UDP flag
+ t = "tcp"
+ case opts.preferUDP:
+ t = "udp"
+ default:
+ t = state.Proto()
+ }
+
+ if t == "tcp" {
+ b.SocketProto = tap.SocketProtocol_TCP
+ } else {
+ b.SocketProto = tap.SocketProtocol_UDP
+ }
+
+ if tapper.Pack() {
+ b.Msg(state.Req)
+ }
+ m, err := b.ToOutsideQuery(tap.Message_FORWARDER_QUERY)
+ if err != nil {
+ return err
+ }
+ tapper.TapMessage(m)
+
+ // Response
+ if reply != nil {
+ if tapper.Pack() {
+ b.Msg(reply)
+ }
+ m, err := b.Time(time.Now()).ToOutsideResponse(tap.Message_FORWARDER_RESPONSE)
+ if err != nil {
+ return err
+ }
+ tapper.TapMessage(m)
+ }
+
+ return nil
+}
diff --git a/plugin/forward/dnstap_test.go b/plugin/forward/dnstap_test.go
new file mode 100644
index 000000000..c86ee8c75
--- /dev/null
+++ b/plugin/forward/dnstap_test.go
@@ -0,0 +1,63 @@
+package forward
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/coredns/coredns/plugin/dnstap"
+ "github.com/coredns/coredns/plugin/dnstap/msg"
+ "github.com/coredns/coredns/plugin/dnstap/test"
+ mwtest "github.com/coredns/coredns/plugin/test"
+ "github.com/coredns/coredns/request"
+
+ tap "github.com/dnstap/golang-dnstap"
+ "github.com/miekg/dns"
+)
+
+func testCase(t *testing.T, f *Forward, q, r *dns.Msg, datq, datr *msg.Builder) {
+ tapq, _ := datq.ToOutsideQuery(tap.Message_FORWARDER_QUERY)
+ tapr, _ := datr.ToOutsideResponse(tap.Message_FORWARDER_RESPONSE)
+ tapper := test.TrapTapper{}
+ ctx := dnstap.ContextWithTapper(context.TODO(), &tapper)
+ err := toDnstap(ctx, "10.240.0.1:40212", f,
+ request.Request{W: &mwtest.ResponseWriter{}, Req: q}, r, time.Now())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(tapper.Trap) != 2 {
+ t.Fatalf("Messages: %d", len(tapper.Trap))
+ }
+ if !test.MsgEqual(tapper.Trap[0], tapq) {
+ t.Errorf("Want: %v\nhave: %v", tapq, tapper.Trap[0])
+ }
+ if !test.MsgEqual(tapper.Trap[1], tapr) {
+ t.Errorf("Want: %v\nhave: %v", tapr, tapper.Trap[1])
+ }
+}
+
+func TestDnstap(t *testing.T) {
+ q := mwtest.Case{Qname: "example.org", Qtype: dns.TypeA}.Msg()
+ r := mwtest.Case{
+ Qname: "example.org.", Qtype: dns.TypeA,
+ Answer: []dns.RR{
+ mwtest.A("example.org. 3600 IN A 10.0.0.1"),
+ },
+ }.Msg()
+ tapq, tapr := test.TestingData(), test.TestingData()
+ fu := New()
+ fu.opts.preferUDP = true
+ testCase(t, fu, q, r, tapq, tapr)
+ tapq.SocketProto = tap.SocketProtocol_TCP
+ tapr.SocketProto = tap.SocketProtocol_TCP
+ ft := New()
+ ft.opts.forceTCP = true
+ testCase(t, ft, q, r, tapq, tapr)
+}
+
+func TestNoDnstap(t *testing.T) {
+ err := toDnstap(context.TODO(), "", nil, request.Request{}, nil, time.Now())
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/plugin/forward/forward.go b/plugin/forward/forward.go
index 0b043e070..c7f7a83c4 100644
--- a/plugin/forward/forward.go
+++ b/plugin/forward/forward.go
@@ -74,7 +74,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
i := 0
list := f.List()
deadline := time.Now().Add(defaultTimeout)
-
+ start := time.Now()
for time.Now().Before(deadline) {
if i >= len(list) {
// reached the end of list, reset to begin
@@ -126,6 +126,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
if child != nil {
child.Finish()
}
+ taperr := toDnstap(ctx, proxy.addr, f, state, ret, start)
upstreamErr = err
@@ -147,11 +148,11 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
formerr := state.ErrorMessage(dns.RcodeFormatError)
w.WriteMsg(formerr)
- return 0, nil
+ return 0, taperr
}
w.WriteMsg(ret)
- return 0, nil
+ return 0, taperr
}
if upstreamErr != nil {