// Control Inter Network Communication. Install/remove only if it is not/is present.
func setINC(network1, network2 string, enable bool) error {
	var (
		table = iptables.Filter
		chain = "FORWARD"
		args  = [2][]string{{"-s", network1, "-d", network2, "-j", "DROP"}, {"-s", network2, "-d", network1, "-j", "DROP"}}
	)

	if enable {
		for i := 0; i < 2; i++ {
			if iptables.Exists(table, chain, args[i]...) {
				continue
			}
			if output, err := iptables.Raw(append([]string{"-I", chain}, args[i]...)...); err != nil {
				return fmt.Errorf("unable to add inter-network communication rule: %s", err.Error())
			} else if len(output) != 0 {
				return fmt.Errorf("error adding inter-network communication rule: %s", string(output))
			}
		}
	} else {
		for i := 0; i < 2; i++ {
			if !iptables.Exists(table, chain, args[i]...) {
				continue
			}
			if output, err := iptables.Raw(append([]string{"-D", chain}, args[i]...)...); err != nil {
				return fmt.Errorf("unable to remove inter-network communication rule: %s", err.Error())
			} else if len(output) != 0 {
				return fmt.Errorf("error removing inter-network communication rule: %s", string(output))
			}
		}
	}

	return nil
}
Example #2
0
// adapted from https://github.com/docker/libnetwork/blob/master/iptables/iptables.go
func (p *portMapper) forward(action iptables.Action, ip net.IP, port int, proto, destAddr string, destPort int, srcIface, destIface string) error {
	daddr := ip.String()
	if ip == nil || ip.IsUnspecified() {
		// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we
		// want "0.0.0.0/0". "0/0" is correctly interpreted as "any
		// value" by both iptables and ip6tables.
		daddr = "0/0"
	}
	args := []string{"-t", string(iptables.Nat), string(action), "VIC",
		"-i", srcIface,
		"-p", proto,
		"-d", daddr,
		"--dport", strconv.Itoa(port),
		"-j", "DNAT",
		"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
	if output, err := iptables.Raw(args...); err != nil {
		return err
	} else if len(output) != 0 {
		return iptables.ChainError{Chain: "FORWARD", Output: output}
	}

	ipStr := ""
	if ip != nil && !ip.IsUnspecified() {
		ipStr = ip.String()
	}

	switch action {
	case iptables.Append:
		p.bindings[bindKey{ipStr, port}] = nil

	case iptables.Delete:
		delete(p.bindings, bindKey{ipStr, port})
	}

	if output, err := iptables.Raw("-t", string(iptables.Filter), string(action), "VIC",
		"-i", srcIface,
		"-o", destIface,
		"-p", proto,
		"-d", destAddr,
		"--dport", strconv.Itoa(destPort),
		"-j", "ACCEPT"); err != nil {
		return err
	} else if len(output) != 0 {
		return iptables.ChainError{Chain: "FORWARD", Output: output}
	}

	if output, err := iptables.Raw("-t", string(iptables.Nat), string(action), "POSTROUTING",
		"-p", proto,
		"-d", destAddr,
		"--dport", strconv.Itoa(destPort),
		"-j", "MASQUERADE"); err != nil {
		return err
	} else if len(output) != 0 {
		return iptables.ChainError{Chain: "FORWARD", Output: output}
	}

	return nil
}
Example #3
0
func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
	var (
		prefix    []string
		operation string
		condition bool
		doesExist = iptables.Exists(rule.table, rule.chain, rule.args...)
	)

	if insert {
		condition = !doesExist
		prefix = []string{"-I", rule.chain}
		operation = "enable"
	} else {
		condition = doesExist
		prefix = []string{"-D", rule.chain}
		operation = "disable"
	}
	if rule.preArgs != nil {
		prefix = append(rule.preArgs, prefix...)
	}

	if condition {
		if output, err := iptables.Raw(append(prefix, rule.args...)...); err != nil {
			return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
		} else if len(output) != 0 {
			return &iptables.ChainError{Chain: rule.chain, Output: output}
		}
	}

	return nil
}
Example #4
0
func chainExists(cname string) bool {
	if _, err := iptables.Raw("-L", cname); err != nil {
		return false
	}

	return true
}
Example #5
0
func verifyV4INCEntries(networks map[string]*bridgeNetwork, numEntries int, t *testing.T) {
	out, err := iptables.Raw("-nvL", IsolationChain)
	if err != nil {
		t.Fatal(err)
	}

	found := 0
	for _, x := range networks {
		for _, y := range networks {
			if x == y {
				continue
			}
			re := regexp.MustCompile(fmt.Sprintf("%s %s", x.config.BridgeName, y.config.BridgeName))
			matches := re.FindAllString(string(out[:]), -1)
			if len(matches) != 1 {
				t.Fatalf("Cannot find expected inter-network isolation rules in IP Tables:\n%s", string(out[:]))
			}
			found++
		}
	}

	if found != numEntries {
		t.Fatalf("Cannot find expected number (%d) of inter-network isolation rules in IP Tables:\n%s\nFound %d", numEntries, string(out[:]), found)
	}
}
Example #6
0
// iptablesRunAndCheck runs an iptables command with the provided args
func iptablesRunAndCheck(action iptables.Action, args []string) error {
	args = append([]string{string(action)}, args...)
	if output, err := iptables.Raw(args...); err != nil {
		return err
	} else if len(output) != 0 {
		return iptables.ChainError{Chain: "FORWARD", Output: output}
	}
	return nil
}
Example #7
0
func rawIPTables(args ...string) error {
	if output, err := iptables.Raw(args...); err != nil {
		return fmt.Errorf("unable to add overlay filter: %v", err)
	} else if len(output) != 0 {
		return fmt.Errorf("unable to add overlay filter: %s", string(output))
	}

	return nil
}
Example #8
0
func setIcc(bridgeIface string, iccEnable, insert bool) error {
	var (
		table      = iptables.Filter
		chain      = "FORWARD"
		args       = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
		acceptArgs = append(args, "ACCEPT")
		dropArgs   = append(args, "DROP")
	)

	if insert {
		if !iccEnable {
			iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)

			if !iptables.Exists(table, chain, dropArgs...) {
				if err := iptables.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
					return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
				}
			}
		} else {
			iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)

			if !iptables.Exists(table, chain, acceptArgs...) {
				if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
					return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
				}
			}
		}
	} else {
		// Remove any ICC rule.
		if !iccEnable {
			if iptables.Exists(table, chain, dropArgs...) {
				iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
			}
		} else {
			if iptables.Exists(table, chain, acceptArgs...) {
				iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
			}
		}
	}

	return nil
}
func (driver *driver) natOut() error {
	masquerade := []string{
		"POSTROUTING", "-t", "nat",
		"-s", driver.pluginConfig.containerSubnet.String(),
		"-j", "MASQUERADE",
	}
	if _, err := iptables.Raw(
		append([]string{"-C"}, masquerade...)...,
	); err != nil {
		incl := append([]string{"-I"}, masquerade...)
		if output, err := iptables.Raw(incl...); err != nil {
			return err
		} else if len(output) > 0 {
			return &iptables.ChainError{
				Chain:  "POSTROUTING",
				Output: output,
			}
		}
	}
	return nil
}
Example #10
0
// todo: reconcile with what libnetwork does and port mappings
func natOut(cidr string) error {
	masquerade := []string{
		"POSTROUTING", "-t", "nat",
		"-s", cidr,
		"-j", "MASQUERADE",
	}
	if _, err := iptables.Raw(
		append([]string{"-C"}, masquerade...)...,
	); err != nil {
		incl := append([]string{"-I"}, masquerade...)
		if output, err := iptables.Raw(incl...); err != nil {
			return err
		} else if len(output) > 0 {
			return &iptables.ChainError{
				Chain:  "POSTROUTING",
				Output: output,
			}
		}
	}
	return nil
}
Example #11
0
func verifyV4INCEntries(networks map[string]*bridgeNetwork, numEntries int, t *testing.T) {
	out, err := iptables.Raw("-L", "FORWARD")
	if err != nil {
		t.Fatal(err)
	}
	for _, nw := range networks {
		nt := types.GetIPNetCopy(nw.bridge.bridgeIPv4)
		nt.IP = nt.IP.Mask(nt.Mask)
		re := regexp.MustCompile(nt.String())
		matches := re.FindAllString(string(out[:]), -1)
		if len(matches) != numEntries {
			t.Fatalf("Cannot find expected inter-network isolation rules in IP Tables:\n%s", string(out[:]))
		}
	}
}
Example #12
0
func TestLinkContainers(t *testing.T) {
	defer netutils.SetupTestNetNS(t)()

	d := newDriver()

	config := &configuration{
		EnableIPTables: true,
	}
	genericOption := make(map[string]interface{})
	genericOption[netlabel.GenericData] = config

	if err := d.Config(genericOption); err != nil {
		t.Fatalf("Failed to setup driver config: %v", err)
	}

	netconfig := &networkConfiguration{
		BridgeName: DefaultBridgeName,
		EnableICC:  false,
	}
	genericOption = make(map[string]interface{})
	genericOption[netlabel.GenericData] = netconfig

	err := d.CreateNetwork("net1", genericOption)
	if err != nil {
		t.Fatalf("Failed to create bridge: %v", err)
	}

	exposedPorts := getExposedPorts()
	epOptions := make(map[string]interface{})
	epOptions[netlabel.ExposedPorts] = exposedPorts

	te1 := &testEndpoint{ifaces: []*testInterface{}}
	err = d.CreateEndpoint("net1", "ep1", te1, epOptions)
	if err != nil {
		t.Fatalf("Failed to create an endpoint : %s", err.Error())
	}

	addr1 := te1.ifaces[0].addr
	if addr1.IP.To4() == nil {
		t.Fatalf("No Ipv4 address assigned to the endpoint:  ep1")
	}

	te2 := &testEndpoint{ifaces: []*testInterface{}}
	err = d.CreateEndpoint("net1", "ep2", te2, nil)
	if err != nil {
		t.Fatalf("Failed to create an endpoint : %s", err.Error())
	}

	addr2 := te2.ifaces[0].addr
	if addr2.IP.To4() == nil {
		t.Fatalf("No Ipv4 address assigned to the endpoint:  ep2")
	}

	ce := []string{"ep1"}
	cConfig := &containerConfiguration{ChildEndpoints: ce}
	genericOption = make(map[string]interface{})
	genericOption[netlabel.GenericData] = cConfig

	err = d.Join("net1", "ep2", "", te2, genericOption)
	if err != nil {
		t.Fatalf("Failed to link ep1 and ep2")
	}

	out, err := iptables.Raw("-L", DockerChain)
	for _, pm := range exposedPorts {
		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
		re := regexp.MustCompile(regex)
		matches := re.FindAllString(string(out[:]), -1)
		if len(matches) != 1 {
			t.Fatalf("IP Tables programming failed %s", string(out[:]))
		}

		regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
		matched, _ := regexp.MatchString(regex, string(out[:]))
		if !matched {
			t.Fatalf("IP Tables programming failed %s", string(out[:]))
		}
	}

	err = d.Leave("net1", "ep2")
	if err != nil {
		t.Fatalf("Failed to unlink ep1 and ep2")
	}

	out, err = iptables.Raw("-L", DockerChain)
	for _, pm := range exposedPorts {
		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
		re := regexp.MustCompile(regex)
		matches := re.FindAllString(string(out[:]), -1)
		if len(matches) != 0 {
			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
		}

		regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
		matched, _ := regexp.MatchString(regex, string(out[:]))
		if matched {
			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
		}
	}

	// Error condition test with an invalid endpoint-id "ep4"
	ce = []string{"ep1", "ep4"}
	cConfig = &containerConfiguration{ChildEndpoints: ce}
	genericOption = make(map[string]interface{})
	genericOption[netlabel.GenericData] = cConfig

	err = d.Join("net1", "ep2", "", te2, genericOption)
	if err != nil {
		out, err = iptables.Raw("-L", DockerChain)
		for _, pm := range exposedPorts {
			regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
			re := regexp.MustCompile(regex)
			matches := re.FindAllString(string(out[:]), -1)
			if len(matches) != 0 {
				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
			}

			regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
			matched, _ := regexp.MatchString(regex, string(out[:]))
			if matched {
				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
			}
		}
	} else {
		t.Fatalf("Expected Join to fail given link conditions are not satisfied")
	}
}
Example #13
0
func TestLinkContainers(t *testing.T) {
	if !testutils.IsRunningInContainer() {
		defer testutils.SetupTestOSContext(t)()
	}

	d := newDriver()

	config := &configuration{
		EnableIPTables: true,
	}
	genericOption := make(map[string]interface{})
	genericOption[netlabel.GenericData] = config

	if err := d.configure(genericOption); err != nil {
		t.Fatalf("Failed to setup driver config: %v", err)
	}

	netconfig := &networkConfiguration{
		BridgeName: DefaultBridgeName,
		EnableICC:  false,
	}
	genericOption = make(map[string]interface{})
	genericOption[netlabel.GenericData] = netconfig

	ipdList := getIPv4Data(t, "")
	err := d.CreateNetwork("net1", genericOption, nil, ipdList, nil)
	if err != nil {
		t.Fatalf("Failed to create bridge: %v", err)
	}

	te1 := newTestEndpoint(ipdList[0].Pool, 11)
	err = d.CreateEndpoint("net1", "ep1", te1.Interface(), nil)
	if err != nil {
		t.Fatalf("Failed to create an endpoint : %s", err.Error())
	}

	exposedPorts := getExposedPorts()
	sbOptions := make(map[string]interface{})
	sbOptions[netlabel.ExposedPorts] = exposedPorts

	err = d.Join("net1", "ep1", "sbox", te1, sbOptions)
	if err != nil {
		t.Fatalf("Failed to join the endpoint: %v", err)
	}

	err = d.ProgramExternalConnectivity("net1", "ep1", sbOptions)
	if err != nil {
		t.Fatalf("Failed to program external connectivity: %v", err)
	}

	addr1 := te1.iface.addr
	if addr1.IP.To4() == nil {
		t.Fatalf("No Ipv4 address assigned to the endpoint:  ep1")
	}

	te2 := newTestEndpoint(ipdList[0].Pool, 22)
	err = d.CreateEndpoint("net1", "ep2", te2.Interface(), nil)
	if err != nil {
		t.Fatalf("Failed to create an endpoint : %s", err.Error())
	}

	addr2 := te2.iface.addr
	if addr2.IP.To4() == nil {
		t.Fatalf("No Ipv4 address assigned to the endpoint:  ep2")
	}

	sbOptions = make(map[string]interface{})
	sbOptions[netlabel.GenericData] = options.Generic{
		"ChildEndpoints": []string{"ep1"},
	}

	err = d.Join("net1", "ep2", "", te2, sbOptions)
	if err != nil {
		t.Fatalf("Failed to link ep1 and ep2")
	}

	err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions)
	if err != nil {
		t.Fatalf("Failed to program external connectivity: %v", err)
	}

	out, err := iptables.Raw("-L", DockerChain)
	for _, pm := range exposedPorts {
		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
		re := regexp.MustCompile(regex)
		matches := re.FindAllString(string(out[:]), -1)
		if len(matches) != 1 {
			t.Fatalf("IP Tables programming failed %s", string(out[:]))
		}

		regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
		matched, _ := regexp.MatchString(regex, string(out[:]))
		if !matched {
			t.Fatalf("IP Tables programming failed %s", string(out[:]))
		}
	}

	err = d.RevokeExternalConnectivity("net1", "ep2")
	if err != nil {
		t.Fatalf("Failed to revoke external connectivity: %v", err)
	}

	err = d.Leave("net1", "ep2")
	if err != nil {
		t.Fatalf("Failed to unlink ep1 and ep2")
	}

	out, err = iptables.Raw("-L", DockerChain)
	for _, pm := range exposedPorts {
		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
		re := regexp.MustCompile(regex)
		matches := re.FindAllString(string(out[:]), -1)
		if len(matches) != 0 {
			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
		}

		regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
		matched, _ := regexp.MatchString(regex, string(out[:]))
		if matched {
			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
		}
	}

	// Error condition test with an invalid endpoint-id "ep4"
	sbOptions = make(map[string]interface{})
	sbOptions[netlabel.GenericData] = options.Generic{
		"ChildEndpoints": []string{"ep1", "ep4"},
	}

	err = d.Join("net1", "ep2", "", te2, sbOptions)
	if err != nil {
		t.Fatal(err)
	}
	err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions)
	if err != nil {
		out, err = iptables.Raw("-L", DockerChain)
		for _, pm := range exposedPorts {
			regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
			re := regexp.MustCompile(regex)
			matches := re.FindAllString(string(out[:]), -1)
			if len(matches) != 0 {
				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
			}

			regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
			matched, _ := regexp.MatchString(regex, string(out[:]))
			if matched {
				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
			}
		}
	} else {
		t.Fatalf("Expected Join to fail given link conditions are not satisfied")
	}
}