[lxc-devel] [lxd/master] Bridged IP Filtering no parent IP fix
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Aug 1 20:46:04 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 427 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190801/7d603f2b/attachment.bin>
-------------- next part --------------
From 05e2b336f05fdb8b058bd43667322a56de227164 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 1 Aug 2019 21:43:25 +0100
Subject: [PATCH 1/2] device/nic/bridged: Fixes issue with non-dhcp,
non-addressed parent device
IP filtering wasn't working on a parent bridge that did not have managed DHCP or any IP addresses on host.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/nic_bridged.go | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index d2f08a3dc7..15deced6a0 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -74,15 +74,6 @@ func (d *nicBridged) validateConfig() error {
return err
}
- // If parent isn't a managed network, check that no managed-only features are enabled.
- if !shared.PathExists(shared.VarPath("networks", d.config["parent"], "dnsmasq.pid")) {
- for _, k := range []string{"ipv4.address", "ipv6.address", "security.mac_filtering", "security.ipv4_filtering", "security.ipv6_filtering"} {
- if d.config[k] != "" || shared.IsTrue(d.config[k]) {
- return fmt.Errorf("%s can only be used with managed networks", k)
- }
- }
- }
-
return nil
}
@@ -620,14 +611,17 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) {
netConfig := dbInfo.Config
+ canIPv4Allocate := netConfig["ipv4.address"] != "" && netConfig["ipv4.address"] != "none" && (netConfig["ipv4.dhcp"] == "" || shared.IsTrue(netConfig["ipv4.dhcp"]))
+ canIPv6Allocate := netConfig["ipv6.address"] != "" && netConfig["ipv6.address"] != "none" && (netConfig["ipv4.dhcp"] == "" || shared.IsTrue(netConfig["ipv4.dhcp"]))
+
// Check DHCPv4 is enabled on parent if dynamic IPv4 allocation is needed.
- if shared.IsTrue(d.config["security.ipv4_filtering"]) && IPv4 == nil && netConfig["ipv4.dhcp"] != "" && !shared.IsTrue(netConfig["ipv4.dhcp"]) {
- return nil, nil, fmt.Errorf("Cannot use security.ipv4_filtering as DHCPv4 is disabled on parent %s and no static IPv4 address set", d.config["parent"])
+ if shared.IsTrue(d.config["security.ipv4_filtering"]) && IPv4 == nil && !canIPv4Allocate {
+ return nil, nil, fmt.Errorf("Cannot use security.ipv4_filtering as DHCPv4 is disabled or no IPv4 on parent %s and no static IPv4 address set", d.config["parent"])
}
// Check DHCPv6 is enabled on parent if dynamic IPv6 allocation is needed.
- if shared.IsTrue(d.config["security.ipv6_filtering"]) && IPv6 == nil && netConfig["ipv6.dhcp"] != "" && !shared.IsTrue(netConfig["ipv6.dhcp"]) {
- return nil, nil, fmt.Errorf("Cannot use security.ipv6_filtering as DHCPv6 is disabled on parent %s and no static IPv6 address set", d.config["parent"])
+ if shared.IsTrue(d.config["security.ipv6_filtering"]) && IPv6 == nil && !canIPv6Allocate {
+ return nil, nil, fmt.Errorf("Cannot use security.ipv6_filtering as DHCPv6 is disabled or no IPv6 on parent %s and no static IPv6 address set", d.config["parent"])
}
dnsmasq.ConfigMutex.Lock()
@@ -640,7 +634,7 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) {
}
// If no static IPv4, then check if there is a valid static DHCP IPv4 address defined.
- if IPv4 == nil && curIPv4.IP != nil {
+ if IPv4 == nil && curIPv4.IP != nil && canIPv4Allocate {
_, subnet, err := net.ParseCIDR(netConfig["ipv4.address"])
if err != nil {
return nil, nil, err
@@ -655,7 +649,7 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) {
}
// If no static IPv6, then check if there is a valid static DHCP IPv6 address defined.
- if IPv6 == nil && curIPv6.IP != nil {
+ if IPv6 == nil && curIPv6.IP != nil && canIPv6Allocate {
_, subnet, err := net.ParseCIDR(netConfig["ipv6.address"])
if err != nil {
return IPv4, IPv6, err
@@ -670,23 +664,23 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) {
}
// If we need to generate either a new IPv4 or IPv6, load existing IPs used in network.
- if IPv4 == nil || IPv6 == nil {
+ if (IPv4 == nil && canIPv4Allocate) || (IPv6 == nil && canIPv6Allocate) {
// Get existing allocations in network.
IPv4Allocs, IPv6Allocs, err := d.getDHCPAllocatedIPs(d.config["parent"])
if err != nil {
return nil, nil, err
}
- // Allocate a new IPv4 address is IPv4 filtering enabled.
- if IPv4 == nil && shared.IsTrue(d.config["security.ipv4_filtering"]) {
+ // Allocate a new IPv4 address if IPv4 filtering enabled.
+ if IPv4 == nil && canIPv4Allocate && shared.IsTrue(d.config["security.ipv4_filtering"]) {
IPv4, err = d.getDHCPFreeIPv4(IPv4Allocs, netConfig, d.instance.Name(), d.config["hwaddr"])
if err != nil {
return nil, nil, err
}
}
- // Allocate a new IPv6 address is IPv6 filtering enabled.
- if IPv6 == nil && shared.IsTrue(d.config["security.ipv6_filtering"]) {
+ // Allocate a new IPv6 address if IPv6 filtering enabled.
+ if IPv6 == nil && canIPv6Allocate && shared.IsTrue(d.config["security.ipv6_filtering"]) {
IPv6, err = d.getDHCPFreeIPv6(IPv6Allocs, netConfig, d.instance.Name(), d.config["hwaddr"])
if err != nil {
return nil, nil, err
@@ -694,8 +688,9 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) {
}
}
- // If either IPv4 or IPv6 assigned is different than what is in dnsmasq config, rebuild config.
- if (IPv4 != nil && bytes.Compare(curIPv4.IP, IPv4.To4()) != 0) || (IPv6 != nil && bytes.Compare(curIPv6.IP, IPv6.To16()) != 0) {
+ // If parent is a DHCP enabled managed network and either IPv4 or IPv6 assigned is different than what is in dnsmasq config, rebuild config.
+ if shared.PathExists(shared.VarPath("networks", d.config["parent"], "dnsmasq.pid")) &&
+ ((IPv4 != nil && bytes.Compare(curIPv4.IP, IPv4.To4()) != 0) || (IPv6 != nil && bytes.Compare(curIPv6.IP, IPv6.To16()) != 0)) {
var IPv4Str, IPv6Str string
if IPv4 != nil {
From cc7b85330c59088f8de720c480450de14a6a0807 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 1 Aug 2019 21:44:19 +0100
Subject: [PATCH 2/2] test: Updates nic bridged filtering tests for non-IP
addressed parent
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
.../container_devices_nic_bridged_filtering.sh | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/test/suites/container_devices_nic_bridged_filtering.sh b/test/suites/container_devices_nic_bridged_filtering.sh
index a94c43b009..23ace8c2b7 100644
--- a/test/suites/container_devices_nic_bridged_filtering.sh
+++ b/test/suites/container_devices_nic_bridged_filtering.sh
@@ -315,12 +315,24 @@ test_container_devices_nic_bridged_filtering() {
lxc delete -f "${ctPrefix}A"
lxc delete -f "${ctPrefix}B"
- # Check filtering works with non-DHCP statically defined IPs.
+ # Check filtering works with non-DHCP statically defined IPs and a bridge with no IP address and DHCP disabled.
lxc network set "${brName}" ipv4.dhcp false
+ lxc network set "${brName}" ipv4.address none
+
lxc network set "${brName}" ipv6.dhcp false
+ lxc network set "${brName}" ipv6.address none
+
lxc network set "${brName}" ipv6.dhcp.stateful false
lxc init testimage "${ctPrefix}A" -p "${ctPrefix}"
- lxc config device add "${ctPrefix}A" eth0 nic nictype=nic name=eth0 nictype=bridged parent="${brName}" ipv4.address=192.0.2.2 ipv6.address=2001:db8::2 security.ipv4_filtering=true security.ipv6_filtering=true
+ lxc config device add "${ctPrefix}A" eth0 nic \
+ nictype=nic \
+ name=eth0 \
+ nictype=bridged \
+ parent="${brName}" \
+ ipv4.address=192.0.2.2 \
+ ipv6.address=2001:db8::2 \
+ security.ipv4_filtering=true \
+ security.ipv6_filtering=true
lxc start "${ctPrefix}A"
# Check MAC filter is present in ebtables.
More information about the lxc-devel
mailing list