[lxc-devel] [lxd/master] Firewall: xtables

tomponline on Github lxc-bot at linuxcontainers.org
Mon Feb 3 14:31:24 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200203/2e18b124/attachment.bin>
-------------- next part --------------
From 3cbe66814f206a1e09379c5207fe21018c1cc5de Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 3 Feb 2020 14:26:46 +0000
Subject: [PATCH 1/3] lxd/firewall: Moves iptables/xtables implementation into
 firewall/drivers package

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/firewall/{consts => drivers}/consts.go     | 2 +-
 lxd/{iptables => firewall/drivers}/iptables.go | 0
 lxd/{iptables => firewall/drivers}/xtables.go  | 0
 3 files changed, 1 insertion(+), 1 deletion(-)
 rename lxd/firewall/{consts => drivers}/consts.go (97%)
 rename lxd/{iptables => firewall/drivers}/iptables.go (100%)
 rename lxd/{iptables => firewall/drivers}/xtables.go (100%)

diff --git a/lxd/firewall/consts/consts.go b/lxd/firewall/drivers/consts.go
similarity index 97%
rename from lxd/firewall/consts/consts.go
rename to lxd/firewall/drivers/consts.go
index f0c1eda57e..297651d2fb 100644
--- a/lxd/firewall/consts/consts.go
+++ b/lxd/firewall/drivers/consts.go
@@ -1,4 +1,4 @@
-package consts
+package drivers
 
 // Location is used to determine whether a rule should be appended or prepended
 type Location int
diff --git a/lxd/iptables/iptables.go b/lxd/firewall/drivers/iptables.go
similarity index 100%
rename from lxd/iptables/iptables.go
rename to lxd/firewall/drivers/iptables.go
diff --git a/lxd/iptables/xtables.go b/lxd/firewall/drivers/xtables.go
similarity index 100%
rename from lxd/iptables/xtables.go
rename to lxd/firewall/drivers/xtables.go

From 4e45bbcc3e855ab9f37ecfd7b59eb660a84b7439 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 3 Feb 2020 14:29:21 +0000
Subject: [PATCH 2/3] lxd/firewall/drivers: Merges iptables helper functions
 into xtable struct

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/firewall/drivers/iptables.go | 137 ---------------------
 lxd/firewall/drivers/xtables.go  | 204 ++++++++++++++++++++++++-------
 2 files changed, 163 insertions(+), 178 deletions(-)
 delete mode 100644 lxd/firewall/drivers/iptables.go

