The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/4820
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === The current implementation of the NAT feature in LXD causes some issues when it should collaborate with firewall/IPsec packages. This patch adds therefor some flexibility within LXD on how firewall rules are handled. This espacially comes into play during restarts of lxd(8). The ipv[46].nat configuration options are advanced to accept the following options: - true|insert: the firewall rule is insert at the beginning of the POSTROUTING table - false: no rule is added - append: the iptables rule is appended at the end of the POSTROUTING table To keep the configuration options backwards compatible the old value "true" and "false" are kept.
From 0c040ded97bd8389313a000f934bf7bfba3a1232 Mon Sep 17 00:00:00 2001 From: oms-kauz <ad...@kauz.net> Date: Sat, 21 Jul 2018 07:13:56 +0000 Subject: [PATCH] Allow NAT rule to be appended to POSTROUTING table The current implementation of the NAT feature in LXD causes some issues when it should collaborate with firewall/IPsec packages. This patch adds therefor some flexibility within LXD on how firewall rules are handled. This espacially comes into play during restarts of lxd(8). The ipv[46].nat configuration options are advanced to accept the following options: - true|insert: the firewall rule is insert at the beginning of the POSTROUTING table - false: no rule is added - append: the iptables rule is appended at the end of the POSTROUTING table To keep the configuration options backwards compatible the old value "true" and "false" are kept. --- doc/networks.md | 4 ++-- lxd/networks.go | 16 ++++++++++++---- lxd/networks_config.go | 8 ++++++-- lxd/networks_iptables.go | 13 ++++++++++--- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/doc/networks.md b/doc/networks.md index 2b29b7a0c..767708371 100644 --- a/doc/networks.md +++ b/doc/networks.md @@ -36,7 +36,7 @@ ipv4.dhcp.expiry | string | ipv4 dhcp | 1h ipv4.dhcp.gateway | string | ipv4 dhcp | ipv4.address | Address of the gateway for the subnet ipv4.dhcp.ranges | string | ipv4 dhcp | all addresses | Comma separated list of IP ranges to use for DHCP (FIRST-LAST format) ipv4.firewall | boolean | ipv4 address | true | Whether to generate filtering firewall rules for this network -ipv4.nat | boolean | ipv4 address | false | Whether to NAT (will default to true if unset and a random ipv4.address is generated) +ipv4.nat | string | ipv4 address | false | Whether and how to NAT ("true" / "insert" a NAT rule is inserted into the NAT table, "append" a NAT rule is appended into the NAT table, "false" no rule generated). It will default to "true"/"insert" if unset and a random ipv4.address is generated) ipv4.routes | string | ipv4 address | - | Comma separated list of additional IPv4 CIDR subnets to route to the bridge ipv4.routing | boolean | ipv4 address | true | Whether to route traffic in and out of the bridge ipv6.address | string | standard mode | random unused subnet | IPv6 address for the bridge (CIDR notation). Use "none" to turn off IPv6 or "auto" to generate a new one @@ -45,7 +45,7 @@ ipv6.dhcp.expiry | string | ipv6 dhcp | 1h ipv6.dhcp.ranges | string | ipv6 stateful dhcp | all addresses | Comma separated list of IPv6 ranges to use for DHCP (FIRST-LAST format) ipv6.dhcp.stateful | boolean | ipv6 dhcp | false | Whether to allocate addresses using DHCP ipv6.firewall | boolean | ipv6 address | true | Whether to generate filtering firewall rules for this network -ipv6.nat | boolean | ipv6 address | false | Whether to NAT (will default to true if unset and a random ipv6.address is generated) +ipv6.nat | string | ipv6 address | false | Whether and how to NAT ("true" / "insert" a NAT rule is inserted into the NAT table, "append" a NAT rule is appended into the NAT table, "false" no rule generated). It will default to "true"/"insert" if unset and a random ipv4.address is generated) ipv6.routes | string | ipv6 address | - | Comma separated list of additional IPv6 CIDR subnets to route to the bridge ipv6.routing | boolean | ipv6 address | true | Whether to route traffic in and out of the bridge raw.dnsmasq | string | - | - | Additional dnsmasq configuration to append to the configuration diff --git a/lxd/networks.go b/lxd/networks.go index b81963be4..1f40703ea 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -1225,8 +1225,12 @@ func (n *network) Start() error { } // Configure NAT - if shared.IsTrue(n.config["ipv4.nat"]) { - err = networkIptablesPrepend("ipv4", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + if !shared.StringInSlice(n.config["ipv4.nat"], []string{"", "false"}) { + if shared.StringInSlice(n.config["ipv4.nat"], []string{"true", "insert"}) { + err = networkIptablesPrepend("ipv4", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + } else { // "append" + err = networkIptablesAppend("ipv4", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + } if err != nil { return err } @@ -1387,8 +1391,12 @@ func (n *network) Start() error { } // Configure NAT - if shared.IsTrue(n.config["ipv6.nat"]) { - err = networkIptablesPrepend("ipv6", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + if !shared.StringInSlice(n.config["ipv6.nat"], []string{"", "false"}) { + if shared.StringInSlice(n.config["ipv6.nat"], []string{"true", "insert"}) { + err = networkIptablesPrepend("ipv6", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + } else { // "append" + err = networkIptablesAppend("ipv6", n.name, "nat", "POSTROUTING", "-s", subnet.String(), "!", "-d", subnet.String(), "-j", "MASQUERADE") + } if err != nil { return err } diff --git a/lxd/networks_config.go b/lxd/networks_config.go index 5c79a9d86..c6dfcf618 100644 --- a/lxd/networks_config.go +++ b/lxd/networks_config.go @@ -61,7 +61,9 @@ var networkConfigKeys = map[string]func(value string) error{ return networkValidAddressCIDRV4(value) }, "ipv4.firewall": shared.IsBool, - "ipv4.nat": shared.IsBool, + "ipv4.nat": func(value string) error { + return shared.IsOneOf(value, []string{"true", "append", "insert", "false"}) + }, "ipv4.dhcp": shared.IsBool, "ipv4.dhcp.gateway": networkValidAddressV4, "ipv4.dhcp.expiry": shared.IsAny, @@ -77,7 +79,9 @@ var networkConfigKeys = map[string]func(value string) error{ return networkValidAddressCIDRV6(value) }, "ipv6.firewall": shared.IsBool, - "ipv6.nat": shared.IsBool, + "ipv6.nat": func(value string) error { + return shared.IsOneOf(value, []string{"true", "append", "insert", "false"}) + }, "ipv6.dhcp": shared.IsBool, "ipv6.dhcp.expiry": shared.IsAny, "ipv6.dhcp.stateful": shared.IsBool, diff --git a/lxd/networks_iptables.go b/lxd/networks_iptables.go index 1c0c2bc88..1dbaf65d3 100644 --- a/lxd/networks_iptables.go +++ b/lxd/networks_iptables.go @@ -8,7 +8,7 @@ import ( "github.com/lxc/lxd/shared" ) -func networkIptablesPrepend(protocol string, netName string, table string, chain string, rule ...string) error { +func networkIptablesConfig(protocol string, netName string, table string, method string, chain string, rule ...string) error { cmd := "iptables" if protocol == "ipv6" { cmd = "ip6tables" @@ -34,8 +34,7 @@ func networkIptablesPrepend(protocol string, netName string, table string, chain return nil } - // Add the rule - args = append(baseArgs, []string{"-I", chain}...) + args = append(baseArgs, []string{method, chain}...) args = append(args, rule...) args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for LXD network %s", netName)) @@ -47,6 +46,14 @@ func networkIptablesPrepend(protocol string, netName string, table string, chain return nil } +func networkIptablesAppend(protocol string, netName string, table string, chain string, rule ...string) error { + return networkIptablesConfig(protocol, netName, table, "-A", chain, rule...) +} + +func networkIptablesPrepend(protocol string, netName string, table string, chain string, rule ...string) error { + return networkIptablesConfig(protocol, netName, table, "-I", chain, rule...) +} + func networkIptablesClear(protocol string, netName string, table string) error { // Detect kernels that lack IPv6 support if !shared.PathExists("/proc/sys/net/ipv6") && protocol == "ipv6" {
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel