From af13dea5c4757a03f288c63bf16f0154764dc609 Mon Sep 17 00:00:00 2001 From: zzhuang94 Date: Wed, 4 Jan 2023 17:13:35 +0800 Subject: [PATCH] race policy gives priority to the first result, whether it is negative or not, as long as it is a standard DNS result. Signed-off-by: zzhuang94 --- README.md | 11 +++++++++++ fanout.go | 4 ++++ setup.go | 10 ++++++++++ 3 files changed, 25 insertions(+) diff --git a/README.md b/README.md index 0dd193c..fb8fcd8 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Each incoming DNS query that hits the CoreDNS fanout plugin will be replicated i * `except-file` is the path to file with line-separated list of domains to exclude from proxying. * `attempt-count` is the number of attempts to connect to upstream servers that are needed before considering an upstream to be down. If 0, the upstream will never be marked as down and request will be finished by `timeout`. Default is `3`. * `timeout` is the timeout of request. After this period, attempts to receive a response from the upstream servers will be stopped. Default is `30s`. +* `race` gives priority to the first result, whether it is negative or not, as long as it is a standard DNS result. ## Metrics If monitoring is enabled (via the *prometheus* plugin) then the following metric are exported: @@ -99,3 +100,13 @@ Sends parallel requests between five resolvers via UDP uses two workers and with } } ~~~ + +Multiple upstream servers are configured but one of them is down, query a `non-existent` domain. +If `race` is enable, we will get `NXDOMAIN` result quickly, otherwise we will get `"connection timed out"` result in a few seconds. +~~~ corefile +. { + fanout . 10.0.0.10:53 10.0.0.11:53 10.0.0.12:53 10.0.0.13:1053 10.0.0.14:1053 { + race + } +} +~~~ diff --git a/fanout.go b/fanout.go index b693d23..b5cf34a 100644 --- a/fanout.go +++ b/fanout.go @@ -40,6 +40,7 @@ type Fanout struct { excludeDomains Domain tlsServerName string timeout time.Duration + race bool net string from string attempts int @@ -141,6 +142,9 @@ func (f *Fanout) getFanoutResult(ctx context.Context, responseCh <-chan *respons if r.err != nil { break } + if f.race { + return r + } if r.response.Rcode != dns.RcodeSuccess { break } diff --git a/setup.go b/setup.go index 2aca307..50f2c6d 100644 --- a/setup.go +++ b/setup.go @@ -161,6 +161,8 @@ func parseValue(v string, f *Fanout, c *caddyfile.Dispenser) error { return parseWorkerCount(f, c) case "timeout": return parseTimeout(f, c) + case "race": + return parseRace(f, c) case "except": return parseIgnored(f, c) case "except-file": @@ -184,6 +186,14 @@ func parseTimeout(f *Fanout, c *caddyfile.Dispenser) error { return err } +func parseRace(f *Fanout, c *caddyfile.Dispenser) error { + if c.NextArg() { + return c.ArgErr() + } + f.race = true + return nil +} + func parseIgnoredFromFile(f *Fanout, c *caddyfile.Dispenser) error { args := c.RemainingArgs() if len(args) != 1 {