github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/drivers/bridge/setup_ip_tables_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package bridge
     5  
     6  import (
     7  	"net"
     8  	"testing"
     9  
    10  	"github.com/docker/docker/libnetwork/iptables"
    11  	"github.com/docker/docker/libnetwork/portmapper"
    12  	"github.com/docker/docker/libnetwork/testutils"
    13  	"github.com/vishvananda/netlink"
    14  )
    15  
    16  const (
    17  	iptablesTestBridgeIP = "192.168.42.1"
    18  )
    19  
    20  func TestProgramIPTable(t *testing.T) {
    21  	// Create a test bridge with a basic bridge configuration (name + IPv4).
    22  	defer testutils.SetupTestOSContext(t)()
    23  
    24  	nh, err := netlink.NewHandle()
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	createTestBridge(getBasicTestConfig(), &bridgeInterface{nlh: nh}, t)
    30  
    31  	// Store various iptables chain rules we care for.
    32  	rules := []struct {
    33  		rule  iptRule
    34  		descr string
    35  	}{
    36  		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-d", "127.1.2.3", "-i", "lo", "-o", "lo", "-j", "DROP"}}, "Test Loopback"},
    37  		{iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", iptablesTestBridgeIP, "!", "-o", DefaultBridgeName, "-j", "MASQUERADE"}}, "NAT Test"},
    38  		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", DefaultBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}, "Test ACCEPT INCOMING"},
    39  		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "!", "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test ACCEPT NON_ICC OUTGOING"},
    40  		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test enable ICC"},
    41  		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "DROP"}}, "Test disable ICC"},
    42  	}
    43  
    44  	// Assert the chain rules' insertion and removal.
    45  	for _, c := range rules {
    46  		assertIPTableChainProgramming(c.rule, c.descr, t)
    47  	}
    48  }
    49  
    50  func TestSetupIPChains(t *testing.T) {
    51  	// Create a test bridge with a basic bridge configuration (name + IPv4).
    52  	defer testutils.SetupTestOSContext(t)()
    53  
    54  	nh, err := netlink.NewHandle()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	driverconfig := &configuration{
    60  		EnableIPTables: true,
    61  	}
    62  	d := &driver{
    63  		config: driverconfig,
    64  	}
    65  	assertChainConfig(d, t)
    66  
    67  	config := getBasicTestConfig()
    68  	br := &bridgeInterface{nlh: nh}
    69  	createTestBridge(config, br, t)
    70  
    71  	assertBridgeConfig(config, br, d, t)
    72  
    73  	config.EnableIPMasquerade = true
    74  	assertBridgeConfig(config, br, d, t)
    75  
    76  	config.EnableICC = true
    77  	assertBridgeConfig(config, br, d, t)
    78  
    79  	config.EnableIPMasquerade = false
    80  	assertBridgeConfig(config, br, d, t)
    81  }
    82  
    83  func getBasicTestConfig() *networkConfiguration {
    84  	config := &networkConfiguration{
    85  		BridgeName:  DefaultBridgeName,
    86  		AddressIPv4: &net.IPNet{IP: net.ParseIP(iptablesTestBridgeIP), Mask: net.CIDRMask(16, 32)}}
    87  	return config
    88  }
    89  
    90  func createTestBridge(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
    91  	if err := setupDevice(config, br); err != nil {
    92  		t.Fatalf("Failed to create the testing Bridge: %s", err.Error())
    93  	}
    94  	if err := setupBridgeIPv4(config, br); err != nil {
    95  		t.Fatalf("Failed to bring up the testing Bridge: %s", err.Error())
    96  	}
    97  }
    98  
    99  // Assert base function which pushes iptables chain rules on insertion and removal.
   100  func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
   101  	// Add
   102  	if err := programChainRule(iptables.IPv4, rule, descr, true); err != nil {
   103  		t.Fatalf("Failed to program iptable rule %s: %s", descr, err.Error())
   104  	}
   105  
   106  	iptable := iptables.GetIptable(iptables.IPv4)
   107  	if iptable.Exists(rule.table, rule.chain, rule.args...) == false {
   108  		t.Fatalf("Failed to effectively program iptable rule: %s", descr)
   109  	}
   110  
   111  	// Remove
   112  	if err := programChainRule(iptables.IPv4, rule, descr, false); err != nil {
   113  		t.Fatalf("Failed to remove iptable rule %s: %s", descr, err.Error())
   114  	}
   115  	if iptable.Exists(rule.table, rule.chain, rule.args...) == true {
   116  		t.Fatalf("Failed to effectively remove iptable rule: %s", descr)
   117  	}
   118  }
   119  
   120  // Assert function which create chains.
   121  func assertChainConfig(d *driver, t *testing.T) {
   122  	var err error
   123  
   124  	d.natChain, d.filterChain, d.isolationChain1, d.isolationChain2, err = setupIPChains(d.config, iptables.IPv4)
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  }
   129  
   130  // Assert function which pushes chains based on bridge config parameters.
   131  func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, d *driver, t *testing.T) {
   132  	nw := bridgeNetwork{portMapper: portmapper.New(""),
   133  		config: config}
   134  	nw.driver = d
   135  
   136  	// Attempt programming of ip tables.
   137  	err := nw.setupIP4Tables(config, br)
   138  	if err != nil {
   139  		t.Fatalf("%v", err)
   140  	}
   141  }