mirror of
https://github.com/coredns/coredns.git
synced 2025-11-02 02:03:13 -05:00
plugin/forward: add HealthChecker interface (#1950)
* 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>
This commit is contained in:
@@ -1,17 +1,48 @@
|
||||
package forward
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// HealthChecker checks the upstream health.
|
||||
type HealthChecker interface {
|
||||
Check(*Proxy) error
|
||||
SetTLSConfig(*tls.Config)
|
||||
}
|
||||
|
||||
// dnsHc is a health checker for a DNS endpoint (DNS, and DoT).
|
||||
type dnsHc struct{ c *dns.Client }
|
||||
|
||||
// NewHealthChecker returns a new HealthChecker based on protocol.
|
||||
func NewHealthChecker(protocol int) HealthChecker {
|
||||
switch protocol {
|
||||
case DNS, TLS:
|
||||
c := new(dns.Client)
|
||||
c.Net = "udp"
|
||||
c.ReadTimeout = 1 * time.Second
|
||||
c.WriteTimeout = 1 * time.Second
|
||||
|
||||
return &dnsHc{c: c}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *dnsHc) SetTLSConfig(cfg *tls.Config) {
|
||||
h.c.Net = "tcp-tls"
|
||||
h.c.TLSConfig = cfg
|
||||
}
|
||||
|
||||
// For HC we send to . IN NS +norec message to the upstream. Dial timeouts and empty
|
||||
// replies are considered fails, basically anything else constitutes a healthy upstream.
|
||||
|
||||
// Check is used as the up.Func in the up.Probe.
|
||||
func (p *Proxy) Check() error {
|
||||
err := p.send()
|
||||
func (h *dnsHc) Check(p *Proxy) error {
|
||||
err := h.send(p.addr)
|
||||
if err != nil {
|
||||
HealthcheckFailureCount.WithLabelValues(p.addr).Add(1)
|
||||
atomic.AddUint32(&p.fails, 1)
|
||||
@@ -22,14 +53,14 @@ func (p *Proxy) Check() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Proxy) send() error {
|
||||
hcping := new(dns.Msg)
|
||||
hcping.SetQuestion(".", dns.TypeNS)
|
||||
func (h *dnsHc) send(addr string) error {
|
||||
ping := new(dns.Msg)
|
||||
ping.SetQuestion(".", dns.TypeNS)
|
||||
|
||||
m, _, err := p.client.Exchange(hcping, p.addr)
|
||||
// If we got a header, we're alright, basically only care about I/O errors 'n stuff
|
||||
m, _, err := h.c.Exchange(ping, addr)
|
||||
// If we got a header, we're alright, basically only care about I/O errors 'n stuff.
|
||||
if err != nil && m != nil {
|
||||
// Silly check, something sane came back
|
||||
// Silly check, something sane came back.
|
||||
if m.Response || m.Opcode == dns.OpcodeQuery {
|
||||
err = nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user