1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Retain V6 DNS server in resolv.conf; use only V4 servers for fallback

Signed-off-by: Santhosh Manohar <santhosh@docker.com>
This commit is contained in:
Santhosh Manohar 2016-01-18 04:07:19 -08:00
parent a02c73c352
commit 30ef9bcf4a
6 changed files with 47 additions and 14 deletions

View file

@ -1706,7 +1706,7 @@ func TestEnableIPv6(t *testing.T) {
} }
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n") tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 127.0.0.11\noptions ndots:0\n") expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 127.0.0.11\nnameserver 2001:4860:4860::8888\noptions ndots:0\n")
//take a copy of resolv.conf for restoring after test completes //take a copy of resolv.conf for restoring after test completes
resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf") resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil { if err != nil {

View file

@ -14,6 +14,13 @@ import (
"github.com/docker/libnetwork/types" "github.com/docker/libnetwork/types"
) )
// constants for the IP address type
const (
IP = iota // IPv4 and IPv6
IPv4
IPv6
)
var ( var (
// ErrNetworkOverlapsWithNameservers preformatted error // ErrNetworkOverlapsWithNameservers preformatted error
ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver") ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")

View file

@ -10,6 +10,7 @@ import (
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/ioutils"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/resolvconf/dns" "github.com/docker/libnetwork/resolvconf/dns"
) )
@ -29,6 +30,8 @@ var (
localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`) localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`)
nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`) nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`) nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
nsIPv6Regexpmatch = regexp.MustCompile(`^\s*nameserver\s*((` + ipv6Address + `))\s*$`)
nsIPv4Regexpmatch = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `))\s*$`)
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`) searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
optionsRegexp = regexp.MustCompile(`^\s*options\s*(([^\s]+\s*)*)$`) optionsRegexp = regexp.MustCompile(`^\s*options\s*(([^\s]+\s*)*)$`)
) )
@ -119,7 +122,7 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
} }
// if the resulting resolvConf has no more nameservers defined, add appropriate // if the resulting resolvConf has no more nameservers defined, add appropriate
// default DNS servers for IPv4 and (optionally) IPv6 // default DNS servers for IPv4 and (optionally) IPv6
if len(GetNameservers(cleanedResolvConf)) == 0 { if len(GetNameservers(cleanedResolvConf, netutils.IP)) == 0 {
logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns) logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
dns := defaultIPv4Dns dns := defaultIPv4Dns
if ipv6Enabled { if ipv6Enabled {
@ -151,10 +154,17 @@ func getLines(input []byte, commentMarker []byte) [][]byte {
} }
// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
func GetNameservers(resolvConf []byte) []string { func GetNameservers(resolvConf []byte, kind int) []string {
nameservers := []string{} nameservers := []string{}
for _, line := range getLines(resolvConf, []byte("#")) { for _, line := range getLines(resolvConf, []byte("#")) {
var ns = nsRegexp.FindSubmatch(line) var ns [][]byte
if kind == netutils.IP {
ns = nsRegexp.FindSubmatch(line)
} else if kind == netutils.IPv4 {
ns = nsIPv4Regexpmatch.FindSubmatch(line)
} else if kind == netutils.IPv6 {
ns = nsIPv6Regexpmatch.FindSubmatch(line)
}
if len(ns) > 0 { if len(ns) > 0 {
nameservers = append(nameservers, string(ns[1])) nameservers = append(nameservers, string(ns[1]))
} }
@ -167,7 +177,7 @@ func GetNameservers(resolvConf []byte) []string {
// This function's output is intended for net.ParseCIDR // This function's output is intended for net.ParseCIDR
func GetNameserversAsCIDR(resolvConf []byte) []string { func GetNameserversAsCIDR(resolvConf []byte) []string {
nameservers := []string{} nameservers := []string{}
for _, nameserver := range GetNameservers(resolvConf) { for _, nameserver := range GetNameservers(resolvConf, netutils.IP) {
nameservers = append(nameservers, nameserver+"/32") nameservers = append(nameservers, nameserver+"/32")
} }
return nameservers return nameservers

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/ioutils"
"github.com/docker/libnetwork/netutils"
_ "github.com/docker/libnetwork/testutils" _ "github.com/docker/libnetwork/testutils"
) )
@ -48,7 +49,7 @@ nameserver 1.2.3.4
`search example.com `search example.com
nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4"}, nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4"},
} { } {
test := GetNameservers([]byte(resolv)) test := GetNameservers([]byte(resolv), netutils.IP)
if !strSlicesEqual(test, result) { if !strSlicesEqual(test, result) {
t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv) t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv)
} }

View file

@ -36,6 +36,7 @@ const (
ptrIPv4domain = ".in-addr.arpa." ptrIPv4domain = ".in-addr.arpa."
ptrIPv6domain = ".ip6.arpa." ptrIPv6domain = ".ip6.arpa."
respTTL = 1800 respTTL = 1800
maxExtDNS = 3 //max number of external servers to try
) )
// resolver implements the Resolver interface // resolver implements the Resolver interface
@ -188,15 +189,24 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
if len(r.extDNS) == 0 { if len(r.extDNS) == 0 {
return return
} }
log.Debugf("Querying ext dns %s for %s[%d]", r.extDNS[0], name, query.Question[0].Qtype)
c := &dns.Client{Net: "udp"} num := maxExtDNS
addr := fmt.Sprintf("%s:%d", r.extDNS[0], 53) if len(r.extDNS) < maxExtDNS {
num = len(r.extDNS)
}
for i := 0; i < num; i++ {
log.Debugf("Querying ext dns %s for %s[%d]", r.extDNS[i], name, query.Question[0].Qtype)
// TODO: iterate over avilable servers in case of error c := &dns.Client{Net: "udp"}
resp, _, err = c.Exchange(query, addr) addr := fmt.Sprintf("%s:%d", r.extDNS[i], 53)
if err != nil {
resp, _, err = c.Exchange(query, addr)
if err == nil {
break
}
log.Errorf("external resolution failed, %s", err) log.Errorf("external resolution failed, %s", err)
}
if resp == nil {
return return
} }
} }

View file

@ -14,6 +14,7 @@ import (
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/etchosts" "github.com/docker/libnetwork/etchosts"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/osl"
"github.com/docker/libnetwork/resolvconf" "github.com/docker/libnetwork/resolvconf"
"github.com/docker/libnetwork/types" "github.com/docker/libnetwork/types"
@ -827,7 +828,7 @@ func (sb *sandbox) setupDNS() error {
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 { if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
var ( var (
err error err error
dnsList = resolvconf.GetNameservers(currRC.Content) dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP)
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
dnsOptionsList = resolvconf.GetOptions(currRC.Content) dnsOptionsList = resolvconf.GetOptions(currRC.Content)
) )
@ -935,7 +936,8 @@ func (sb *sandbox) rebuildDNS() error {
} }
// localhost entries have already been filtered out from the list // localhost entries have already been filtered out from the list
sb.extDNS = resolvconf.GetNameservers(currRC.Content) // retain only the v4 servers in sb for forwarding the DNS queries
sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
var ( var (
dnsList = []string{sb.resolver.NameServer()} dnsList = []string{sb.resolver.NameServer()}
@ -943,6 +945,9 @@ func (sb *sandbox) rebuildDNS() error {
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
) )
// external v6 DNS servers has to be listed in resolv.conf
dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
// Resolver returns the options in the format resolv.conf expects // Resolver returns the options in the format resolv.conf expects
dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...) dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)