diff --git a/plugin/pkg/parse/host.go b/plugin/pkg/parse/host.go index 87177125f..c1b7d23e0 100644 --- a/plugin/pkg/parse/host.go +++ b/plugin/pkg/parse/host.go @@ -4,12 +4,23 @@ import ( "fmt" "net" "os" + "strings" "github.com/coredns/coredns/plugin/pkg/transport" "github.com/miekg/dns" ) +// Strips the zone, but preserves any port that comes after the zone +func stripZone(host string) string { + if strings.Contains(host, "%") { + lastPercent := strings.LastIndex(host, "%") + newHost := host[:lastPercent] + return newHost + } + return host +} + // HostPortOrFile parses the strings in s, each string can either be a // address, [scheme://]address:port or a filename. The address part is checked // and in case of filename a resolv.conf like file is (assumed) and parsed and @@ -21,10 +32,11 @@ func HostPortOrFile(s ...string) ([]string, error) { trans, host := Transport(h) addr, _, err := net.SplitHostPort(host) + if err != nil { // Parse didn't work, it is not a addr:port combo - if net.ParseIP(host) == nil { - // Not an IP address. + hostNoZone := stripZone(host) + if net.ParseIP(hostNoZone) == nil { ss, err := tryFile(host) if err == nil { servers = append(servers, ss...) @@ -47,8 +59,7 @@ func HostPortOrFile(s ...string) ([]string, error) { continue } - if net.ParseIP(addr) == nil { - // Not an IP address. + if net.ParseIP(stripZone(addr)) == nil { ss, err := tryFile(host) if err == nil { servers = append(servers, ss...) diff --git a/plugin/pkg/parse/host_test.go b/plugin/pkg/parse/host_test.go index f6e771f29..1c23c5bee 100644 --- a/plugin/pkg/parse/host_test.go +++ b/plugin/pkg/parse/host_test.go @@ -34,6 +34,26 @@ func TestHostPortOrFile(t *testing.T) { "127.0.0.1:53", false, }, + { + "fe80::1", + "[fe80::1]:53", + false, + }, + { + "fe80::1%ens3", + "[fe80::1%ens3]:53", + false, + }, + { + "[fd01::1]:153", + "[fd01::1]:153", + false, + }, + { + "[fd01::1%ens3]:153", + "[fd01::1%ens3]:153", + false, + }, } err := ioutil.WriteFile("resolv.conf", []byte("nameserver 127.0.0.1\n"), 0600)