* plugin/forward: add HealthChecker interface Make the HealthChecker interface and morph the current DNS health checker into that interface. Remove all whole bunch of method on Forward that didn't make sense. This is done in preparation of adding a DoH client to forward - which requires a completely different healthcheck implementation (and more, but lets start here) Signed-off-by: Miek Gieben <miek@miek.nl> * Use protocol Signed-off-by: Miek Gieben <miek@miek.nl> * Dial doesnt need to be method an Forward either Signed-off-by: Miek Gieben <miek@miek.nl> * Address comments Address various comments on the PR. Signed-off-by: Miek Gieben <miek@miek.nl>
122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package forward
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
"github.com/coredns/coredns/plugin/test"
|
|
"github.com/coredns/coredns/request"
|
|
|
|
"github.com/mholt/caddy"
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func TestProxyClose(t *testing.T) {
|
|
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
ret := new(dns.Msg)
|
|
ret.SetReply(r)
|
|
w.WriteMsg(ret)
|
|
})
|
|
defer s.Close()
|
|
|
|
req := new(dns.Msg)
|
|
req.SetQuestion("example.org.", dns.TypeA)
|
|
state := request.Request{W: &test.ResponseWriter{}, Req: req}
|
|
ctx := context.TODO()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
p := NewProxy(s.Addr, DNS)
|
|
p.start(hcInterval)
|
|
|
|
go func() { p.Connect(ctx, state, options{}) }()
|
|
go func() { p.Connect(ctx, state, options{forceTCP: true}) }()
|
|
go func() { p.Connect(ctx, state, options{}) }()
|
|
go func() { p.Connect(ctx, state, options{forceTCP: true}) }()
|
|
|
|
p.close()
|
|
}
|
|
}
|
|
|
|
func TestProxy(t *testing.T) {
|
|
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
ret := new(dns.Msg)
|
|
ret.SetReply(r)
|
|
ret.Answer = append(ret.Answer, test.A("example.org. IN A 127.0.0.1"))
|
|
w.WriteMsg(ret)
|
|
})
|
|
defer s.Close()
|
|
|
|
c := caddy.NewTestController("dns", "forward . "+s.Addr)
|
|
f, err := parseForward(c)
|
|
if err != nil {
|
|
t.Errorf("Failed to create forwarder: %s", err)
|
|
}
|
|
f.OnStartup()
|
|
defer f.OnShutdown()
|
|
|
|
m := new(dns.Msg)
|
|
m.SetQuestion("example.org.", dns.TypeA)
|
|
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
|
|
|
if _, err := f.ServeDNS(context.TODO(), rec, m); err != nil {
|
|
t.Fatal("Expected to receive reply, but didn't")
|
|
}
|
|
if x := rec.Msg.Answer[0].Header().Name; x != "example.org." {
|
|
t.Errorf("Expected %s, got %s", "example.org.", x)
|
|
}
|
|
}
|
|
|
|
func TestProxyTLSFail(t *testing.T) {
|
|
// This is an udp/tcp test server, so we shouldn't reach it with TLS.
|
|
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
ret := new(dns.Msg)
|
|
ret.SetReply(r)
|
|
ret.Answer = append(ret.Answer, test.A("example.org. IN A 127.0.0.1"))
|
|
w.WriteMsg(ret)
|
|
})
|
|
defer s.Close()
|
|
|
|
c := caddy.NewTestController("dns", "forward . tls://"+s.Addr)
|
|
f, err := parseForward(c)
|
|
if err != nil {
|
|
t.Errorf("Failed to create forwarder: %s", err)
|
|
}
|
|
f.OnStartup()
|
|
defer f.OnShutdown()
|
|
|
|
m := new(dns.Msg)
|
|
m.SetQuestion("example.org.", dns.TypeA)
|
|
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
|
|
|
if _, err := f.ServeDNS(context.TODO(), rec, m); err == nil {
|
|
t.Fatal("Expected *not* to receive reply, but got one")
|
|
}
|
|
}
|
|
|
|
func TestProtocolSelection(t *testing.T) {
|
|
p := NewProxy("bad_address", DNS)
|
|
|
|
stateUDP := request.Request{W: &test.ResponseWriter{}, Req: new(dns.Msg)}
|
|
stateTCP := request.Request{W: &test.ResponseWriter{TCP: true}, Req: new(dns.Msg)}
|
|
ctx := context.TODO()
|
|
|
|
go func() {
|
|
p.Connect(ctx, stateUDP, options{})
|
|
p.Connect(ctx, stateUDP, options{forceTCP: true})
|
|
p.Connect(ctx, stateUDP, options{preferUDP: true})
|
|
p.Connect(ctx, stateUDP, options{preferUDP: true, forceTCP: true})
|
|
p.Connect(ctx, stateTCP, options{})
|
|
p.Connect(ctx, stateTCP, options{forceTCP: true})
|
|
p.Connect(ctx, stateTCP, options{preferUDP: true})
|
|
p.Connect(ctx, stateTCP, options{preferUDP: true, forceTCP: true})
|
|
}()
|
|
|
|
for i, exp := range []string{"udp", "tcp", "udp", "tcp", "tcp", "tcp", "udp", "tcp"} {
|
|
proto := <-p.transport.dial
|
|
p.transport.ret <- nil
|
|
if proto != exp {
|
|
t.Errorf("Unexpected protocol in case %d, expected %q, actual %q", i, exp, proto)
|
|
}
|
|
}
|
|
}
|