github.com/moby/docker@v26.1.3+incompatible/libnetwork/firewall_linux_test.go (about)

     1  package libnetwork
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/docker/docker/internal/testutils/netnsutils"
     9  	"github.com/docker/docker/libnetwork/config"
    10  	"github.com/docker/docker/libnetwork/iptables"
    11  	"github.com/docker/docker/libnetwork/netlabel"
    12  	"github.com/docker/docker/libnetwork/options"
    13  	"gotest.tools/v3/assert"
    14  	is "gotest.tools/v3/assert/cmp"
    15  )
    16  
    17  const (
    18  	fwdChainName = "FORWARD"
    19  	usrChainName = userChain
    20  )
    21  
    22  func TestUserChain(t *testing.T) {
    23  	iptable4 := iptables.GetIptable(iptables.IPv4)
    24  	iptable6 := iptables.GetIptable(iptables.IPv6)
    25  
    26  	tests := []struct {
    27  		iptables  bool
    28  		insert    bool // insert other rules to FORWARD
    29  		fwdChain  []string
    30  		userChain []string
    31  	}{
    32  		{
    33  			iptables: false,
    34  			insert:   false,
    35  			fwdChain: []string{"-P FORWARD ACCEPT"},
    36  		},
    37  		{
    38  			iptables:  true,
    39  			insert:    false,
    40  			fwdChain:  []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER"},
    41  			userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"},
    42  		},
    43  		{
    44  			iptables:  true,
    45  			insert:    true,
    46  			fwdChain:  []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER", "-A FORWARD -j DROP"},
    47  			userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"},
    48  		},
    49  	}
    50  
    51  	for _, tc := range tests {
    52  		tc := tc
    53  		t.Run(fmt.Sprintf("iptables=%v,insert=%v", tc.iptables, tc.insert), func(t *testing.T) {
    54  			defer netnsutils.SetupTestOSContext(t)()
    55  			defer resetIptables(t)
    56  
    57  			c, err := New(
    58  				OptionBoltdbWithRandomDBFile(t),
    59  				config.OptionDriverConfig("bridge", map[string]any{
    60  					netlabel.GenericData: options.Generic{
    61  						"EnableIPTables":  tc.iptables,
    62  						"EnableIP6Tables": tc.iptables,
    63  					},
    64  				}))
    65  			assert.NilError(t, err)
    66  			defer c.Stop()
    67  
    68  			// init. condition, FORWARD chain empty DOCKER-USER not exist
    69  			assert.Check(t, is.DeepEqual(getRules(t, iptable4, fwdChainName), []string{"-P FORWARD ACCEPT"}))
    70  			assert.Check(t, is.DeepEqual(getRules(t, iptable6, fwdChainName), []string{"-P FORWARD ACCEPT"}))
    71  
    72  			if tc.insert {
    73  				_, err = iptable4.Raw("-A", fwdChainName, "-j", "DROP")
    74  				assert.Check(t, err)
    75  				_, err = iptable6.Raw("-A", fwdChainName, "-j", "DROP")
    76  				assert.Check(t, err)
    77  			}
    78  			arrangeUserFilterRule()
    79  
    80  			assert.Check(t, is.DeepEqual(getRules(t, iptable4, fwdChainName), tc.fwdChain))
    81  			assert.Check(t, is.DeepEqual(getRules(t, iptable6, fwdChainName), tc.fwdChain))
    82  			if tc.userChain != nil {
    83  				assert.Check(t, is.DeepEqual(getRules(t, iptable4, usrChainName), tc.userChain))
    84  				assert.Check(t, is.DeepEqual(getRules(t, iptable6, usrChainName), tc.userChain))
    85  			} else {
    86  				_, err = iptable4.Raw("-S", usrChainName)
    87  				assert.Check(t, is.ErrorContains(err, "No chain/target/match by that name"), "ipv4 chain %v: created unexpectedly", usrChainName)
    88  				_, err = iptable6.Raw("-S", usrChainName)
    89  				assert.Check(t, is.ErrorContains(err, "No chain/target/match by that name"), "ipv6 chain %v: created unexpectedly", usrChainName)
    90  			}
    91  		})
    92  	}
    93  }
    94  
    95  func getRules(t *testing.T, iptable *iptables.IPTable, chain string) []string {
    96  	t.Helper()
    97  	output, err := iptable.Raw("-S", chain)
    98  	assert.NilError(t, err, "chain %s: failed to get rules", chain)
    99  
   100  	rules := strings.Split(string(output), "\n")
   101  	if len(rules) > 0 {
   102  		rules = rules[:len(rules)-1]
   103  	}
   104  	return rules
   105  }
   106  
   107  func resetIptables(t *testing.T) {
   108  	t.Helper()
   109  
   110  	for _, ipVer := range []iptables.IPVersion{iptables.IPv4, iptables.IPv6} {
   111  		iptable := iptables.GetIptable(ipVer)
   112  
   113  		_, err := iptable.Raw("-F", fwdChainName)
   114  		assert.Check(t, err)
   115  		_ = iptable.RemoveExistingChain(usrChainName, iptables.Filter)
   116  	}
   117  }