micro/util/addr/addr.go

160 lines
2.7 KiB
Go
Raw Normal View History

2019-05-31 01:52:10 +03:00
package addr
import (
"fmt"
"net"
)
var (
privateBlocks []*net.IPNet
)
func init() {
for _, b := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"} {
if _, block, err := net.ParseCIDR(b); err == nil {
privateBlocks = append(privateBlocks, block)
}
}
}
func isPrivateIP(ipAddr string) bool {
ip := net.ParseIP(ipAddr)
for _, priv := range privateBlocks {
if priv.Contains(ip) {
return true
}
}
return false
}
// IsLocal tells us whether an ip is local
func IsLocal(addr string) bool {
// extract the host
host, _, err := net.SplitHostPort(addr)
if err == nil {
addr = host
}
// check if its localhost
if addr == "localhost" {
return true
}
// check against all local ips
for _, ip := range IPs() {
if addr == ip {
return true
}
}
return false
}
2019-05-31 01:52:10 +03:00
// Extract returns a real ip
func Extract(addr string) (string, error) {
// if addr specified then its returned
if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") {
2019-05-31 01:52:10 +03:00
return addr, nil
}
ifaces, err := net.Interfaces()
if err != nil {
return "", fmt.Errorf("Failed to get interfaces! Err: %v", err)
}
//nolint:prealloc
2019-05-31 01:52:10 +03:00
var addrs []net.Addr
var loAddrs []net.Addr
2019-05-31 01:52:10 +03:00
for _, iface := range ifaces {
ifaceAddrs, err := iface.Addrs()
if err != nil {
// ignore error, interface can dissapear from system
continue
}
2019-08-26 09:37:49 +03:00
if iface.Flags&net.FlagLoopback != 0 {
loAddrs = append(loAddrs, ifaceAddrs...)
2019-08-26 09:37:49 +03:00
continue
}
2019-05-31 01:52:10 +03:00
addrs = append(addrs, ifaceAddrs...)
}
addrs = append(addrs, loAddrs...)
2019-05-31 01:52:10 +03:00
var ipAddr []byte
var publicIP []byte
for _, rawAddr := range addrs {
var ip net.IP
switch addr := rawAddr.(type) {
case *net.IPAddr:
ip = addr.IP
case *net.IPNet:
ip = addr.IP
default:
continue
}
if !isPrivateIP(ip.String()) {
publicIP = ip
continue
}
ipAddr = ip
break
}
// return private ip
if ipAddr != nil {
return net.IP(ipAddr).String(), nil
}
// return public or virtual ip
if publicIP != nil {
return net.IP(publicIP).String(), nil
}
return "", fmt.Errorf("No IP address found, and explicit IP not provided")
}
// IPs returns all known ips
func IPs() []string {
ifaces, err := net.Interfaces()
if err != nil {
return nil
}
var ipAddrs []string
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
continue
}
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 {
continue
}
// dont skip ipv6 addrs
/*
ip = ip.To4()
if ip == nil {
continue
}
*/
2019-05-31 01:52:10 +03:00
ipAddrs = append(ipAddrs, ip.String())
}
}
return ipAddrs
}