2019-05-30 23:52:10 +01: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
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract returns a real ip
|
|
|
|
func Extract(addr string) (string, error) {
|
|
|
|
// if addr specified then its returned
|
2019-07-17 10:38:50 +03:00
|
|
|
if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") {
|
2019-05-30 23:52:10 +01:00
|
|
|
return addr, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ifaces, err := net.Interfaces()
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("Failed to get interfaces! Err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var addrs []net.Addr
|
2019-08-27 23:33:30 +08:00
|
|
|
var loAddrs []net.Addr
|
2019-05-30 23:52:10 +01:00
|
|
|
for _, iface := range ifaces {
|
|
|
|
ifaceAddrs, err := iface.Addrs()
|
|
|
|
if err != nil {
|
|
|
|
// ignore error, interface can dissapear from system
|
|
|
|
continue
|
|
|
|
}
|
2019-08-26 14:37:49 +08:00
|
|
|
if iface.Flags&net.FlagLoopback != 0 {
|
2019-08-27 23:33:30 +08:00
|
|
|
loAddrs = append(loAddrs, ifaceAddrs...)
|
2019-08-26 14:37:49 +08:00
|
|
|
continue
|
|
|
|
}
|
2019-05-30 23:52:10 +01:00
|
|
|
addrs = append(addrs, ifaceAddrs...)
|
|
|
|
}
|
2019-08-27 23:33:30 +08:00
|
|
|
addrs = append(addrs, loAddrs...)
|
2019-05-30 23:52:10 +01: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
|
|
|
|
}
|
|
|
|
|
2019-07-17 10:38:50 +03:00
|
|
|
// dont skip ipv6 addrs
|
|
|
|
/*
|
|
|
|
ip = ip.To4()
|
|
|
|
if ip == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
*/
|
2019-05-30 23:52:10 +01:00
|
|
|
|
|
|
|
ipAddrs = append(ipAddrs, ip.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipAddrs
|
|
|
|
}
|