github.com/marwan-at-work/consul@v1.4.5/ipaddr/detect.go (about)

     1  package ipaddr
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  )
     7  
     8  // GetPrivateIPv4 returns the list of private network IPv4 addresses on
     9  // all active interfaces.
    10  func GetPrivateIPv4() ([]*net.IPAddr, error) {
    11  	addresses, err := activeInterfaceAddresses()
    12  	if err != nil {
    13  		return nil, fmt.Errorf("Failed to get interface addresses: %v", err)
    14  	}
    15  
    16  	var addrs []*net.IPAddr
    17  	for _, rawAddr := range addresses {
    18  		var ip net.IP
    19  		switch addr := rawAddr.(type) {
    20  		case *net.IPAddr:
    21  			ip = addr.IP
    22  		case *net.IPNet:
    23  			ip = addr.IP
    24  		default:
    25  			continue
    26  		}
    27  		if ip.To4() == nil {
    28  			continue
    29  		}
    30  		if !isPrivate(ip) {
    31  			continue
    32  		}
    33  		addrs = append(addrs, &net.IPAddr{IP: ip})
    34  	}
    35  	return addrs, nil
    36  }
    37  
    38  // GetPublicIPv6 returns the list of all public IPv6 addresses
    39  // on all active interfaces.
    40  func GetPublicIPv6() ([]*net.IPAddr, error) {
    41  	addresses, err := net.InterfaceAddrs()
    42  	if err != nil {
    43  		return nil, fmt.Errorf("Failed to get interface addresses: %v", err)
    44  	}
    45  
    46  	var addrs []*net.IPAddr
    47  	for _, rawAddr := range addresses {
    48  		var ip net.IP
    49  		switch addr := rawAddr.(type) {
    50  		case *net.IPAddr:
    51  			ip = addr.IP
    52  		case *net.IPNet:
    53  			ip = addr.IP
    54  		default:
    55  			continue
    56  		}
    57  		if ip.To4() != nil {
    58  			continue
    59  		}
    60  		if isPrivate(ip) {
    61  			continue
    62  		}
    63  		addrs = append(addrs, &net.IPAddr{IP: ip})
    64  	}
    65  	return addrs, nil
    66  }
    67  
    68  // privateBlocks contains non-forwardable address blocks which are used
    69  // for private networks. RFC 6890 provides an overview of special
    70  // address blocks.
    71  var privateBlocks = []*net.IPNet{
    72  	parseCIDR("10.0.0.0/8"),     // RFC 1918 IPv4 private network address
    73  	parseCIDR("100.64.0.0/10"),  // RFC 6598 IPv4 shared address space
    74  	parseCIDR("127.0.0.0/8"),    // RFC 1122 IPv4 loopback address
    75  	parseCIDR("169.254.0.0/16"), // RFC 3927 IPv4 link local address
    76  	parseCIDR("172.16.0.0/12"),  // RFC 1918 IPv4 private network address
    77  	parseCIDR("192.0.0.0/24"),   // RFC 6890 IPv4 IANA address
    78  	parseCIDR("192.0.2.0/24"),   // RFC 5737 IPv4 documentation address
    79  	parseCIDR("192.168.0.0/16"), // RFC 1918 IPv4 private network address
    80  	parseCIDR("::1/128"),        // RFC 1884 IPv6 loopback address
    81  	parseCIDR("fe80::/10"),      // RFC 4291 IPv6 link local addresses
    82  	parseCIDR("fc00::/7"),       // RFC 4193 IPv6 unique local addresses
    83  	parseCIDR("fec0::/10"),      // RFC 1884 IPv6 site-local addresses
    84  	parseCIDR("2001:db8::/32"),  // RFC 3849 IPv6 documentation address
    85  }
    86  
    87  func parseCIDR(s string) *net.IPNet {
    88  	_, block, err := net.ParseCIDR(s)
    89  	if err != nil {
    90  		panic(fmt.Sprintf("Bad CIDR %s: %s", s, err))
    91  	}
    92  	return block
    93  }
    94  
    95  func isPrivate(ip net.IP) bool {
    96  	for _, priv := range privateBlocks {
    97  		if priv.Contains(ip) {
    98  			return true
    99  		}
   100  	}
   101  	return false
   102  }
   103  
   104  // Returns addresses from interfaces that is up
   105  func activeInterfaceAddresses() ([]net.Addr, error) {
   106  	var upAddrs []net.Addr
   107  	var loAddrs []net.Addr
   108  
   109  	interfaces, err := net.Interfaces()
   110  	if err != nil {
   111  		return nil, fmt.Errorf("Failed to get interfaces: %v", err)
   112  	}
   113  
   114  	for _, iface := range interfaces {
   115  		// Require interface to be up
   116  		if iface.Flags&net.FlagUp == 0 {
   117  			continue
   118  		}
   119  
   120  		addresses, err := iface.Addrs()
   121  		if err != nil {
   122  			return nil, fmt.Errorf("Failed to get interface addresses: %v", err)
   123  		}
   124  
   125  		if iface.Flags&net.FlagLoopback != 0 {
   126  			loAddrs = append(loAddrs, addresses...)
   127  			continue
   128  		}
   129  
   130  		upAddrs = append(upAddrs, addresses...)
   131  	}
   132  
   133  	if len(upAddrs) == 0 {
   134  		return loAddrs, nil
   135  	}
   136  
   137  	return upAddrs, nil
   138  }