Ejemplo n.º 1
0
Archivo: net.go Proyecto: neviim/scope
func validateRemoteAddr(ip net.IP) bool {
	if ip == nil {
		return false
	}
	if ip.IsInterfaceLocalMulticast() {
		return false
	}
	if ip.IsLinkLocalMulticast() {
		return false
	}
	if ip.IsLinkLocalUnicast() {
		return false
	}
	if ip.IsLoopback() {
		return false
	}
	if ip.IsMulticast() {
		return false
	}
	if ip.IsUnspecified() {
		return false
	}
	if isBroadcasty(ip) {
		return false
	}

	return true
}
Ejemplo n.º 2
0
// getFirstLocalIPAddr returns the first available IP address of the local machine
// This is a fix for Beaglebone Black where net.LookupIP(hostname) return no IP address.
func getFirstLocalIPAddr() (net.IP, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return nil, err
	}

	for _, addr := range addrs {
		var ip net.IP
		switch v := addr.(type) {
		case *net.IPNet:
			ip = v.IP
		case *net.IPAddr:
			ip = v.IP
		}
		if ip == nil || ip.IsLoopback() || ip.IsUnspecified() {
			continue
		}
		ip = ip.To4()
		if ip == nil {
			continue // not an ipv4 address
		}
		return ip, nil
	}

	return nil, errors.New("Could not determine ip address")
}
Ejemplo n.º 3
0
func GetFirstInterface() (name string, ip string) {
	ifaces, _ := net.Interfaces()

	for _, iface := range ifaces {
		addrs, _ := iface.Addrs()

		ipV4 := false
		for _, addr := range addrs {
			var ip net.IP
			if ipnet, ok := addr.(*net.IPNet); ok {
				ip = ipnet.IP
			} else if ipaddr, ok := addr.(*net.IPAddr); ok {
				ip = ipaddr.IP
			}
			if ip != nil && ip.To4() != nil && !ip.IsUnspecified() {
				ipstr := addr.String()
				idx := strings.Index(ipstr, "/")
				if idx >= 0 {
					ipstr = ipstr[:idx]
				}

				return iface.Name, ipstr
			}
		}
		if !ipV4 {
			continue
		}

	}

	return "", "0.0.0.0"
}
Ejemplo n.º 4
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
}
Ejemplo n.º 5
0
// If bind-address is usable, return it directly
// If bind-address is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
// interface.
func ValidPublicAddrForMaster(bindAddress net.IP) (net.IP, error) {
	if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
		hostIP, err := ChooseHostInterface()
		if err != nil {
			return nil, err
		}
		bindAddress = hostIP
	}
	return bindAddress, nil
}
// Helper function to check if a given IP is not public (non-routable).
func validateIP(ip net.IP) (bool, error) {
	if ip.IsLoopback() {
		return false, IPisLoopbackError
	}
	if ip.IsUnspecified() {
		return false, IPisUnspecifiedError
	}
	if isInAddressRange(ip, ipv4Nonpublic, ipv6Nonpublic) {
		return false, IPisNotPublicError
	}
	return true, nil
}
Ejemplo n.º 7
0
func InterfaceIPs() ([]*net.IPAddr, error) {
	var (
		addrs []*net.IPAddr
	)

	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		iaddrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}

		for _, iaddr := range iaddrs {
			var (
				ip   net.IP
				zone string
			)

			switch x := iaddr.(type) {
			case *net.IPAddr:
				ip = x.IP
				zone = x.Zone
			case *net.IPNet:
				ip = x.IP
				zone = ""
			}

			if ip.IsMulticast() ||
				ip.IsUnspecified() ||
				ip.IsInterfaceLocalMulticast() ||
				ip.IsLinkLocalMulticast() ||
				ip.IsLinkLocalUnicast() {
				continue
			}

			if ipv4 := ip.To4(); ipv4 != nil {
				ip = ipv4
			}

			addrs = append(addrs, &net.IPAddr{
				IP:   ip,
				Zone: zone,
			})
		}
	}

	return addrs, nil
}
Ejemplo n.º 8
0
func (c *Chain) Forward(action Action, ip net.IP, port, rangeEnd int, proto, destAddr string) error {
	daddr := ip.String()
	if 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"
	}
	if output, err := Raw("-t", "nat", fmt.Sprint(action), c.Name,
		"-p", proto,
		"-d", daddr,
		"--dport", fmt.Sprintf("%d:%d", port, rangeEnd),
		"-j", "DNAT",
		"--to-destination", destAddr); err != nil && action != Delete {
		return err
	} else if len(output) != 0 && action != Delete {
		return fmt.Errorf("Error iptables forward: %s", output)
	}

	fAction := action
	if fAction == Add {
		fAction = "-I"
	}
	if output, err := Raw(string(fAction), "FORWARD",
		"!", "-i", c.Bridge,
		"-o", c.Bridge,
		"-p", proto,
		"-d", destAddr,
		"--dport", fmt.Sprintf("%d:%d", port, rangeEnd),
		"-j", "ACCEPT"); err != nil && action != Delete {
		return err
	} else if len(output) != 0 && action != Delete {
		return fmt.Errorf("Error iptables forward: %s", output)
	}

	if output, err := Raw("-t", "nat", string(fAction), "POSTROUTING",
		"-p", proto,
		"-s", destAddr,
		"-d", destAddr,
		"--dport", fmt.Sprintf("%d:%d", port, rangeEnd),
		"-j", "MASQUERADE"); err != nil && action != Delete {
		return err
	} else if len(output) != 0 && action != Delete {
		return fmt.Errorf("Error iptables forward: %s", output)
	}

	return nil
}
Ejemplo n.º 9
0
// Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
	daddr := ip.String()
	if 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(Nat), string(action), c.Name,
		"-p", proto,
		"-d", daddr,
		"--dport", strconv.Itoa(port),
		"-j", "DNAT",
		"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
	if !c.HairpinMode {
		args = append(args, "!", "-i", bridgeName)
	}
	if output, err := Raw(args...); err != nil {
		return err
	} else if len(output) != 0 {
		return ChainError{Chain: "FORWARD", Output: output}
	}

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

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

	return nil
}
Ejemplo n.º 10
0
Archivo: scope.go Proyecto: vmware/vic
func (s *Scope) ContainerByAddr(addr net.IP) *Endpoint {
	s.RLock()
	defer s.RUnlock()

	if addr == nil || addr.IsUnspecified() {
		return nil
	}

	for _, e := range s.endpoints {
		if addr.Equal(e.IP()) {
			return e
		}
	}

	return nil
}
Ejemplo n.º 11
0
// Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
	daddr := ip.String()
	if 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{
		"-p", proto,
		"-d", daddr,
		"--dport", strconv.Itoa(port),
		"-j", "DNAT",
		"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
	if !c.HairpinMode {
		args = append(args, "!", "-i", bridgeName)
	}
	if err := ProgramRule(Nat, c.Name, action, args); err != nil {
		return err
	}

	args = []string{
		"!", "-i", bridgeName,
		"-o", bridgeName,
		"-p", proto,
		"-d", destAddr,
		"--dport", strconv.Itoa(destPort),
		"-j", "ACCEPT",
	}
	if err := ProgramRule(Filter, c.Name, action, args); err != nil {
		return err
	}

	args = []string{
		"-p", proto,
		"-s", destAddr,
		"-d", destAddr,
		"--dport", strconv.Itoa(destPort),
		"-j", "MASQUERADE",
	}
	if err := ProgramRule(Nat, "POSTROUTING", action, args); err != nil {
		return err
	}

	return nil
}
Ejemplo n.º 12
0
// getClientConnectURLs returns suitable URLs for clients to connect to the listen
// port based on the server options' Host and Port. If the Host corresponds to
// "any" interfaces, this call returns the list of resolved IP addresses.
func (s *Server) getClientConnectURLs() []string {
	s.mu.Lock()
	defer s.mu.Unlock()

	sPort := strconv.Itoa(s.opts.Port)
	urls := make([]string, 0, 1)

	ipAddr, err := net.ResolveIPAddr("ip", s.opts.Host)
	// If the host is "any" (0.0.0.0 or ::), get specific IPs from available
	// interfaces.
	if err == nil && ipAddr.IP.IsUnspecified() {
		var ip net.IP
		ifaces, _ := net.Interfaces()
		for _, i := range ifaces {
			addrs, _ := i.Addrs()
			for _, addr := range addrs {
				switch v := addr.(type) {
				case *net.IPNet:
					ip = v.IP
				case *net.IPAddr:
					ip = v.IP
				}
				// Skip non global unicast addresses
				if !ip.IsGlobalUnicast() || ip.IsUnspecified() {
					ip = nil
					continue
				}
				urls = append(urls, net.JoinHostPort(ip.String(), sPort))
			}
		}
	}
	if err != nil || len(urls) == 0 {
		// We are here if s.opts.Host is not "0.0.0.0" nor "::", or if for some
		// reason we could not add any URL in the loop above.
		// We had a case where a Windows VM was hosed and would have err == nil
		// and not add any address in the array in the loop above, and we
		// ended-up returning 0.0.0.0, which is problematic for Windows clients.
		// Check for 0.0.0.0 or :: specifically, and ignore if that's the case.
		if s.opts.Host == "0.0.0.0" || s.opts.Host == "::" {
			Errorf("Address %q can not be resolved properly", s.opts.Host)
		} else {
			urls = append(urls, net.JoinHostPort(s.opts.Host, sPort))
		}
	}
	return urls
}
Ejemplo n.º 13
0
func (c *Chain) Forward(action Action, ip net.IP, port int, proto, dest_addr string, dest_port int) error {
	daddr := ip.String()
	if 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"
	}
	if output, err := Raw("-t", "nat", fmt.Sprint(action), c.Name,
		"-p", proto,
		"-d", daddr,
		"--dport", strconv.Itoa(port),
		"!", "-i", c.Bridge,
		"-j", "DNAT",
		"--to-destination", net.JoinHostPort(dest_addr, strconv.Itoa(dest_port))); err != nil {
		return err
	} else if len(output) != 0 {
		return fmt.Errorf("Error iptables forward: %s", output)
	}
	return nil
}
Ejemplo n.º 14
0
// RunKubelet starts the Kubelet.
func (c *NodeConfig) RunKubelet() {
	var clusterDNS net.IP
	if c.KubeletServer.ClusterDNS == "" {
		if service, err := c.Client.Services(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if includesServicePort(service.Spec.Ports, 53, "dns") {
				// Use master service if service includes "dns" port 53.
				clusterDNS = net.ParseIP(service.Spec.ClusterIP)
			}
		}
	}
	if clusterDNS == nil {
		if endpoint, err := c.Client.Endpoints(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if endpointIP, ok := firstEndpointIPWithNamedPort(endpoint, 53, "dns"); ok {
				// Use first endpoint if endpoint includes "dns" port 53.
				clusterDNS = net.ParseIP(endpointIP)
			} else if endpointIP, ok := firstEndpointIP(endpoint, 53); ok {
				// Test and use first endpoint if endpoint includes any port 53.
				if err := cmdutil.WaitForSuccessfulDial(false, "tcp", fmt.Sprintf("%s:%d", endpointIP, 53), 50*time.Millisecond, 0, 2); err == nil {
					clusterDNS = net.ParseIP(endpointIP)
				}
			}
		}
	}
	if clusterDNS != nil && !clusterDNS.IsUnspecified() {
		c.KubeletServer.ClusterDNS = clusterDNS.String()
	}

	c.KubeletDeps.DockerClient = c.DockerClient
	// updated by NodeConfig.EnsureVolumeDir
	c.KubeletServer.RootDirectory = c.VolumeDir

	// hook for overriding the cadvisor interface for integration tests
	c.KubeletDeps.CAdvisorInterface = defaultCadvisorInterface
	// hook for overriding the container manager interface for integration tests
	c.KubeletDeps.ContainerManager = defaultContainerManagerInterface

	go func() {
		glog.Fatal(kubeletapp.Run(c.KubeletServer, c.KubeletDeps))
	}()
}
Ejemplo n.º 15
0
func (p *portMapper) isPortAvailable(proto string, ip net.IP, port int) bool {
	addr := ""
	if ip != nil && !ip.IsUnspecified() {
		addr = ip.String()
	}

	if _, ok := p.bindings[bindKey{addr, port}]; ok {
		return false
	}

	c, err := net.Dial(proto, net.JoinHostPort(addr, strconv.Itoa(port)))
	defer func() {
		if c != nil {
			c.Close()
		}
	}()

	if err != nil {
		return true
	}

	return false
}
Ejemplo n.º 16
0
func (c *Context) newExternalScope(id uid.UID, name string, subnet *net.IPNet, gateway net.IP, dns []net.IP, ipam *IPAM) (*Scope, error) {
	// ipam cannot be specified without gateway and subnet
	if ipam != nil && len(ipam.pools) > 0 {
		if ip.IsUnspecifiedSubnet(subnet) || gateway.IsUnspecified() {
			return nil, fmt.Errorf("ipam cannot be specified without gateway and subnet for external network")
		}
	}

	if !ip.IsUnspecifiedSubnet(subnet) {
		// cannot overlap with the default bridge pool
		if c.defaultBridgePool.Network.Contains(subnet.IP) ||
			c.defaultBridgePool.Network.Contains(highestIP4(subnet)) {
			return nil, fmt.Errorf("external network cannot overlap with default bridge network")
		}
	}

	n := Config.ContainerNetworks[name]
	if n == nil {
		return nil, fmt.Errorf("no network info for external scope %s", name)
	}

	return c.newScopeCommon(id, name, ExternalScopeType, subnet, gateway, dns, ipam, n.PortGroup)
}
Ejemplo n.º 17
0
func (c *Context) newExternalScope(id uid.UID, name string, subnet *net.IPNet, gateway net.IP, dns []net.IP, pools []string) (*Scope, error) {
	defer trace.End(trace.Begin(""))
	// ipam cannot be specified without gateway and subnet
	if len(pools) > 0 {
		if ip.IsUnspecifiedSubnet(subnet) || gateway.IsUnspecified() {
			return nil, fmt.Errorf("ipam cannot be specified without gateway and subnet for external network")
		}
	}

	if !ip.IsUnspecifiedSubnet(subnet) {
		// cannot overlap with the default bridge pool
		if c.defaultBridgePool.Network.Contains(subnet.IP) ||
			c.defaultBridgePool.Network.Contains(highestIP4(subnet)) {
			return nil, fmt.Errorf("external network cannot overlap with default bridge network")
		}
	}

	pg := c.config.PortGroups[name]
	if pg == nil {
		return nil, fmt.Errorf("no network info for external scope %s", name)
	}

	return c.newScopeCommon(id, name, constants.ExternalScopeType, subnet, gateway, dns, pools, pg)
}
Ejemplo n.º 18
0
func ShowAllInterfaces() {
	ifaces, _ := net.Interfaces()

	iplist := ""
	for _, iface := range ifaces {
		addrs, _ := iface.Addrs()

		ipV4 := false
		ipAddrs := []string{}
		for _, addr := range addrs {
			var ip net.IP
			if ipnet, ok := addr.(*net.IPNet); ok {
				ip = ipnet.IP
			} else if ipaddr, ok := addr.(*net.IPAddr); ok {
				ip = ipaddr.IP
			}
			if ip != nil && ip.To4() != nil && !ip.IsUnspecified() {
				ipstr := addr.String()
				idx := strings.Index(ipstr, "/")
				if idx >= 0 {
					ipstr = ipstr[:idx]
				}
				ipAddrs = append(ipAddrs, ipstr)
				ipV4 = true
			}
		}
		if !ipV4 {
			continue
		}

		iplist += fmt.Sprintf("%-7d %-40s %s\n", iface.Index, iface.Name, strings.Join(ipAddrs, ", "))
	}

	fmt.Printf("%-7s %-40s %s\n", "index", "interface name", "ip")
	fmt.Print(iplist)
}
Ejemplo n.º 19
0
func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []*api.ServicePort, hosts []string, affinity api.ServiceAffinity) (*api.LoadBalancerStatus, error) {
	glog.V(4).Infof("CreateTCPLoadBalancer(%v, %v, %v, %v, %v, %v)", name, region, externalIP, ports, hosts, affinity)

	if len(ports) > 1 {
		return nil, fmt.Errorf("multiple ports are not yet supported in openstack load balancers")
	}

	var persistence *vips.SessionPersistence
	switch affinity {
	case api.ServiceAffinityNone:
		persistence = nil
	case api.ServiceAffinityClientIP:
		persistence = &vips.SessionPersistence{Type: "SOURCE_IP"}
	default:
		return nil, fmt.Errorf("unsupported load balancer affinity: %v", affinity)
	}

	lbmethod := lb.opts.LBMethod
	if lbmethod == "" {
		lbmethod = pools.LBMethodRoundRobin
	}
	pool, err := pools.Create(lb.network, pools.CreateOpts{
		Name:     name,
		Protocol: pools.ProtocolTCP,
		SubnetID: lb.opts.SubnetId,
		LBMethod: lbmethod,
	}).Extract()
	if err != nil {
		return nil, err
	}

	for _, host := range hosts {
		addr, err := getAddressByName(lb.compute, host)
		if err != nil {
			return nil, err
		}

		_, err = members.Create(lb.network, members.CreateOpts{
			PoolID:       pool.ID,
			ProtocolPort: ports[0].Port, //TODO: need to handle multi-port
			Address:      addr,
		}).Extract()
		if err != nil {
			pools.Delete(lb.network, pool.ID)
			return nil, err
		}
	}

	var mon *monitors.Monitor
	if lb.opts.CreateMonitor {
		mon, err = monitors.Create(lb.network, monitors.CreateOpts{
			Type:       monitors.TypeTCP,
			Delay:      int(lb.opts.MonitorDelay.Duration.Seconds()),
			Timeout:    int(lb.opts.MonitorTimeout.Duration.Seconds()),
			MaxRetries: int(lb.opts.MonitorMaxRetries),
		}).Extract()
		if err != nil {
			pools.Delete(lb.network, pool.ID)
			return nil, err
		}

		_, err = pools.AssociateMonitor(lb.network, pool.ID, mon.ID).Extract()
		if err != nil {
			monitors.Delete(lb.network, mon.ID)
			pools.Delete(lb.network, pool.ID)
			return nil, err
		}
	}

	createOpts := vips.CreateOpts{
		Name:         name,
		Description:  fmt.Sprintf("Kubernetes external service %s", name),
		Protocol:     "TCP",
		ProtocolPort: ports[0].Port, //TODO: need to handle multi-port
		PoolID:       pool.ID,
		Persistence:  persistence,
	}
	if !externalIP.IsUnspecified() {
		createOpts.Address = externalIP.String()
	}

	vip, err := vips.Create(lb.network, createOpts).Extract()
	if err != nil {
		if mon != nil {
			monitors.Delete(lb.network, mon.ID)
		}
		pools.Delete(lb.network, pool.ID)
		return nil, err
	}

	status := &api.LoadBalancerStatus{}
	status.Ingress = []api.LoadBalancerIngress{{IP: vip.Address}}

	return status, nil
}
Ejemplo n.º 20
0
// Checks if the mappings local IP address matches the IP address of the gateway
// For example, if we are explicitly listening on 192.168.0.12, there is no
// point trying to acquire a mapping on a gateway to which the local IP is
// 10.0.0.1. Fallback to true if any of the IPs is not there.
func (m *Mapping) validGateway(ip net.IP) bool {
	if m.address.IP == nil || ip == nil || m.address.IP.IsUnspecified() || ip.IsUnspecified() {
		return true
	}
	return m.address.IP.Equal(ip)
}
Ejemplo n.º 21
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"
	}
	ipStr := ""
	if ip != nil && !ip.IsUnspecified() {
		ipStr = ip.String()
	}

	key := bindKey{ip: ipStr, port: port}
	switch action {
	case iptables.Delete:
		// lookup commands to reverse
		if args, ok := p.bindings[key]; ok {
			if err := iptablesDelete(args); err != nil {
				return err
			}
			delete(p.bindings, bindKey{ipStr, port})
			return nil
		}
		return fmt.Errorf("Failed to find unmap data for %s:%d", ipStr, port)

	case iptables.Append:
		var savedArgs [][]string

		args := []string{"VIC", "-t", string(iptables.Nat),
			"-i", srcIface,
			"-p", proto,
			"-d", daddr,
			"--dport", strconv.Itoa(port),
			"-j", "DNAT",
			"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
		if err := iptablesRunAndCheck(action, args); err != nil {
			return err
		}
		savedArgs = append(savedArgs, args)
		p.bindings[key] = savedArgs

		// allow traffic from container to container via vch external interface
		args = []string{"VIC", "-t", string(iptables.Nat),
			"-i", destIface,
			"-p", proto,
			"--dport", strconv.Itoa(port),
			"-j", "DNAT",
			"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort)),
			"-m", "addrtype",
			"--dst-type", "LOCAL"}
		if err := iptablesRunAndCheck(action, args); err != nil {
			return err
		}
		savedArgs = append(savedArgs, args)
		p.bindings[key] = savedArgs

		args = []string{"VIC", "-t", string(iptables.Filter),
			"-i", srcIface,
			"-o", destIface,
			"-p", proto,
			"-d", destAddr,
			"--dport", strconv.Itoa(destPort),
			"-j", "ACCEPT"}
		if err := iptablesRunAndCheck(action, args); err != nil {
			return err
		}
		savedArgs = append(savedArgs, args)
		p.bindings[key] = savedArgs

		args = []string{"POSTROUTING", "-t", string(iptables.Nat),
			"-p", proto,
			"-d", destAddr,
			"--dport", strconv.Itoa(destPort),
			"-j", "MASQUERADE"}
		if err := iptablesRunAndCheck(action, args); err != nil {
			return err
		}
		savedArgs = append(savedArgs, args)
		p.bindings[key] = savedArgs
		return nil

	default:
		log.Warnf("noop for given operation: %s", action)
	}

	return nil
}
Ejemplo n.º 22
0
Archivo: ip.go Proyecto: kjplatz/vic
func IsUnspecifiedIP(ip net.IP) bool {
	return len(ip) == 0 || ip.IsUnspecified()
}