aboutsummaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authorGravatar hansedong <admin@yinxiaoluo.com> 2022-04-13 00:39:48 +0800
committerGravatar GitHub <noreply@github.com> 2022-04-12 12:39:48 -0400
commit0622a6c66c6c0c6659ece5e6e41ea218912b0ed2 (patch)
treec0532dbe57397cb6b40e70bc543b6aa3e7426117 /plugin
parente60c179194cc1ff85d24fe9b887d901aea74641d (diff)
downloadcoredns-0622a6c66c6c0c6659ece5e6e41ea218912b0ed2.tar.gz
coredns-0622a6c66c6c0c6659ece5e6e41ea218912b0ed2.tar.zst
coredns-0622a6c66c6c0c6659ece5e6e41ea218912b0ed2.zip
plugin/forward: configurable domain support for healthcheck (#5281)
* plugin/forward: configurable domain support for healthcheck Signed-off-by: hansedong <admin@yinxiaoluo.com>
Diffstat (limited to 'plugin')
-rw-r--r--plugin/forward/README.md16
-rw-r--r--plugin/forward/forward.go3
-rw-r--r--plugin/forward/health.go16
-rw-r--r--plugin/forward/health_test.go39
-rw-r--r--plugin/forward/proxy.go2
-rw-r--r--plugin/forward/setup.go7
-rw-r--r--plugin/forward/setup_test.go65
7 files changed, 113 insertions, 35 deletions
diff --git a/plugin/forward/README.md b/plugin/forward/README.md
index 892701f70..1ea335bf2 100644
--- a/plugin/forward/README.md
+++ b/plugin/forward/README.md
@@ -50,7 +50,7 @@ forward FROM TO... {
tls CERT KEY CA
tls_servername NAME
policy random|round_robin|sequential
- health_check DURATION [no_rec]
+ health_check DURATION [no_rec] [domain DOMAIN]
max_concurrent MAX
}
~~~
@@ -90,6 +90,8 @@ forward FROM TO... {
* `<duration>` - use a different duration for health checking, the default duration is 0.5s.
* `no_rec` - optional argument that sets the RecursionDesired-flag of the dns-query used in health checking to `false`.
The flag is default `true`.
+ * `domain DOMAIN` - optional arguments that sets the domain of the dns-query used in health checking.
+ If not configured, the requested domain name is `.`. `DOMAIN` is used to configure the domain name.
* `max_concurrent` **MAX** will limit the number of concurrent queries to **MAX**. Any new query that would
raise the number of concurrent queries above the **MAX** will result in a REFUSED response. This
response does not count as a health failure. When choosing a value for **MAX**, pick a number
@@ -182,6 +184,18 @@ service with health checks.
}
~~~
+Or configure other domain name for health check requests
+
+~~~ corefile
+. {
+ forward . tls://9.9.9.9 {
+ tls_servername dns.quad9.net
+ health_check 5s domain example.org
+ }
+ cache 30
+}
+~~~
+
Or with multiple upstreams from the same provider
~~~ corefile
diff --git a/plugin/forward/forward.go b/plugin/forward/forward.go
index 19a469c72..e7fcaaad6 100644
--- a/plugin/forward/forward.go
+++ b/plugin/forward/forward.go
@@ -56,7 +56,7 @@ type Forward struct {
// New returns a new Forward.
func New() *Forward {
- f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(random), from: ".", hcInterval: hcInterval, opts: options{forceTCP: false, preferUDP: false, hcRecursionDesired: true}}
+ f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(random), from: ".", hcInterval: hcInterval, opts: options{forceTCP: false, preferUDP: false, hcRecursionDesired: true, hcDomain: "."}}
return f
}
@@ -234,6 +234,7 @@ type options struct {
forceTCP bool
preferUDP bool
hcRecursionDesired bool
+ hcDomain string
}
var defaultTimeout = 5 * time.Second
diff --git a/plugin/forward/health.go b/plugin/forward/health.go
index f4cfab834..ec0b48143 100644
--- a/plugin/forward/health.go
+++ b/plugin/forward/health.go
@@ -16,6 +16,8 @@ type HealthChecker interface {
SetTLSConfig(*tls.Config)
SetRecursionDesired(bool)
GetRecursionDesired() bool
+ SetDomain(domain string)
+ GetDomain() string
SetTCPTransport()
}
@@ -23,6 +25,7 @@ type HealthChecker interface {
type dnsHc struct {
c *dns.Client
recursionDesired bool
+ domain string
}
var (
@@ -31,7 +34,7 @@ var (
)
// NewHealthChecker returns a new HealthChecker based on transport.
-func NewHealthChecker(trans string, recursionDesired bool) HealthChecker {
+func NewHealthChecker(trans string, recursionDesired bool, domain string) HealthChecker {
switch trans {
case transport.DNS, transport.TLS:
c := new(dns.Client)
@@ -39,7 +42,7 @@ func NewHealthChecker(trans string, recursionDesired bool) HealthChecker {
c.ReadTimeout = hcReadTimeout
c.WriteTimeout = hcWriteTimeout
- return &dnsHc{c: c, recursionDesired: recursionDesired}
+ return &dnsHc{c: c, recursionDesired: recursionDesired, domain: domain}
}
log.Warningf("No healthchecker for transport %q", trans)
@@ -58,6 +61,13 @@ 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"
}
@@ -80,7 +90,7 @@ func (h *dnsHc) Check(p *Proxy) error {
func (h *dnsHc) send(addr string) error {
ping := new(dns.Msg)
- ping.SetQuestion(".", dns.TypeNS)
+ ping.SetQuestion(h.domain, dns.TypeNS)
ping.MsgHdr.RecursionDesired = h.recursionDesired
m, _, err := h.c.Exchange(ping, addr)
diff --git a/plugin/forward/health_test.go b/plugin/forward/health_test.go
index 2d65f4353..9917b3a37 100644
--- a/plugin/forward/health_test.go
+++ b/plugin/forward/health_test.go
@@ -242,3 +242,42 @@ func TestHealthNoMaxFails(t *testing.T) {
t.Errorf("Expected number of health checks to be %d, got %d", 0, i1)
}
}
+
+func TestHealthDomain(t *testing.T) {
+ hcReadTimeout = 10 * time.Millisecond
+ readTimeout = 10 * time.Millisecond
+ defaultTimeout = 10 * time.Millisecond
+ hcWriteTimeout = 10 * time.Millisecond
+ hcDomain := "example.org."
+ i := uint32(0)
+ q := uint32(0)
+ s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
+ if atomic.LoadUint32(&q) == 0 { //drop the first query to trigger health-checking
+ atomic.AddUint32(&q, 1)
+ return
+ }
+ if r.Question[0].Name == hcDomain && r.RecursionDesired == true {
+ atomic.AddUint32(&i, 1)
+ }
+ ret := new(dns.Msg)
+ ret.SetReply(r)
+ w.WriteMsg(ret)
+ })
+ defer s.Close()
+ p := NewProxy(s.Addr, transport.DNS)
+ p.health.SetDomain(hcDomain)
+ f := New()
+ f.SetProxy(p)
+ defer f.OnShutdown()
+
+ req := new(dns.Msg)
+ req.SetQuestion(".", dns.TypeNS)
+
+ f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
+
+ time.Sleep(20 * time.Millisecond)
+ i1 := atomic.LoadUint32(&i)
+ if i1 != 1 {
+ t.Errorf("Expected number of health checks with Domain==%s to be %d, got %d", hcDomain, 1, i1)
+ }
+}
diff --git a/plugin/forward/proxy.go b/plugin/forward/proxy.go
index 80cb581f9..6a4b5693e 100644
--- a/plugin/forward/proxy.go
+++ b/plugin/forward/proxy.go
@@ -29,7 +29,7 @@ func NewProxy(addr, trans string) *Proxy {
probe: up.New(),
transport: newTransport(addr),
}
- p.health = NewHealthChecker(trans, true)
+ p.health = NewHealthChecker(trans, true, ".")
runtime.SetFinalizer(p, (*Proxy).finalizer)
return p
}
diff --git a/plugin/forward/setup.go b/plugin/forward/setup.go
index baf0512ba..af8141898 100644
--- a/plugin/forward/setup.go
+++ b/plugin/forward/setup.go
@@ -151,6 +151,7 @@ func parseStanza(c *caddy.Controller) (*Forward, error) {
if f.opts.forceTCP && transports[i] != transport.TLS {
f.proxies[i].health.SetTCPTransport()
}
+ f.proxies[i].health.SetDomain(f.opts.hcDomain)
}
return f, nil
@@ -187,11 +188,17 @@ func parseBlock(c *caddy.Controller, f *Forward) error {
return fmt.Errorf("health_check can't be negative: %d", dur)
}
f.hcInterval = dur
+ f.opts.hcDomain = "."
for c.NextArg() {
switch hcOpts := c.Val(); hcOpts {
case "no_rec":
f.opts.hcRecursionDesired = false
+ case "domain":
+ if !c.NextArg() {
+ return c.ArgErr()
+ }
+ f.opts.hcDomain = c.Val()
default:
return fmt.Errorf("health_check: unknown option %s", hcOpts)
}
diff --git a/plugin/forward/setup_test.go b/plugin/forward/setup_test.go
index 3c38acf97..2a5257e98 100644
--- a/plugin/forward/setup_test.go
+++ b/plugin/forward/setup_test.go
@@ -20,25 +20,27 @@ func TestSetup(t *testing.T) {
expectedErr string
}{
// positive
- {"forward . 127.0.0.1", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 {\nexcept miek.nl\n}\n", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 {\nmax_fails 3\n}\n", false, ".", nil, 3, options{hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 {\nforce_tcp\n}\n", false, ".", nil, 2, options{forceTCP: true, hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 {\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 {\nforce_tcp\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, forceTCP: true, hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1:8080", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . [::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . [2003::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward . 127.0.0.1 \n", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
- {"forward 10.9.3.0/18 127.0.0.1", false, "0.9.10.in-addr.arpa.", nil, 2, options{hcRecursionDesired: true}, ""},
+ {"forward . 127.0.0.1", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s domain example.org\n}\n", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "example.org"}, ""},
+ {"forward . 127.0.0.1 {\nexcept miek.nl\n}\n", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 {\nmax_fails 3\n}\n", false, ".", nil, 3, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 {\nforce_tcp\n}\n", false, ".", nil, 2, options{forceTCP: true, hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 {\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 {\nforce_tcp\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, forceTCP: true, hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1:53", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1:8080", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . [::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . [2003::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward . 127.0.0.1 \n", false, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
+ {"forward 10.9.3.0/18 127.0.0.1", false, "0.9.10.in-addr.arpa.", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, ""},
// negative
- {"forward . a27.0.0.1", true, "", nil, 0, options{hcRecursionDesired: true}, "not an IP"},
- {"forward . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, 0, options{hcRecursionDesired: true}, "unknown property"},
+ {"forward . a27.0.0.1", true, "", nil, 0, options{hcRecursionDesired: true, hcDomain: "."}, "not an IP"},
+ {"forward . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, 0, options{hcRecursionDesired: true, hcDomain: "."}, "unknown property"},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s domain\n}\n", true, "", nil, 0, options{hcRecursionDesired: true, hcDomain: "."}, "Wrong argument count or unexpected line ending after 'domain'"},
{`forward . ::1
- forward com ::2`, true, "", nil, 0, options{hcRecursionDesired: true}, "plugin"},
- {"forward . https://127.0.0.1 \n", true, ".", nil, 2, options{hcRecursionDesired: true}, "'https' is not supported as a destination protocol in forward: https://127.0.0.1"},
- {"forward xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 127.0.0.1 \n", true, ".", nil, 2, options{hcRecursionDesired: true}, "unable to normalize 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'"},
+ forward com ::2`, true, "", nil, 0, options{hcRecursionDesired: true, hcDomain: "."}, "plugin"},
+ {"forward . https://127.0.0.1 \n", true, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, "'https' is not supported as a destination protocol in forward: https://127.0.0.1"},
+ {"forward xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 127.0.0.1 \n", true, ".", nil, 2, options{hcRecursionDesired: true, hcDomain: "."}, "unable to normalize 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'"},
}
for i, test := range tests {
@@ -221,18 +223,23 @@ func TestSetupMaxConcurrent(t *testing.T) {
func TestSetupHealthCheck(t *testing.T) {
tests := []struct {
- input string
- shouldErr bool
- expectedVal bool
- expectedErr string
+ input string
+ shouldErr bool
+ expectedRecVal bool
+ expectedDomain string
+ expectedErr string
}{
// positive
- {"forward . 127.0.0.1\n", false, true, ""},
- {"forward . 127.0.0.1 {\nhealth_check 0.5s\n}\n", false, true, ""},
- {"forward . 127.0.0.1 {\nhealth_check 0.5s no_rec\n}\n", false, false, ""},
+ {"forward . 127.0.0.1\n", false, true, ".", ""},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s\n}\n", false, true, ".", ""},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s no_rec\n}\n", false, false, ".", ""},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s no_rec domain example.org\n}\n", false, false, "example.org", ""},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s domain example.org\n}\n", false, true, "example.org", ""},
// negative
- {"forward . 127.0.0.1 {\nhealth_check no_rec\n}\n", true, true, "time: invalid duration"},
- {"forward . 127.0.0.1 {\nhealth_check 0.5s rec\n}\n", true, true, "health_check: unknown option rec"},
+ {"forward . 127.0.0.1 {\nhealth_check no_rec\n}\n", true, true, ".", "time: invalid duration"},
+ {"forward . 127.0.0.1 {\nhealth_check domain example.org\n}\n", true, true, "example.org", "time: invalid duration"},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s rec\n}\n", true, true, ".", "health_check: unknown option rec"},
+ {"forward . 127.0.0.1 {\nhealth_check 0.5s domain\n}\n", true, true, ".", "Wrong argument count or unexpected line ending after 'domain'"},
}
for i, test := range tests {
@@ -247,13 +254,13 @@ func TestSetupHealthCheck(t *testing.T) {
if !test.shouldErr {
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
}
-
if !strings.Contains(err.Error(), test.expectedErr) {
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
}
}
- if !test.shouldErr && (f.opts.hcRecursionDesired != test.expectedVal || f.proxies[0].health.GetRecursionDesired() != test.expectedVal) {
- t.Errorf("Test %d: expected: %t, got: %d", i, test.expectedVal, f.maxConcurrent)
+ if !test.shouldErr && (f.opts.hcRecursionDesired != test.expectedRecVal || f.proxies[0].health.GetRecursionDesired() != test.expectedRecVal ||
+ f.opts.hcDomain != test.expectedDomain || f.proxies[0].health.GetDomain() != test.expectedDomain) {
+ t.Errorf("Test %d: expectedRec: %v, got: %v. expectedDomain: %s, got: %s. ", i, test.expectedRecVal, f.opts.hcRecursionDesired, test.expectedDomain, f.opts.hcDomain)
}
}
}