瀏覽代碼

Merge pull request #1115 from sanimej/thread

Move the iptables setup for embedded DNS into a reexec process
Alessandro Boch 9 年之前
父節點
當前提交
23d46777a8
共有 3 個文件被更改,包括 89 次插入18 次删除
  1. 5 18
      libnetwork/resolver.go
  2. 77 0
      libnetwork/resolver_unix.go
  3. 7 0
      libnetwork/resolver_windows.go

+ 5 - 18
libnetwork/resolver.go

@@ -9,7 +9,6 @@ import (
 	"time"
 
 	log "github.com/Sirupsen/logrus"
-	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/types"
 	"github.com/miekg/dns"
 )
@@ -105,8 +104,6 @@ func (r *resolver) SetupFunc() func() {
 			r.err = fmt.Errorf("error in opening name server socket %v", err)
 			return
 		}
-		laddr := r.conn.LocalAddr()
-		_, ipPort, _ := net.SplitHostPort(laddr.String())
 
 		// Listen on a TCP as well
 		tcpaddr := &net.TCPAddr{
@@ -118,21 +115,6 @@ func (r *resolver) SetupFunc() func() {
 			r.err = fmt.Errorf("error in opening name TCP server socket %v", err)
 			return
 		}
-		ltcpaddr := r.tcpListen.Addr()
-		_, tcpPort, _ := net.SplitHostPort(ltcpaddr.String())
-		rules := [][]string{
-			{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", laddr.String()},
-			{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
-			{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", ltcpaddr.String()},
-			{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
-		}
-
-		for _, rule := range rules {
-			r.err = iptables.RawCombinedOutputNative(rule...)
-			if r.err != nil {
-				return
-			}
-		}
 		r.err = nil
 	})
 }
@@ -142,6 +124,11 @@ func (r *resolver) Start() error {
 	if r.err != nil {
 		return r.err
 	}
+
+	if err := r.setupIPTable(); err != nil {
+		return fmt.Errorf("setting up IP table rules failed: %v", err)
+	}
+
 	s := &dns.Server{Handler: r, PacketConn: r.conn}
 	r.server = s
 	go func() {

+ 77 - 0
libnetwork/resolver_unix.go

@@ -0,0 +1,77 @@
+// +build !windows
+
+package libnetwork
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"os/exec"
+	"runtime"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/docker/docker/pkg/reexec"
+	"github.com/docker/libnetwork/iptables"
+	"github.com/vishvananda/netns"
+)
+
+func init() {
+	reexec.Register("setup-resolver", reexecSetupResolver)
+}
+
+func reexecSetupResolver() {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	if len(os.Args) < 4 {
+		log.Error("invalid number of arguments..")
+		os.Exit(1)
+	}
+
+	_, ipPort, _ := net.SplitHostPort(os.Args[2])
+	_, tcpPort, _ := net.SplitHostPort(os.Args[3])
+	rules := [][]string{
+		{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[2]},
+		{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
+		{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[3]},
+		{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
+	}
+
+	f, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0)
+	if err != nil {
+		log.Errorf("failed get network namespace %q: %v", os.Args[1], err)
+		os.Exit(2)
+	}
+	defer f.Close()
+
+	nsFD := f.Fd()
+	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
+		log.Errorf("setting into container net ns %v failed, %v", os.Args[1], err)
+		os.Exit(3)
+	}
+
+	for _, rule := range rules {
+		if iptables.RawCombinedOutputNative(rule...) != nil {
+			log.Errorf("setting up rule failed, %v", rule)
+		}
+	}
+}
+
+func (r *resolver) setupIPTable() error {
+	if r.err != nil {
+		return r.err
+	}
+	laddr := r.conn.LocalAddr().String()
+	ltcpaddr := r.tcpListen.Addr().String()
+
+	cmd := &exec.Cmd{
+		Path:   reexec.Self(),
+		Args:   append([]string{"setup-resolver"}, r.sb.Key(), laddr, ltcpaddr),
+		Stdout: os.Stdout,
+		Stderr: os.Stderr,
+	}
+	if err := cmd.Run(); err != nil {
+		return fmt.Errorf("reexec failed: %v", err)
+	}
+	return nil
+}

+ 7 - 0
libnetwork/resolver_windows.go

@@ -0,0 +1,7 @@
+// +build windows
+
+package libnetwork
+
+func (r *resolver) setupIPTable() error {
+	return nil
+}