[lxc-devel] [lxd/master] Allow NAT rule to be appended to POSTROUTING table
lxdicted on Github
lxc-bot at linuxcontainers.org
Sun Jul 22 05:22:30 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 966 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180722/6a05bae8/attachment.bin>
-------------- next part --------------
From 0c040ded97bd8389313a000f934bf7bfba3a1232 Mon Sep 17 00:00:00 2001
From: oms-kauz <admin at 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" {
More information about the lxc-devel
mailing list