diff options
author | 2023-03-24 12:55:51 +0000 | |
---|---|---|
committer | 2023-03-24 08:55:51 -0400 | |
commit | f823825f8a34edb85d5d18cd5d2f6f850adf408e (patch) | |
tree | 79d241ab9b4c7c343d806f4041c8efccbe3f9ca0 /plugin/pkg/proxy/health.go | |
parent | 47dceabfc6465ba6c5d41472d6602d4ad5c9fb1b (diff) | |
download | coredns-f823825f8a34edb85d5d18cd5d2f6f850adf408e.tar.gz coredns-f823825f8a34edb85d5d18cd5d2f6f850adf408e.tar.zst coredns-f823825f8a34edb85d5d18cd5d2f6f850adf408e.zip |
plugin/forward: Allow Proxy to be used outside of forward plugin. (#5951)
* plugin/forward: Move Proxy into pkg/plugin/proxy, to allow forward.Proxy to be used outside of forward plugin.
Signed-off-by: Patrick Downey <patrick.downey@dioadconsulting.com>
Diffstat (limited to 'plugin/pkg/proxy/health.go')
-rw-r--r-- | plugin/pkg/proxy/health.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/plugin/pkg/proxy/health.go b/plugin/pkg/proxy/health.go new file mode 100644 index 000000000..e87104a13 --- /dev/null +++ b/plugin/pkg/proxy/health.go @@ -0,0 +1,131 @@ +package proxy + +import ( + "crypto/tls" + "sync/atomic" + "time" + + "github.com/coredns/coredns/plugin/pkg/log" + "github.com/coredns/coredns/plugin/pkg/transport" + + "github.com/miekg/dns" +) + +// HealthChecker checks the upstream health. +type HealthChecker interface { + Check(*Proxy) error + SetTLSConfig(*tls.Config) + GetTLSConfig() *tls.Config + SetRecursionDesired(bool) + GetRecursionDesired() bool + SetDomain(domain string) + GetDomain() string + SetTCPTransport() + GetReadTimeout() time.Duration + SetReadTimeout(time.Duration) + GetWriteTimeout() time.Duration + SetWriteTimeout(time.Duration) +} + +// dnsHc is a health checker for a DNS endpoint (DNS, and DoT). +type dnsHc struct { + c *dns.Client + recursionDesired bool + domain string +} + +// NewHealthChecker returns a new HealthChecker based on transport. +func NewHealthChecker(trans string, recursionDesired bool, domain string) HealthChecker { + switch trans { + case transport.DNS, transport.TLS: + c := new(dns.Client) + c.Net = "udp" + c.ReadTimeout = 1 * time.Second + c.WriteTimeout = 1 * time.Second + + return &dnsHc{ + c: c, + recursionDesired: recursionDesired, + domain: domain, + } + } + + log.Warningf("No healthchecker for transport %q", trans) + return nil +} + +func (h *dnsHc) SetTLSConfig(cfg *tls.Config) { + h.c.Net = "tcp-tls" + h.c.TLSConfig = cfg +} + +func (h *dnsHc) GetTLSConfig() *tls.Config { + return h.c.TLSConfig +} + +func (h *dnsHc) SetRecursionDesired(recursionDesired bool) { + h.recursionDesired = recursionDesired +} +func (h *dnsHc) GetRecursionDesired() bool { + return h.recursionDesired +} + +func (h *dnsHc) SetDomain(domain string) { + h.domain = domain +} +func (h *dnsHc) GetDomain() string { + return h.domain +} + +func (h *dnsHc) SetTCPTransport() { + h.c.Net = "tcp" +} + +func (h *dnsHc) GetReadTimeout() time.Duration { + return h.c.ReadTimeout +} + +func (h *dnsHc) SetReadTimeout(t time.Duration) { + h.c.ReadTimeout = t +} + +func (h *dnsHc) GetWriteTimeout() time.Duration { + return h.c.WriteTimeout +} + +func (h *dnsHc) SetWriteTimeout(t time.Duration) { + h.c.WriteTimeout = t +} + +// For HC, we send to . IN NS +[no]rec 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 (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) + return err + } + + atomic.StoreUint32(&p.fails, 0) + return nil +} + +func (h *dnsHc) send(addr string) error { + ping := new(dns.Msg) + ping.SetQuestion(h.domain, dns.TypeNS) + ping.MsgHdr.RecursionDesired = h.recursionDesired + + 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. + if m.Response || m.Opcode == dns.OpcodeQuery { + err = nil + } + } + + return err +} |