diff --git a/plugin/hosts/README.md b/plugin/hosts/README.md index 60135e71a..b18438cc6 100644 --- a/plugin/hosts/README.md +++ b/plugin/hosts/README.md @@ -15,6 +15,9 @@ The plugin reloads the content of the hosts file every 5 seconds. Upon reload, C new definitions. Should the file be deleted, any inlined content will continue to be served. When the file is restored, it will then again be used. +If you want to pass the request to the rest of the plugin chain if there is no match in the *hosts* +plugin, you must specify the `fallthrough` option. + This plugin can only be used once per Server Block. ## The hosts file @@ -60,7 +63,9 @@ hosts [FILE [ZONES...]] { then all of them will be treated as the additional content for hosts file. The specified hosts file path will still be read but entries will be overridden. * `ttl` change the DNS TTL of the records generated (forward and reverse). The default is 3600 seconds (1 hour). -* `reload` change the period between each hostsfile reload. A time of zero seconds disable the feature. Examples of valid durations: "300ms", "1.5h" or "2h45m" are valid duration with units "ns" (nanosecond), "us" (or "µs" for microsecond), "ms" (millisecond), "s" (second), "m" (minute), "h" (hour). +* `reload` change the period between each hostsfile reload. A time of zero seconds disables the + feature. Examples of valid durations: "300ms", "1.5h" or "2h45m". See Go's + [time](https://godoc.org/time). package. * `no_reverse` disable the automatic generation of the `in-addr.arpa` or `ip6.arpa` entries for the hosts * `fallthrough` If zone matches and no record can be generated, pass request to the next plugin. If **[ZONES...]** is omitted, then fallthrough happens for all zones for which the plugin diff --git a/plugin/hosts/hosts.go b/plugin/hosts/hosts.go index 54b090b4d..a94c65a7e 100644 --- a/plugin/hosts/hosts.go +++ b/plugin/hosts/hosts.go @@ -29,8 +29,8 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( zone := plugin.Zones(h.Origins).Matches(qname) if zone == "" { - // PTR zones don't need to be specified in Origins - if state.Type() != "PTR" { + // PTR zones don't need to be specified in Origins. + if state.QType() != dns.TypePTR { // if this doesn't match we need to fall through regardless of h.Fallthrough return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r) } @@ -56,8 +56,10 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( if h.Fall.Through(qname) { return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r) } - if !h.otherRecordsExist(state.QType(), qname) { - return dns.RcodeNameError, nil + // We want to send an NXDOMAIN, but because of /etc/hosts' setup we don't have a SOA, so we make it REFUSED + // to at least give an answer back to signals we're having problems resolving this. + if !h.otherRecordsExist(qname) { + return dns.RcodeServerFailure, nil } } @@ -70,23 +72,12 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( return dns.RcodeSuccess, nil } -func (h Hosts) otherRecordsExist(qtype uint16, qname string) bool { - switch qtype { - case dns.TypeA: - if len(h.LookupStaticHostV6(qname)) > 0 { - return true - } - case dns.TypeAAAA: - if len(h.LookupStaticHostV4(qname)) > 0 { - return true - } - default: - if len(h.LookupStaticHostV4(qname)) > 0 { - return true - } - if len(h.LookupStaticHostV6(qname)) > 0 { - return true - } +func (h Hosts) otherRecordsExist(qname string) bool { + if len(h.LookupStaticHostV4(qname)) > 0 { + return true + } + if len(h.LookupStaticHostV6(qname)) > 0 { + return true } return false } diff --git a/plugin/hosts/setup.go b/plugin/hosts/setup.go index 73fd3cec4..981ea141f 100644 --- a/plugin/hosts/setup.go +++ b/plugin/hosts/setup.go @@ -73,13 +73,12 @@ func setup(c *caddy.Controller) error { func hostsParse(c *caddy.Controller) (Hosts, error) { config := dnsserver.GetConfig(c) - options := newOptions() - h := Hosts{ Hostsfile: &Hostsfile{ path: "/etc/hosts", hmap: newMap(), - options: options, + inline: newMap(), + options: newOptions(), }, } @@ -129,7 +128,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) { case "fallthrough": h.Fall.SetZonesFromArgs(c.RemainingArgs()) case "no_reverse": - options.autoReverse = false + h.options.autoReverse = false case "ttl": remaining := c.RemainingArgs() if len(remaining) < 1 { @@ -142,7 +141,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) { if ttl <= 0 || ttl > 65535 { return h, c.Errf("ttl provided is invalid") } - options.ttl = uint32(ttl) + h.options.ttl = uint32(ttl) case "reload": remaining := c.RemainingArgs() if len(remaining) != 1 { @@ -155,7 +154,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) { if reload < 0 { return h, c.Errf("invalid negative duration for reload '%s'", remaining[0]) } - options.reload = reload + h.options.reload = reload default: if len(h.Fall.Zones) == 0 { line := strings.Join(append([]string{c.Val()}, c.RemainingArgs()...), " ")