浏览代码

Merge pull request #1577 from mrallen1/fix/1502

Prevent DNS server conflicts in CreateBridgeIface
Guillaume J. Charmes 11 年之前
父节点
当前提交
c22ff0296e
共有 4 个文件被更改,包括 101 次插入2 次删除
  1. 29 2
      network.go
  2. 16 0
      network_test.go
  3. 18 0
      utils/utils.go
  4. 38 0
      utils/utils_test.go

+ 29 - 2
network.go

@@ -76,6 +76,21 @@ func checkRouteOverlaps(networks []*net.IPNet, dockerNetwork *net.IPNet) error {
 	return nil
 }
 
+func checkNameserverOverlaps(nameservers []string, dockerNetwork *net.IPNet) error {
+	if len(nameservers) > 0 {
+		for _, ns := range nameservers {
+			_, nsNetwork, err := net.ParseCIDR(ns)
+			if err != nil {
+				return err
+			}
+			if networkOverlaps(dockerNetwork, nsNetwork) {
+				return fmt.Errorf("%s overlaps nameserver %s", dockerNetwork, nsNetwork)
+			}
+		}
+	}
+	return nil
+}
+
 // CreateBridgeIface creates a network bridge interface on the host system with the name `ifaceName`,
 // and attempts to configure it with an address which doesn't conflict with any other interface on the host.
 // If it can't find an address which doesn't conflict, it will return an error.
@@ -100,6 +115,16 @@ func CreateBridgeIface(config *DaemonConfig) error {
 		"192.168.44.1/24",
 	}
 
+	nameservers := []string{}
+	resolvConf, _ := utils.GetResolvConf()
+	// we don't check for an error here, because we don't really care
+	// if we can't read /etc/resolv.conf. So instead we skip the append
+	// if resolvConf is nil. It either doesn't exist, or we can't read it
+	// for some reason.
+	if resolvConf != nil {
+		nameservers = append(nameservers, utils.GetNameserversAsCIDR(resolvConf)...)
+	}
+
 	var ifaceAddr string
 	for _, addr := range addrs {
 		_, dockerNetwork, err := net.ParseCIDR(addr)
@@ -111,8 +136,10 @@ func CreateBridgeIface(config *DaemonConfig) error {
 			return err
 		}
 		if err := checkRouteOverlaps(routes, dockerNetwork); err == nil {
-			ifaceAddr = addr
-			break
+			if err := checkNameserverOverlaps(nameservers, dockerNetwork); err == nil {
+				ifaceAddr = addr
+				break
+			}
 		} else {
 			utils.Debugf("%s: %s", addr, err)
 		}

+ 16 - 0
network_test.go

@@ -295,3 +295,19 @@ func TestCheckRouteOverlaps(t *testing.T) {
 		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
 	}
 }
+
+func TestCheckNameserverOverlaps(t *testing.T) {
+	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
+
+	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
+
+	if err := checkNameserverOverlaps(nameservers, netX); err == nil {
+		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
+	}
+
+	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
+
+	if err := checkNameserverOverlaps(nameservers, netX); err != nil {
+		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
+	}
+}

+ 18 - 0
utils/utils.go

@@ -16,6 +16,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"runtime"
+	"regexp"
 	"strconv"
 	"strings"
 	"sync"
@@ -903,6 +904,23 @@ func StripComments(input []byte, commentMarker []byte) []byte {
 	return output
 }
 
+// GetNameserversAsCIDR returns nameservers (if any) listed in 
+// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
+// This function's output is intended for net.ParseCIDR
+func GetNameserversAsCIDR(resolvConf []byte) []string {
+	var parsedResolvConf = StripComments(resolvConf, []byte("#"))
+	nameservers := []string{}
+	re := regexp.MustCompile(`^\s*nameserver\s*(([0-9]\.){3}([0-9]))\s*$`)
+	for _, line := range bytes.Split(parsedResolvConf, []byte("\n")) {
+		var ns = re.FindSubmatch(line)
+		if len(ns) > 0 {
+			nameservers = append(nameservers, string(ns[1])+"/32")
+		}
+	}
+
+	return nameservers
+}
+
 func ParseHost(host string, port int, addr string) (string, error) {
 	var proto string
 	switch {

+ 38 - 0
utils/utils_test.go

@@ -444,3 +444,41 @@ func TestParsePortMapping(t *testing.T) {
 		t.Fail()
 	}
 }
+
+func TestGetNameserversAsCIDR(t *testing.T) {
+	for resolv, result := range map[string][]string{`
+nameserver 1.2.3.4
+nameserver 4.3.2.1
+search example.com`: {"1.2.3.4/32", "4.3.2.1/32"},
+		`search example.com`: {},
+		`nameserver 1.2.3.4
+search example.com
+nameserver 4.3.2.1`: []string{"1.2.3.4/32", "4.3.2.1/32"},
+    ``: []string{},
+    `  nameserver 1.2.3.4   `: []string{"1.2.3.4/32"},
+    `search example.com
+nameserver 1.2.3.4
+#nameserver 4.3.2.1`: []string{"1.2.3.4/32"},
+    `search example.com
+nameserver 1.2.3.4 # not 4.3.2.1`: []string{"1.2.3.4/32"},
+    } {
+        test := GetNameserversAsCIDR([]byte(resolv))
+        if !StrSlicesEqual(test, result) {
+            t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv)
+        }
+    }
+}
+
+func StrSlicesEqual(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+
+	for i, v := range a {
+		if v != b[i] {
+			return false
+		}
+	}
+
+	return true
+}