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 }