| package libnetwork |
| |
| import ( |
| "fmt" |
| "strings" |
| "testing" |
| |
| "github.com/docker/docker/libnetwork/iptables" |
| "github.com/docker/docker/libnetwork/netlabel" |
| "github.com/docker/docker/libnetwork/options" |
| "github.com/docker/docker/libnetwork/testutils" |
| "gotest.tools/v3/assert" |
| ) |
| |
| const ( |
| fwdChainName = "FORWARD" |
| usrChainName = userChain |
| ) |
| |
| func TestUserChain(t *testing.T) { |
| iptable4 := iptables.GetIptable(iptables.IPv4) |
| iptable6 := iptables.GetIptable(iptables.IPv6) |
| |
| tests := []struct { |
| iptables bool |
| insert bool // insert other rules to FORWARD |
| fwdChain []string |
| userChain []string |
| }{ |
| { |
| iptables: false, |
| insert: false, |
| fwdChain: []string{"-P FORWARD ACCEPT"}, |
| }, |
| { |
| iptables: true, |
| insert: false, |
| fwdChain: []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER"}, |
| userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"}, |
| }, |
| { |
| iptables: true, |
| insert: true, |
| fwdChain: []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER", "-A FORWARD -j DROP"}, |
| userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"}, |
| }, |
| } |
| |
| for _, tc := range tests { |
| tc := tc |
| t.Run(fmt.Sprintf("iptables=%v,insert=%v", tc.iptables, tc.insert), func(t *testing.T) { |
| defer testutils.SetupTestOSContext(t)() |
| defer resetIptables(t) |
| |
| c, err := New() |
| assert.NilError(t, err) |
| defer c.Stop() |
| c.cfg.DriverCfg["bridge"] = map[string]interface{}{ |
| netlabel.GenericData: options.Generic{ |
| "EnableIPTables": tc.iptables, |
| "EnableIP6Tables": tc.iptables, |
| }, |
| } |
| |
| // init. condition, FORWARD chain empty DOCKER-USER not exist |
| assert.DeepEqual(t, getRules(t, iptables.IPv4, fwdChainName), []string{"-P FORWARD ACCEPT"}) |
| assert.DeepEqual(t, getRules(t, iptables.IPv6, fwdChainName), []string{"-P FORWARD ACCEPT"}) |
| |
| if tc.insert { |
| _, err = iptable4.Raw("-A", fwdChainName, "-j", "DROP") |
| assert.NilError(t, err) |
| _, err = iptable6.Raw("-A", fwdChainName, "-j", "DROP") |
| assert.NilError(t, err) |
| } |
| arrangeUserFilterRule() |
| |
| assert.DeepEqual(t, getRules(t, iptables.IPv4, fwdChainName), tc.fwdChain) |
| assert.DeepEqual(t, getRules(t, iptables.IPv6, fwdChainName), tc.fwdChain) |
| if tc.userChain != nil { |
| assert.DeepEqual(t, getRules(t, iptables.IPv4, usrChainName), tc.userChain) |
| assert.DeepEqual(t, getRules(t, iptables.IPv6, usrChainName), tc.userChain) |
| } else { |
| _, err := iptable4.Raw("-S", usrChainName) |
| assert.Assert(t, err != nil, "ipv4 chain %v: created unexpectedly", usrChainName) |
| _, err = iptable6.Raw("-S", usrChainName) |
| assert.Assert(t, err != nil, "ipv6 chain %v: created unexpectedly", usrChainName) |
| } |
| }) |
| } |
| } |
| |
| func getRules(t *testing.T, ipVer iptables.IPVersion, chain string) []string { |
| iptable := iptables.GetIptable(ipVer) |
| |
| t.Helper() |
| output, err := iptable.Raw("-S", chain) |
| assert.NilError(t, err, "chain %s: failed to get rules", chain) |
| |
| rules := strings.Split(string(output), "\n") |
| if len(rules) > 0 { |
| rules = rules[:len(rules)-1] |
| } |
| return rules |
| } |
| |
| func resetIptables(t *testing.T) { |
| t.Helper() |
| |
| for _, ipVer := range []iptables.IPVersion{iptables.IPv4, iptables.IPv6} { |
| iptable := iptables.GetIptable(ipVer) |
| |
| _, err := iptable.Raw("-F", fwdChainName) |
| assert.Check(t, err) |
| _ = iptable.RemoveExistingChain(usrChainName, "") |
| } |
| } |