Browse Source

pkg: listeners: move Docker-specific semantics to docker/daemon*

Since there are other users of pkg/listeners, it doesn't make sense to
contain Docker-specific semantics and warnings inside it. To that end,
move the scary warning about -tlsverify and the libnetwork port
allocation code to CmdDaemon (where they belong). This helps massively
reduce the dependency tree for users of pkg/listeners.

Signed-off-by: Aleksa Sarai <asarai@suse.de>
Aleksa Sarai 9 years ago
parent
commit
5ee0a94101

+ 15 - 2
docker/daemon.go

@@ -250,11 +250,24 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
 		if len(protoAddrParts) != 2 {
 			logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr)
 		}
-		l, err := listeners.Init(protoAddrParts[0], protoAddrParts[1], serverConfig.SocketGroup, serverConfig.TLSConfig)
+
+		proto := protoAddrParts[0]
+		addr := protoAddrParts[1]
+
+		// It's a bad idea to bind to TCP without tlsverify.
+		if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
+			logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
+		}
+		l, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
 		if err != nil {
 			logrus.Fatal(err)
 		}
-
+		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
+		if proto == "tcp" {
+			if err := allocateDaemonPort(addr); err != nil {
+				logrus.Fatal(err)
+			}
+		}
 		logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
 		api.Accept(protoAddrParts[1], l...)
 	}

+ 32 - 0
docker/daemon_unix.go

@@ -4,9 +4,11 @@ package main
 
 import (
 	"fmt"
+	"net"
 	"os"
 	"os/signal"
 	"path/filepath"
+	"strconv"
 	"syscall"
 
 	"github.com/Sirupsen/logrus"
@@ -15,6 +17,7 @@ import (
 	"github.com/docker/docker/libcontainerd"
 	"github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/system"
+	"github.com/docker/libnetwork/portallocator"
 )
 
 const defaultDaemonConfigFile = "/etc/docker/daemon.json"
@@ -87,3 +90,32 @@ func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
 func (cli *DaemonCli) getLibcontainerdRoot() string {
 	return filepath.Join(cli.Config.ExecRoot, "libcontainerd")
 }
+
+// allocateDaemonPort ensures that there are no containers
+// that try to use any port allocated for the docker server.
+func allocateDaemonPort(addr string) error {
+	host, port, err := net.SplitHostPort(addr)
+	if err != nil {
+		return err
+	}
+
+	intPort, err := strconv.Atoi(port)
+	if err != nil {
+		return err
+	}
+
+	var hostIPs []net.IP
+	if parsedIP := net.ParseIP(host); parsedIP != nil {
+		hostIPs = append(hostIPs, parsedIP)
+	} else if hostIPs, err = net.LookupIP(host); err != nil {
+		return fmt.Errorf("failed to lookup %s address in host specification", host)
+	}
+
+	pa := portallocator.Get()
+	for _, hostIP := range hostIPs {
+		if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
+			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
+		}
+	}
+	return nil
+}

+ 4 - 0
docker/daemon_windows.go

@@ -69,3 +69,7 @@ func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
 func (cli *DaemonCli) getLibcontainerdRoot() string {
 	return ""
 }
+
+func allocateDaemonPort(addr string) error {
+	return nil
+}

+ 0 - 24
pkg/listeners/listeners.go

@@ -1,24 +0,0 @@
-package listeners
-
-import (
-	"crypto/tls"
-	"net"
-
-	"github.com/Sirupsen/logrus"
-	"github.com/docker/go-connections/sockets"
-)
-
-func initTCPSocket(addr string, tlsConfig *tls.Config) (l net.Listener, err error) {
-	if tlsConfig == nil || tlsConfig.ClientAuth != tls.RequireAndVerifyClientCert {
-		// TODO: Move this outside pkg/listeners since it's Docker-specific.
-		//       ... and slightly scary.
-		logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
-	}
-	if l, err = sockets.NewTCPSocket(addr, tlsConfig); err != nil {
-		return nil, err
-	}
-	if err := allocateDaemonPort(addr); err != nil {
-		return nil, err
-	}
-	return
-}

+ 8 - 36
pkg/listeners/listeners_unix.go

@@ -11,19 +11,22 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/coreos/go-systemd/activation"
 	"github.com/docker/go-connections/sockets"
-	"github.com/docker/libnetwork/portallocator"
 )
 
 // Init creates new listeners for the server.
-func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.Listener, err error) {
+// TODO: Clean up the fact that socketGroup and tlsConfig aren't always used.
+func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) ([]net.Listener, error) {
+	ls := []net.Listener{}
+
 	switch proto {
 	case "fd":
-		ls, err = listenFD(addr, tlsConfig)
+		fds, err := listenFD(addr, tlsConfig)
 		if err != nil {
 			return nil, err
 		}
+		ls = append(ls, fds...)
 	case "tcp":
-		l, err := initTCPSocket(addr, tlsConfig)
+		l, err := sockets.NewTCPSocket(addr, tlsConfig)
 		if err != nil {
 			return nil, err
 		}
@@ -38,7 +41,7 @@ func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.List
 		return nil, fmt.Errorf("invalid protocol format: %q", proto)
 	}
 
-	return
+	return ls, nil
 }
 
 // listenFD returns the specified socket activated files as a slice of
@@ -89,34 +92,3 @@ func listenFD(addr string, tlsConfig *tls.Config) ([]net.Listener, error) {
 	}
 	return []net.Listener{listeners[fdOffset]}, nil
 }
-
-// allocateDaemonPort ensures that there are no containers
-// that try to use any port allocated for the docker server.
-// TODO: Move this outside pkg/listeners since it's Docker-specific, and requires
-//       libnetwork which increases the dependency tree quite drastically.
-func allocateDaemonPort(addr string) error {
-	host, port, err := net.SplitHostPort(addr)
-	if err != nil {
-		return err
-	}
-
-	intPort, err := strconv.Atoi(port)
-	if err != nil {
-		return err
-	}
-
-	var hostIPs []net.IP
-	if parsedIP := net.ParseIP(host); parsedIP != nil {
-		hostIPs = append(hostIPs, parsedIP)
-	} else if hostIPs, err = net.LookupIP(host); err != nil {
-		return fmt.Errorf("failed to lookup %s address in host specification", host)
-	}
-
-	pa := portallocator.Get()
-	for _, hostIP := range hostIPs {
-		if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
-			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
-		}
-	}
-	return nil
-}

+ 6 - 9
pkg/listeners/listeners_windows.go

@@ -7,13 +7,16 @@ import (
 	"strings"
 
 	"github.com/Microsoft/go-winio"
+	"github.com/docker/go-connections/sockets"
 )
 
 // Init creates new listeners for the server.
-func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.Listener, err error) {
+func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) ([]net.Listener, error) {
+	ls := []net.Listener{}
+
 	switch proto {
 	case "tcp":
-		l, err := initTCPSocket(addr, tlsConfig)
+		l, err := sockets.NewTCPSocket(addr, tlsConfig)
 		if err != nil {
 			return nil, err
 		}
@@ -47,11 +50,5 @@ func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.List
 		return nil, fmt.Errorf("invalid protocol format: windows only supports tcp and npipe")
 	}
 
-	return
-}
-
-// allocateDaemonPort ensures that there are no containers
-// that try to use any port allocated for the docker server.
-func allocateDaemonPort(addr string) error {
-	return nil
+	return ls, nil
 }