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 }
// 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") }
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" }
// 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 }
// 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 }
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 }
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 }
// 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 }
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 }
// 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 }
// 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 }
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 }
// 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)) }() }
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 }
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) }
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) }
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) }
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 }
// 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) }
// 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 }
func IsUnspecifiedIP(ip net.IP) bool { return len(ip) == 0 || ip.IsUnspecified() }