diff --git a/lxd/firewall/drivers/iptables.go b/lxd/firewall/drivers/iptables.go
deleted file mode 100644
index 2ec75314d9..0000000000
--- a/lxd/firewall/drivers/iptables.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package iptables
-
-import (
-	"fmt"
-	"os/exec"
-	"strings"
-
-	"github.com/lxc/lxd/shared"
-)
-
-func iptablesConfig(protocol string, comment string, table string, method string, chain string,
-	rule ...string) error {
-	cmd := "iptables"
-	if protocol == "ipv6" {
-		cmd = "ip6tables"
-	}
-
-	_, err := exec.LookPath(cmd)
-	if err != nil {
-		return fmt.Errorf("Asked to setup %s firewalling but %s can't be found", protocol, cmd)
-	}
-
-	baseArgs := []string{"-w"}
-	if table == "" {
-		table = "filter"
-	}
-	baseArgs = append(baseArgs, []string{"-t", table}...)
-
-	// Check for an existing entry
-	args := append(baseArgs, []string{"-C", chain}...)
-	args = append(args, rule...)
-	args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for %s", comment))
-	_, err = shared.RunCommand(cmd, args...)
-	if err == nil {
-		return nil
-	}
-
-	args = append(baseArgs, []string{method, chain}...)
-	args = append(args, rule...)
-	args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for %s", comment))
-
-	_, err = shared.TryRunCommand(cmd, args...)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func iptablesAppend(protocol string, comment string, table string, chain string, rule ...string) error {
-	return iptablesConfig(protocol, comment, table, "-A", chain, rule...)
-}
-
-func iptablesPrepend(protocol string, comment string, table string, chain string, rule ...string) error {
-	return iptablesConfig(protocol, comment, table, "-I", chain, rule...)
-}
-
-func iptablesClear(protocol string, comment string, table string) error {
-	// Detect kernels that lack IPv6 support
-	if !shared.PathExists("/proc/sys/net/ipv6") && protocol == "ipv6" {
-		return nil
-	}
-
-	cmd := "iptables"
-	if protocol == "ipv6" {
-		cmd = "ip6tables"
-	}
-
-	_, err := exec.LookPath(cmd)
-	if err != nil {
-		return nil
-	}
-
-	baseArgs := []string{"-w"}
-	if table == "" {
-		table = "filter"
-	}
-	baseArgs = append(baseArgs, []string{"-t", table}...)
-
-	// List the rules
-	args := append(baseArgs, "-S")
-	output, err := shared.TryRunCommand(cmd, args...)
-	if err != nil {
-		return fmt.Errorf("Failed to list %s rules for %s (table %s)", protocol, comment, table)
-	}
-
-	for _, line := range strings.Split(output, "\n") {
-		if !strings.Contains(line, fmt.Sprintf("generated for %s", comment)) {
-			continue
-		}
-
-		// Remove the entry
-		fields := strings.Fields(line)
-		fields[0] = "-D"
-
-		args = append(baseArgs, fields...)
-		_, err = shared.TryRunCommand("sh", "-c", fmt.Sprintf("%s %s", cmd, strings.Join(args, " ")))
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-// NetworkAppend adds a network rule at end of ruleset.
-func NetworkAppend(protocol string, comment string, table string, chain string,
-	rule ...string) error {
-	return iptablesAppend(protocol, fmt.Sprintf("LXD network %s", comment),
-		table, chain, rule...)
-}
-
-// NetworkPrepend adds a network rule at start of ruleset.
-func NetworkPrepend(protocol string, comment string, table string, chain string,
-	rule ...string) error {
-	return iptablesPrepend(protocol, fmt.Sprintf("LXD network %s", comment),
-		table, chain, rule...)
-}
-
-// NetworkClear removes network rules.
-func NetworkClear(protocol string, comment string, table string) error {
-	return iptablesClear(protocol, fmt.Sprintf("LXD network %s", comment),
-		table)
-}
-
-// ContainerPrepend adds container rule at start of ruleset.
-func ContainerPrepend(protocol string, comment string, table string,
-	chain string, rule ...string) error {
-	return iptablesPrepend(protocol, fmt.Sprintf("LXD container %s", comment),
-		table, chain, rule...)
-}
-
-// ContainerClear removes container rules.
-func ContainerClear(protocol string, comment string, table string) error {
-	return iptablesClear(protocol, fmt.Sprintf("LXD container %s", comment),
-		table)
-}
diff --git a/lxd/firewall/drivers/xtables.go b/lxd/firewall/drivers/xtables.go
index 5b7c86a332..b7f6bf7373 100644
--- a/lxd/firewall/drivers/xtables.go
+++ b/lxd/firewall/drivers/xtables.go
@@ -1,13 +1,13 @@
-package iptables
+package drivers
 
 import (
 	"encoding/hex"
 	"fmt"
 	"net"
+	"os/exec"
 	"strings"
 
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
-	firewallConsts "github.com/lxc/lxd/lxd/firewall/consts"
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
 )
@@ -18,17 +18,17 @@ type XTables struct{}
 // Lower-level Functions
 
 // NetworkClear removes network rules.
-func (xt XTables) NetworkClear(family firewallConsts.Family, table firewallConsts.Table, comment string) error {
-	return NetworkClear(fmt.Sprintf("%s", family), comment, fmt.Sprintf("%s", table))
+func (d XTables) NetworkClear(family Family, table Table, comment string) error {
+	return d.networkClear(fmt.Sprintf("%s", family), comment, fmt.Sprintf("%s", table))
 }
 
 // InstanceClear removes rules all rules for the given instance.
-func (xt XTables) InstanceClear(family firewallConsts.Family, table firewallConsts.Table, comment string) error {
-	return ContainerClear(fmt.Sprintf("%s", family), comment, fmt.Sprintf("%s", table))
+func (d XTables) InstanceClear(family Family, table Table, comment string) error {
+	return d.containerClear(fmt.Sprintf("%s", family), comment, fmt.Sprintf("%s", table))
 }
 
 // VerifyIPv6Module checks to see if the ipv6 kernel module is present.
-func (xt XTables) VerifyIPv6Module() error {
+func (d XTables) VerifyIPv6Module() error {
 	// Check br_netfilter is loaded and enabled for IPv6.
 	sysctlPath := "net/bridge/bridge-nf-call-ip6tables"
 	sysctlVal, err := util.SysctlGet(sysctlPath)
@@ -46,20 +46,20 @@ func (xt XTables) VerifyIPv6Module() error {
 // Proxy Functions
 
 // InstanceProxySetupNAT creates a default NAT setup.
-func (xt XTables) InstanceProxySetupNAT(family firewallConsts.Family, connType, address, port string, destAddr net.IP, destPort string, comment string) error {
+func (d XTables) InstanceProxySetupNAT(family Family, connType, address, port string, destAddr net.IP, destPort string, comment string) error {
 	toDest := fmt.Sprintf("%s:%s", destAddr, destPort)
 	if family == "ipv6" {
 		toDest = fmt.Sprintf("[%s]:%s", destAddr, destPort)
 	}
 
 	// outbound <-> container
-	err := ContainerPrepend(fmt.Sprintf("%s", family), comment, "nat", "PREROUTING", "-p", connType, "--destination", address, "--dport", port, "-j", "DNAT", "--to-destination", toDest)
+	err := d.containerPrepend(fmt.Sprintf("%s", family), comment, "nat", "PREROUTING", "-p", connType, "--destination", address, "--dport", port, "-j", "DNAT", "--to-destination", toDest)
 	if err != nil {
 		return err
 	}
 
 	// host <-> container
-	err = ContainerPrepend(fmt.Sprintf("%s", family), comment, "nat", "OUTPUT", "-p", connType, "--destination", address, "--dport", port, "-j", "DNAT", "--to-destination", toDest)
+	err = d.containerPrepend(fmt.Sprintf("%s", family), comment, "nat", "OUTPUT", "-p", connType, "--destination", address, "--dport", port, "-j", "DNAT", "--to-destination", toDest)
 	if err != nil {
 		return err
 	}
@@ -70,7 +70,7 @@ func (xt XTables) InstanceProxySetupNAT(family firewallConsts.Family, connType,
 // NIC Bridged Functions
 
 // InstanceNicBridgedRemoveFilters removes any non-standard rules from the nic instance.
-func (xt XTables) InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP) error {
+func (d XTables) InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP) error {
 	// Get a current list of rules active on the host.
 	out, err := shared.RunCommand("ebtables", "--concurrent", "-L", "--Lmac2", "--Lx")
 	if err != nil {
@@ -78,7 +78,7 @@ func (xt XTables) InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 ne
 	}
 
 	// Get a list of rules that we would have applied on instance start.
-	rules := generateFilterEbtablesRules(m, ipv4, ipv6)
+	rules := d.generateFilterEbtablesRules(m, ipv4, ipv6)
 
 	errs := []error{}
 	// Iterate through each active rule on the host and try and match it to one the LXD rules.
@@ -94,7 +94,7 @@ func (xt XTables) InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 ne
 			}
 
 			// Check whether active rule matches one of our rules to delete.
-			if !matchEbtablesRule(fields, rule, true) {
+			if !d.matchEbtablesRule(fields, rule, true) {
 				continue
 			}
 
@@ -115,8 +115,8 @@ func (xt XTables) InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 ne
 }
 
 // InstanceNicBridgedSetFilters sets the nic rules to standard filtering.
-func (xt XTables) InstanceNicBridgedSetFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP, comment string) error {
-	rules := generateFilterEbtablesRules(m, ipv4, ipv6)
+func (d XTables) InstanceNicBridgedSetFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP, comment string) error {
+	rules := d.generateFilterEbtablesRules(m, ipv4, ipv6)
 	for _, rule := range rules {
 		_, err := shared.RunCommand(rule[0], append([]string{"--concurrent"}, rule[1:]...)...)
 		if err != nil {
@@ -124,13 +124,13 @@ func (xt XTables) InstanceNicBridgedSetFilters(m deviceConfig.Device, ipv4 net.I
 		}
 	}
 
-	rules, err := generateFilterIptablesRules(m, ipv6)
+	rules, err := d.generateFilterIptablesRules(m, ipv6)
 	if err != nil {
 		return err
 	}
 
 	for _, rule := range rules {
-		err = ContainerPrepend(rule[0], fmt.Sprintf("%s - %s_filtering", comment, rule[0]), "filter", rule[1], rule[2:]...)
+		err = d.containerPrepend(rule[0], fmt.Sprintf("%s - %s_filtering", comment, rule[0]), "filter", rule[1], rule[2:]...)
 		if err != nil {
 			return err
 		}
@@ -142,20 +142,20 @@ func (xt XTables) InstanceNicBridgedSetFilters(m deviceConfig.Device, ipv4 net.I
 // Network Functions
 
 // NetworkSetupAllowForwarding allows forwarding dependent on boolean argument
-func (xt XTables) NetworkSetupAllowForwarding(family firewallConsts.Family, name string, actionType firewallConsts.Action) error {
+func (d XTables) NetworkSetupAllowForwarding(family Family, name string, actionType Action) error {
 	forwardType := "DROP"
-	if actionType == firewallConsts.ActionAccept {
+	if actionType == ActionAccept {
 		forwardType = "ACCEPT"
-	} else if actionType == firewallConsts.ActionReject {
+	} else if actionType == ActionReject {
 		forwardType = "REJECT"
 	}
 
-	err := NetworkPrepend(fmt.Sprintf("%s", family), name, "", "FORWARD", "-i", name, "-j", forwardType)
+	err := d.networkPrepend(fmt.Sprintf("%s", family), name, "", "FORWARD", "-i", name, "-j", forwardType)
 	if err != nil {
 		return err
 	}
 
-	err = NetworkPrepend(fmt.Sprintf("%s", family), name, "", "FORWARD", "-o", name, "-j", forwardType)
+	err = d.networkPrepend(fmt.Sprintf("%s", family), name, "", "FORWARD", "-o", name, "-j", forwardType)
 
 	if err != nil {
 		return err
@@ -165,14 +165,14 @@ func (xt XTables) NetworkSetupAllowForwarding(family firewallConsts.Family, name
 }
 
 // NetworkSetupNAT configures NAT
-func (xt XTables) NetworkSetupNAT(family firewallConsts.Family, name string, location firewallConsts.Location, args ...string) error {
-	if location == firewallConsts.LocationPrepend {
-		err := NetworkPrepend(fmt.Sprintf("%s", family), name, "nat", "POSTROUTING", args...)
+func (d XTables) NetworkSetupNAT(family Family, name string, location Location, args ...string) error {
+	if location == LocationPrepend {
+		err := d.networkPrepend(fmt.Sprintf("%s", family), name, "nat", "POSTROUTING", args...)
 		if err != nil {
 			return err
 		}
-	} else if location == firewallConsts.LocationAppend {
-		err := NetworkAppend(fmt.Sprintf("%s", family), name, "nat", "POSTROUTING", args...)
+	} else if location == LocationAppend {
+		err := d.networkAppend(fmt.Sprintf("%s", family), name, "nat", "POSTROUTING", args...)
 		if err != nil {
 			return err
 		}
@@ -182,7 +182,7 @@ func (xt XTables) NetworkSetupNAT(family firewallConsts.Family, name string, loc
 }
 
 // NetworkSetupIPv4DNSOverrides sets up basic iptables overrides for DHCP/DNS
-func (xt XTables) NetworkSetupIPv4DNSOverrides(name string) error {
+func (d XTables) NetworkSetupIPv4DNSOverrides(name string) error {
 	rules := [][]string{
 		{"ipv4", name, "", "INPUT", "-i", name, "-p", "udp", "--dport", "67", "-j", "ACCEPT"},
 		{"ipv4", name, "", "INPUT", "-i", name, "-p", "udp", "--dport", "53", "-j", "ACCEPT"},
@@ -192,7 +192,7 @@ func (xt XTables) NetworkSetupIPv4DNSOverrides(name string) error {
 		{"ipv4", name, "", "OUTPUT", "-o", name, "-p", "tcp", "--sport", "53", "-j", "ACCEPT"}}
 
 	for _, rule := range rules {
-		err := NetworkPrepend(rule[0], rule[1], rule[2], rule[3], rule[4:]...)
+		err := d.networkPrepend(rule[0], rule[1], rule[2], rule[3], rule[4:]...)
 		if err != nil {
 			return err
 		}
@@ -202,12 +202,12 @@ func (xt XTables) NetworkSetupIPv4DNSOverrides(name string) error {
 }
 
 // NetworkSetupIPv4DHCPWorkaround attempts a workaround for broken DHCP clients
-func (xt XTables) NetworkSetupIPv4DHCPWorkaround(name string) error {
-	return NetworkPrepend("ipv4", name, "mangle", "POSTROUTING", "-o", name, "-p", "udp", "--dport", "68", "-j", "CHECKSUM", "--checksum-fill")
+func (d XTables) NetworkSetupIPv4DHCPWorkaround(name string) error {
+	return d.networkPrepend("ipv4", name, "mangle", "POSTROUTING", "-o", name, "-p", "udp", "--dport", "68", "-j", "CHECKSUM", "--checksum-fill")
 }
 
 // NetworkSetupIPv6DNSOverrides sets up basic iptables overrides for DHCP/DNS
-func (xt XTables) NetworkSetupIPv6DNSOverrides(name string) error {
+func (d XTables) NetworkSetupIPv6DNSOverrides(name string) error {
 	rules := [][]string{
 		{"ipv6", name, "", "INPUT", "-i", name, "-p", "udp", "--dport", "547", "-j", "ACCEPT"},
 		{"ipv6", name, "", "INPUT", "-i", name, "-p", "udp", "--dport", "53", "-j", "ACCEPT"},
@@ -217,7 +217,7 @@ func (xt XTables) NetworkSetupIPv6DNSOverrides(name string) error {
 		{"ipv6", name, "", "OUTPUT", "-o", name, "-p", "tcp", "--sport", "53", "-j", "ACCEPT"}}
 
 	for _, rule := range rules {
-		err := NetworkPrepend(rule[0], rule[1], rule[2], rule[3], rule[4:]...)
+		err := d.networkPrepend(rule[0], rule[1], rule[2], rule[3], rule[4:]...)
 		if err != nil {
 			return err
 		}
@@ -227,14 +227,14 @@ func (xt XTables) NetworkSetupIPv6DNSOverrides(name string) error {
 }
 
 // NetworkSetupTunnelNAT configures tunnel NAT
-func (xt XTables) NetworkSetupTunnelNAT(name string, location firewallConsts.Location, overlaySubnet net.IPNet) error {
-	if location == firewallConsts.LocationPrepend {
-		err := NetworkPrepend("ipv4", name, "nat", "POSTROUTING", "-s", overlaySubnet.String(), "!", "-d", overlaySubnet.String(), "-j", "MASQUERADE")
+func (d XTables) NetworkSetupTunnelNAT(name string, location Location, overlaySubnet net.IPNet) error {
+	if location == LocationPrepend {
+		err := d.networkPrepend("ipv4", name, "nat", "POSTROUTING", "-s", overlaySubnet.String(), "!", "-d", overlaySubnet.String(), "-j", "MASQUERADE")
 		if err != nil {
 			return err
 		}
-	} else if location == firewallConsts.LocationAppend {
-		err := NetworkAppend("ipv4", name, "nat", "POSTROUTING", "-s", overlaySubnet.String(), "!", "-d", overlaySubnet.String(), "-j", "MASQUERADE")
+	} else if location == LocationAppend {
+		err := d.networkAppend("ipv4", name, "nat", "POSTROUTING", "-s", overlaySubnet.String(), "!", "-d", overlaySubnet.String(), "-j", "MASQUERADE")
 		if err != nil {
 			return err
 		}
@@ -246,7 +246,7 @@ func (xt XTables) NetworkSetupTunnelNAT(name string, location firewallConsts.Loc
 // Helper Functions
 
 // generateFilterEbtablesRules returns a customised set of ebtables filter rules based on the device.
-func generateFilterEbtablesRules(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP) [][]string {
+func (d XTables) generateFilterEbtablesRules(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP) [][]string {
 	// MAC source filtering rules. Blocks any packet coming from instance with an incorrect Ethernet source MAC.
 	// This is required for IP filtering too.
 	rules := [][]string{
@@ -285,7 +285,7 @@ func generateFilterEbtablesRules(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP
 }
 
 // generateFilterIptablesRules returns a customised set of iptables filter rules based on the device.
-func generateFilterIptablesRules(m deviceConfig.Device, ipv6 net.IP) (rules [][]string, err error) {
+func (d XTables) generateFilterIptablesRules(m deviceConfig.Device, ipv6 net.IP) (rules [][]string, err error) {
 	mac, err := net.ParseMAC(m["hwaddr"])
 	if err != nil {
 		return
@@ -320,7 +320,7 @@ func generateFilterIptablesRules(m deviceConfig.Device, ipv6 net.IP) (rules [][]
 // matchEbtablesRule compares an active rule to a supplied match rule to see if they match.
 // If deleteMode is true then the "-A" flag in the active rule will be modified to "-D" and will
 // not be part of the equality match. This allows delete commands to be generated from dumped add commands.
-func matchEbtablesRule(activeRule []string, matchRule []string, deleteMode bool) bool {
+func (d XTables) matchEbtablesRule(activeRule []string, matchRule []string, deleteMode bool) bool {
 	for i := range matchRule {
 		// Active rules will be dumped in "add" format, we need to detect
 		// this and switch it to "delete" mode if requested. If this has already been
@@ -345,3 +345,125 @@ func matchEbtablesRule(activeRule []string, matchRule []string, deleteMode bool)
 
 	return true
 }
+
+func (d XTables) iptablesConfig(protocol string, comment string, table string, method string, chain string,
+	rule ...string) error {
+	cmd := "iptables"
+	if protocol == "ipv6" {
+		cmd = "ip6tables"
+	}
+
+	_, err := exec.LookPath(cmd)
+	if err != nil {
+		return fmt.Errorf("Asked to setup %s firewalling but %s can't be found", protocol, cmd)
+	}
+
+	baseArgs := []string{"-w"}
+	if table == "" {
+		table = "filter"
+	}
+	baseArgs = append(baseArgs, []string{"-t", table}...)
+
+	// Check for an existing entry
+	args := append(baseArgs, []string{"-C", chain}...)
+	args = append(args, rule...)
+	args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for %s", comment))
+	_, err = shared.RunCommand(cmd, args...)
+	if err == nil {
+		return nil
+	}
+
+	args = append(baseArgs, []string{method, chain}...)
+	args = append(args, rule...)
+	args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for %s", comment))
+
+	_, err = shared.TryRunCommand(cmd, args...)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (d XTables) iptablesAppend(protocol string, comment string, table string, chain string, rule ...string) error {
+	return d.iptablesConfig(protocol, comment, table, "-A", chain, rule...)
+}
+
+func (d XTables) iptablesPrepend(protocol string, comment string, table string, chain string, rule ...string) error {
+	return d.iptablesConfig(protocol, comment, table, "-I", chain, rule...)
+}
+
+func (d XTables) iptablesClear(protocol string, comment string, table string) error {
+	// Detect kernels that lack IPv6 support
+	if !shared.PathExists("/proc/sys/net/ipv6") && protocol == "ipv6" {
+		return nil
+	}
+
+	cmd := "iptables"
+	if protocol == "ipv6" {
+		cmd = "ip6tables"
+	}
+
+	_, err := exec.LookPath(cmd)
+	if err != nil {
+		return nil
+	}
+
+	baseArgs := []string{"-w"}
+	if table == "" {
+		table = "filter"
+	}
+	baseArgs = append(baseArgs, []string{"-t", table}...)
+
+	// List the rules
+	args := append(baseArgs, "-S")
+	output, err := shared.TryRunCommand(cmd, args...)
+	if err != nil {
+		return fmt.Errorf("Failed to list %s rules for %s (table %s)", protocol, comment, table)
+	}
+
+	for _, line := range strings.Split(output, "\n") {
+		if !strings.Contains(line, fmt.Sprintf("generated for %s", comment)) {
+			continue
+		}
+
+		// Remove the entry
+		fields := strings.Fields(line)
+		fields[0] = "-D"
+
+		args = append(baseArgs, fields...)
+		_, err = shared.TryRunCommand("sh", "-c", fmt.Sprintf("%s %s", cmd, strings.Join(args, " ")))
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// networkAppend adds a network rule at end of ruleset.
+func (d XTables) networkAppend(protocol string, comment string, table string, chain string, rule ...string) error {
+	return d.iptablesAppend(protocol, fmt.Sprintf("LXD network %s", comment), table, chain, rule...)
+}
+
+// networkPrepend adds a network rule at start of ruleset.
+func (d XTables) networkPrepend(protocol string, comment string, table string, chain string,
+	rule ...string) error {
+	return d.iptablesPrepend(protocol, fmt.Sprintf("LXD network %s", comment), table, chain, rule...)
+}
+
+// networkClear removes network rules.
+func (d XTables) networkClear(protocol string, comment string, table string) error {
+	return d.iptablesClear(protocol, fmt.Sprintf("LXD network %s", comment), table)
+}
+
+// containerPrepend adds container rule at start of ruleset.
+func (d XTables) containerPrepend(protocol string, comment string, table string,
+	chain string, rule ...string) error {
+	return d.iptablesPrepend(protocol, fmt.Sprintf("LXD container %s", comment), table, chain, rule...)
+}
+
+// containerClear removes container rules.
+func (d XTables) containerClear(protocol string, comment string, table string) error {
+	return d.iptablesClear(protocol, fmt.Sprintf("LXD container %s", comment), table)
+}

From 83eba4aeb83d21f223508b2a9cd515fc3ee40c05 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 3 Feb 2020 14:30:01 +0000
Subject: [PATCH 3/3] lxd/firewall: Updates interface and loader for new pkg

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/firewall/interfaces.go | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/lxd/firewall/interfaces.go b/lxd/firewall/interfaces.go
index 3e5bd8bd07..db06fedf3f 100644
--- a/lxd/firewall/interfaces.go
+++ b/lxd/firewall/interfaces.go
@@ -4,35 +4,34 @@ import (
 	"net"
 
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
-	firewallConsts "github.com/lxc/lxd/lxd/firewall/consts"
-	"github.com/lxc/lxd/lxd/iptables"
+	"github.com/lxc/lxd/lxd/firewall/drivers"
 )
 
 // Firewall represents an LXD firewall.
 type Firewall interface {
 	// Lower-level Functions
-	NetworkClear(family firewallConsts.Family, table firewallConsts.Table, comment string) error
-	InstanceClear(family firewallConsts.Family, table firewallConsts.Table, comment string) error
+	NetworkClear(family drivers.Family, table drivers.Table, comment string) error
+	InstanceClear(family drivers.Family, table drivers.Table, comment string) error
 	VerifyIPv6Module() error
 
 	// Proxy Functions
-	InstanceProxySetupNAT(family firewallConsts.Family, connType, address, port string, destAddr net.IP, destPort string, comment string) error
+	InstanceProxySetupNAT(family drivers.Family, connType, address, port string, destAddr net.IP, destPort string, comment string) error
 
 	// NIC Bridged Functions
 	InstanceNicBridgedRemoveFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP) error
 	InstanceNicBridgedSetFilters(m deviceConfig.Device, ipv4 net.IP, ipv6 net.IP, comment string) error
 
 	// Network Functions
-	NetworkSetupAllowForwarding(family firewallConsts.Family, name string, actionType firewallConsts.Action) error
-	NetworkSetupNAT(family firewallConsts.Family, name string, location firewallConsts.Location, args ...string) error
+	NetworkSetupAllowForwarding(family drivers.Family, name string, actionType drivers.Action) error
+	NetworkSetupNAT(family drivers.Family, name string, location drivers.Location, args ...string) error
 	NetworkSetupIPv4DNSOverrides(name string) error
 	NetworkSetupIPv4DHCPWorkaround(name string) error
 	NetworkSetupIPv6DNSOverrides(name string) error
-	NetworkSetupTunnelNAT(name string, location firewallConsts.Location, overlaySubnet net.IPNet) error
+	NetworkSetupTunnelNAT(name string, location drivers.Location, overlaySubnet net.IPNet) error
 }
 
 // New returns an appropriate firewall implementation.
 func New() Firewall {
 	// TODO: Issue #6223: add startup logic to choose xtables or nftables
-	return iptables.XTables{}
+	return drivers.XTables{}
 }


More information about the lxc-devel mailing list