github.com/codemac/docker@v1.2.1-0.20150518222241-6a18412d5b9c/pkg/iptables/iptables_test.go (about)

     1  package iptables
     2  
     3  import (
     4  	"net"
     5  	"os/exec"
     6  	"strconv"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  )
    11  
    12  const chainName = "DOCKERTEST"
    13  
    14  var natChain *Chain
    15  var filterChain *Chain
    16  
    17  func TestNewChain(t *testing.T) {
    18  	var err error
    19  
    20  	natChain, err = NewChain(chainName, "lo", Nat, false)
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  
    25  	filterChain, err = NewChain(chainName, "lo", Filter, false)
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  }
    30  
    31  func TestForward(t *testing.T) {
    32  	ip := net.ParseIP("192.168.1.1")
    33  	port := 1234
    34  	dstAddr := "172.17.0.1"
    35  	dstPort := 4321
    36  	proto := "tcp"
    37  
    38  	err := natChain.Forward(Insert, ip, port, proto, dstAddr, dstPort)
    39  	if err != nil {
    40  		t.Fatal(err)
    41  	}
    42  
    43  	dnatRule := []string{
    44  		"-d", ip.String(),
    45  		"-p", proto,
    46  		"--dport", strconv.Itoa(port),
    47  		"-j", "DNAT",
    48  		"--to-destination", dstAddr + ":" + strconv.Itoa(dstPort),
    49  	}
    50  
    51  	if !Exists(natChain.Table, natChain.Name, dnatRule...) {
    52  		t.Fatalf("DNAT rule does not exist")
    53  	}
    54  
    55  	filterRule := []string{
    56  		"!", "-i", filterChain.Bridge,
    57  		"-o", filterChain.Bridge,
    58  		"-d", dstAddr,
    59  		"-p", proto,
    60  		"--dport", strconv.Itoa(dstPort),
    61  		"-j", "ACCEPT",
    62  	}
    63  
    64  	if !Exists(filterChain.Table, filterChain.Name, filterRule...) {
    65  		t.Fatalf("filter rule does not exist")
    66  	}
    67  
    68  	masqRule := []string{
    69  		"-d", dstAddr,
    70  		"-s", dstAddr,
    71  		"-p", proto,
    72  		"--dport", strconv.Itoa(dstPort),
    73  		"-j", "MASQUERADE",
    74  	}
    75  
    76  	if !Exists(natChain.Table, "POSTROUTING", masqRule...) {
    77  		t.Fatalf("MASQUERADE rule does not exist")
    78  	}
    79  }
    80  
    81  func TestLink(t *testing.T) {
    82  	var err error
    83  
    84  	ip1 := net.ParseIP("192.168.1.1")
    85  	ip2 := net.ParseIP("192.168.1.2")
    86  	port := 1234
    87  	proto := "tcp"
    88  
    89  	err = filterChain.Link(Append, ip1, ip2, port, proto)
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	rule1 := []string{
    95  		"-i", filterChain.Bridge,
    96  		"-o", filterChain.Bridge,
    97  		"-p", proto,
    98  		"-s", ip1.String(),
    99  		"-d", ip2.String(),
   100  		"--dport", strconv.Itoa(port),
   101  		"-j", "ACCEPT"}
   102  
   103  	if !Exists(filterChain.Table, filterChain.Name, rule1...) {
   104  		t.Fatalf("rule1 does not exist")
   105  	}
   106  
   107  	rule2 := []string{
   108  		"-i", filterChain.Bridge,
   109  		"-o", filterChain.Bridge,
   110  		"-p", proto,
   111  		"-s", ip2.String(),
   112  		"-d", ip1.String(),
   113  		"--sport", strconv.Itoa(port),
   114  		"-j", "ACCEPT"}
   115  
   116  	if !Exists(filterChain.Table, filterChain.Name, rule2...) {
   117  		t.Fatalf("rule2 does not exist")
   118  	}
   119  }
   120  
   121  func TestPrerouting(t *testing.T) {
   122  	args := []string{
   123  		"-i", "lo",
   124  		"-d", "192.168.1.1"}
   125  
   126  	err := natChain.Prerouting(Insert, args...)
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  
   131  	rule := []string{
   132  		"-j", natChain.Name}
   133  
   134  	rule = append(rule, args...)
   135  
   136  	if !Exists(natChain.Table, "PREROUTING", rule...) {
   137  		t.Fatalf("rule does not exist")
   138  	}
   139  
   140  	delRule := append([]string{"-D", "PREROUTING", "-t", string(Nat)}, rule...)
   141  	if _, err = Raw(delRule...); err != nil {
   142  		t.Fatal(err)
   143  	}
   144  }
   145  
   146  func TestOutput(t *testing.T) {
   147  	args := []string{
   148  		"-o", "lo",
   149  		"-d", "192.168.1.1"}
   150  
   151  	err := natChain.Output(Insert, args...)
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	rule := []string{
   157  		"-j", natChain.Name}
   158  
   159  	rule = append(rule, args...)
   160  
   161  	if !Exists(natChain.Table, "OUTPUT", rule...) {
   162  		t.Fatalf("rule does not exist")
   163  	}
   164  
   165  	delRule := append([]string{"-D", "OUTPUT", "-t",
   166  		string(natChain.Table)}, rule...)
   167  	if _, err = Raw(delRule...); err != nil {
   168  		t.Fatal(err)
   169  	}
   170  }
   171  
   172  func TestConcurrencyWithWait(t *testing.T) {
   173  	RunConcurrencyTest(t, true)
   174  }
   175  
   176  func TestConcurrencyNoWait(t *testing.T) {
   177  	RunConcurrencyTest(t, false)
   178  }
   179  
   180  // Runs 10 concurrent rule additions. This will fail if iptables
   181  // is actually invoked simultaneously without --wait.
   182  // Note that if iptables does not support the xtable lock on this
   183  // system, then allowXlock has no effect -- it will always be off.
   184  func RunConcurrencyTest(t *testing.T, allowXlock bool) {
   185  	var wg sync.WaitGroup
   186  
   187  	if !allowXlock && supportsXlock {
   188  		supportsXlock = false
   189  		defer func() { supportsXlock = true }()
   190  	}
   191  
   192  	ip := net.ParseIP("192.168.1.1")
   193  	port := 1234
   194  	dstAddr := "172.17.0.1"
   195  	dstPort := 4321
   196  	proto := "tcp"
   197  
   198  	for i := 0; i < 10; i++ {
   199  		wg.Add(1)
   200  		go func() {
   201  			defer wg.Done()
   202  			err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort)
   203  			if err != nil {
   204  				t.Fatal(err)
   205  			}
   206  		}()
   207  	}
   208  	wg.Wait()
   209  }
   210  
   211  func TestCleanup(t *testing.T) {
   212  	var err error
   213  	var rules []byte
   214  
   215  	// Cleanup filter/FORWARD first otherwise output of iptables-save is dirty
   216  	link := []string{"-t", string(filterChain.Table),
   217  		string(Delete), "FORWARD",
   218  		"-o", filterChain.Bridge,
   219  		"-j", filterChain.Name}
   220  	if _, err = Raw(link...); err != nil {
   221  		t.Fatal(err)
   222  	}
   223  	filterChain.Remove()
   224  
   225  	err = RemoveExistingChain(chainName, Nat)
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  
   230  	rules, err = exec.Command("iptables-save").Output()
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  	if strings.Contains(string(rules), chainName) {
   235  		t.Fatalf("Removing chain failed. %s found in iptables-save", chainName)
   236  	}
   237  }