mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Add nftables support to testutil SetFilterForwardPolicies
Because nftables tables/chain aren't fixed, like they are in iptables - this change makes an assumption about the bridge driver's naming. Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
@@ -356,6 +356,7 @@ func TestBridgeINCRouted(t *testing.T) {
|
||||
d := daemon.New(t)
|
||||
d.StartWithBusybox(ctx, t)
|
||||
t.Cleanup(func() { d.Stop(t) })
|
||||
firewallBackend := d.FirewallBackendDriver(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
t.Cleanup(func() { c.Close() })
|
||||
@@ -455,7 +456,7 @@ func TestBridgeINCRouted(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, fwdPolicy := range []string{"ACCEPT", "DROP"} {
|
||||
networking.SetFilterForwardPolicies(t, fwdPolicy)
|
||||
networking.SetFilterForwardPolicies(t, firewallBackend, fwdPolicy)
|
||||
t.Run(fwdPolicy, func(t *testing.T) {
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name+"/v4/ping", func(t *testing.T) {
|
||||
|
||||
@@ -649,6 +649,7 @@ func TestDirectRoutingOpenPorts(t *testing.T) {
|
||||
d := daemon.New(t)
|
||||
d.StartWithBusybox(ctx, t)
|
||||
t.Cleanup(func() { d.Stop(t) })
|
||||
firewallBackend := d.FirewallBackendDriver(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
t.Cleanup(func() { c.Close() })
|
||||
@@ -771,7 +772,7 @@ func TestDirectRoutingOpenPorts(t *testing.T) {
|
||||
// ping/http timeouts separately. (The iptables filter-FORWARD policy affects the
|
||||
// whole host, so ACCEPT/DROP tests can't be parallelized).
|
||||
for _, fwdPolicy := range []string{"ACCEPT", "DROP"} {
|
||||
networking.SetFilterForwardPolicies(t, fwdPolicy)
|
||||
networking.SetFilterForwardPolicies(t, firewallBackend, fwdPolicy)
|
||||
t.Run(fwdPolicy, func(t *testing.T) {
|
||||
for gwMode := range networks {
|
||||
t.Run(gwMode+"/v4/ping", func(t *testing.T) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package networking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -12,8 +13,15 @@ import (
|
||||
"gotest.tools/v3/poll"
|
||||
)
|
||||
|
||||
const (
|
||||
// The name of the bridge driver's nftables tables.
|
||||
nftTable = "docker-bridges"
|
||||
// The name of the filter-FORWARD chain in nftTable.
|
||||
nftFFChain = "filter-FORWARD"
|
||||
)
|
||||
|
||||
// Find the policy in, for example "Chain FORWARD (policy ACCEPT)".
|
||||
var rePolicy = lazyregexp.New("policy ([A-Z]+)")
|
||||
var rePolicy = lazyregexp.New("policy ([A-Za-z]+)")
|
||||
|
||||
// SetFilterForwardPolicies sets the default policy for the FORWARD chain in
|
||||
// the filter tables for both IPv4 and IPv6. The original policy is restored
|
||||
@@ -22,20 +30,24 @@ var rePolicy = lazyregexp.New("policy ([A-Z]+)")
|
||||
// There's only one filter-FORWARD policy, so this won't behave well if used by
|
||||
// tests running in parallel in a single network namespace that expect different
|
||||
// behaviour.
|
||||
func SetFilterForwardPolicies(t *testing.T, policy string) {
|
||||
func SetFilterForwardPolicies(t *testing.T, firewallBackend string, policy string) {
|
||||
t.Helper()
|
||||
if strings.Contains(firewallBackend, "iptables") {
|
||||
setIptablesFFP(t, policy)
|
||||
return
|
||||
}
|
||||
if firewallBackend == "nftables" {
|
||||
setNftablesFFP(t, policy)
|
||||
return
|
||||
}
|
||||
t.Fatalf("unknown firewall backend %s", firewallBackend)
|
||||
}
|
||||
|
||||
func setIptablesFFP(t *testing.T, policy string) {
|
||||
t.Helper()
|
||||
for _, iptablesCmd := range []string{"iptables", "ip6tables"} {
|
||||
cmd := exec.Command(iptablesCmd, "-L", "FORWARD")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get %s FORWARD policy: %v", iptablesCmd, err)
|
||||
}
|
||||
opMatch := rePolicy.FindSubmatch(out)
|
||||
if len(opMatch) != 2 {
|
||||
t.Fatalf("Failed to find %s FORWARD policy in: %s", iptablesCmd, out)
|
||||
}
|
||||
origPolicy := string(opMatch[1])
|
||||
origPolicy, err := getChainPolicy(t, exec.Command(iptablesCmd, "-L", "FORWARD"))
|
||||
assert.NilError(t, err, "failed to get iptables policy")
|
||||
if origPolicy == policy {
|
||||
continue
|
||||
}
|
||||
@@ -50,6 +62,43 @@ func SetFilterForwardPolicies(t *testing.T, policy string) {
|
||||
}
|
||||
}
|
||||
|
||||
func setNftablesFFP(t *testing.T, policy string) {
|
||||
t.Helper()
|
||||
policy = strings.ToLower(policy)
|
||||
for _, family := range []string{"ip", "ip6"} {
|
||||
origPolicy, err := getChainPolicy(t, exec.Command("nft", "list", "chain", family, nftTable, nftFFChain))
|
||||
assert.NilError(t, err, "failed to get nftables policy")
|
||||
if origPolicy == policy {
|
||||
continue
|
||||
}
|
||||
cmd := func(p string) *exec.Cmd {
|
||||
return exec.Command("nft", "add", "chain", family, nftTable, nftFFChain, "{", "policy", p, ";", "}")
|
||||
}
|
||||
if err := cmd(policy).Run(); err != nil {
|
||||
t.Fatalf("Failed to set %s filter-FORWARD policy: %v", family, err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := cmd(origPolicy).Run(); err != nil {
|
||||
t.Logf("Failed to restore %s filter-FORWARD policy: %v", family, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getChainPolicy(t *testing.T, cmd *exec.Cmd) (string, error) {
|
||||
t.Helper()
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("getting policy: %w", err)
|
||||
}
|
||||
opMatch := rePolicy.FindSubmatch(out)
|
||||
if len(opMatch) != 2 {
|
||||
return "", fmt.Errorf("searching for policy: %w", err)
|
||||
}
|
||||
return string(opMatch[1]), nil
|
||||
}
|
||||
|
||||
// FirewalldRunning returns true if "firewall-cmd --state" reports "running".
|
||||
func FirewalldRunning() bool {
|
||||
state, err := exec.Command("firewall-cmd", "--state").CombinedOutput()
|
||||
return err == nil && strings.TrimSpace(string(state)) == "running"
|
||||
Reference in New Issue
Block a user