[lxc-devel] [lxd/master] Proxy: Improves validation

tomponline on Github lxc-bot at linuxcontainers.org
Wed Apr 22 13:39:21 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 501 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200422/c32f508d/attachment.bin>
-------------- next part --------------
From b1ce57fa647512765633c81313d5f03694c533d4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 13:46:43 +0100
Subject: [PATCH 1/4] lxd/device/proxy: Dont allow proxy_protocol to be set
 when in nat mode

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/proxy.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/device/proxy.go b/lxd/device/proxy.go
index 4e25213b58..94ba00d614 100644
--- a/lxd/device/proxy.go
+++ b/lxd/device/proxy.go
@@ -96,8 +96,8 @@ func (d *proxy) validateConfig(instConf instance.ConfigReader) error {
 		return fmt.Errorf("Cannot map a single port to multiple ports")
 	}
 
-	if shared.IsTrue(d.config["proxy_protocol"]) && !strings.HasPrefix(d.config["connect"], "tcp") {
-		return fmt.Errorf("The PROXY header can only be sent to tcp servers")
+	if shared.IsTrue(d.config["proxy_protocol"]) && (!strings.HasPrefix(d.config["connect"], "tcp") || shared.IsTrue(d.config["nat"])) {
+		return fmt.Errorf("The PROXY header can only be sent to tcp servers in non-nat mode")
 	}
 
 	if (!strings.HasPrefix(d.config["listen"], "unix:") || strings.HasPrefix(d.config["listen"], "unix:@")) &&

From c9ba14de5f5f858ace3114b007551bf1c3082b94 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 13:53:02 +0100
Subject: [PATCH 2/4] lxd/device/proxy: Dont wrap lines

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/proxy.go | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lxd/device/proxy.go b/lxd/device/proxy.go
index 94ba00d614..5ebf13845a 100644
--- a/lxd/device/proxy.go
+++ b/lxd/device/proxy.go
@@ -111,10 +111,8 @@ func (d *proxy) validateConfig(instConf instance.ConfigReader) error {
 		}
 
 		// Support TCP <-> TCP and UDP <-> UDP
-		if listenAddr.ConnType == "unix" || connectAddr.ConnType == "unix" ||
-			listenAddr.ConnType != connectAddr.ConnType {
-			return fmt.Errorf("Proxying %s <-> %s is not supported when using NAT",
-				listenAddr.ConnType, connectAddr.ConnType)
+		if listenAddr.ConnType == "unix" || connectAddr.ConnType == "unix" || listenAddr.ConnType != connectAddr.ConnType {
+			return fmt.Errorf("Proxying %s <-> %s is not supported when using NAT", listenAddr.ConnType, connectAddr.ConnType)
 		}
 	}
 

From 9ea65ca58f29f2fef8bf5d5b10b8dc777a2ddb58 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 14:24:58 +0100
Subject: [PATCH 3/4] lxd/device/proxy: Improves validation

	Prevents listening on wildcard addresses in NAT mode.
	Prevents mixing different IP version addresses in listen and connect in NAT mode.

Fixes #7221

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/proxy.go | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/lxd/device/proxy.go b/lxd/device/proxy.go
index 5ebf13845a..0351c43100 100644
--- a/lxd/device/proxy.go
+++ b/lxd/device/proxy.go
@@ -114,6 +114,43 @@ func (d *proxy) validateConfig(instConf instance.ConfigReader) error {
 		if listenAddr.ConnType == "unix" || connectAddr.ConnType == "unix" || listenAddr.ConnType != connectAddr.ConnType {
 			return fmt.Errorf("Proxying %s <-> %s is not supported when using NAT", listenAddr.ConnType, connectAddr.ConnType)
 		}
+
+		var ipVersion uint // Records which IP version we are using, as these cannot be mixed in NAT mode.
+
+		for _, listenAddrStr := range listenAddr.Addr {
+			ipStr, _, err := net.SplitHostPort(listenAddrStr)
+			if err != nil {
+				return err
+			}
+
+			ip := net.ParseIP(ipStr)
+
+			if ip.Equal(net.IPv4zero) || ip.Equal(net.IPv6zero) {
+				return fmt.Errorf("Cannot listen on wildcard address %q when in nat mode", ip)
+			}
+
+			// Record the listen IP version if not record already.
+			if ipVersion == 0 {
+				if ip.To4() == nil {
+					ipVersion = 6
+				} else {
+					ipVersion = 4
+				}
+			}
+		}
+
+		// Check each connect address against the listen IP version and check they match.
+		for _, connectAddrStr := range connectAddr.Addr {
+			ipStr, _, err := net.SplitHostPort(connectAddrStr)
+			if err != nil {
+				return err
+			}
+
+			ipTo4 := net.ParseIP(ipStr).To4()
+			if ipTo4 == nil && ipVersion != 6 || ipTo4 != nil && ipVersion != 4 {
+				return fmt.Errorf("Cannot mix IP versions between listen and connect in nat mode")
+			}
+		}
 	}
 
 	return nil

From 8d093b1442d7214656c8590476587e3a720637e8 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 14:37:51 +0100
Subject: [PATCH 4/4] test/suites/container/devices/proxy: Updates tests with
 new validation rules

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 test/suites/container_devices_proxy.sh | 27 ++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/test/suites/container_devices_proxy.sh b/test/suites/container_devices_proxy.sh
index 0b8eed5c5f..c71e2d1e7f 100644
--- a/test/suites/container_devices_proxy.sh
+++ b/test/suites/container_devices_proxy.sh
@@ -21,6 +21,32 @@ container_devices_proxy_validation() {
     false
   fi
 
+  # Check using wildcard addresses isn't allowed in NAT mode.
+  if lxc config device add proxyTester proxyDev proxy "listen=tcp:0.0.0.0:$HOST_TCP_PORT" connect=tcp:0.0.0.0:4321 nat=true ; then
+    echo "Proxy device shouldn't allow wildcard IPv4 listen addresses in NAT mode"
+    false
+  fi
+  if lxc config device add proxyTester proxyDev proxy "listen=tcp:[::]:$HOST_TCP_PORT" connect=tcp:0.0.0.0:4321 nat=true ; then
+    echo "Proxy device shouldn't allow wildcard IPv6 listen addresses in NAT mode"
+    false
+  fi
+
+  # Check using mixing IP versions in listen/connect addresses isn't allowed in NAT mode.
+  if lxc config device add proxyTester proxyDev proxy "listen=tcp:127.0.0.1:$HOST_TCP_PORT" connect=tcp:[::]:4321 nat=true ; then
+    echo "Proxy device shouldn't allow mixing IP address versions in NAT mode"
+    false
+  fi
+  if lxc config device add proxyTester proxyDev proxy "listen=tcp:[::1]:$HOST_TCP_PORT" connect=tcp:0.0.0.0:4321 nat=true ; then
+    echo "Proxy device shouldn't allow mixing IP address versions in NAT mode"
+    false
+  fi
+
+  # Check user proxy_protocol isn't allowed in NAT mode.
+  if lxc config device add proxyTester proxyDev proxy "listen=tcp:[::1]:$HOST_TCP_PORT" connect=tcp:[::]:4321 nat=true proxy_protocol=true ; then
+    echo "Proxy device shouldn't allow proxy_protocol in NAT mode"
+    false
+  fi
+
   # Check that old invalid config doesn't prevent device being stopped and removed cleanly.
   lxc config device add proxyTester proxyDev proxy "listen=tcp:127.0.0.1:$HOST_TCP_PORT" connect=tcp:127.0.0.1:4321 bind=host
   lxd sql global "UPDATE instances_devices_config SET value='tcp:localhost:4321' WHERE value='tcp:127.0.0.1:4321';"
@@ -29,6 +55,7 @@ container_devices_proxy_validation() {
   # Add the device again with the same listen param so if the old process hasn't been stopped it will fail to start.
   lxc config device add proxyTester proxyDev proxy "listen=tcp:127.0.0.1:$HOST_TCP_PORT" connect=tcp:127.0.0.1:4321 bind=host
 
+
   lxc delete -f proxyTester
 }
 


More information about the lxc-devel mailing list