github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/bridge/setup_ip_tables_test.go (about)

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