github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drivers/bridge/setup_ip_tables_test.go (about)

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