bf8b3aeac7
* remove redundant code * check invalid ip address first * remove redundant code * cleanup Co-authored-by: 刘海洋 <haiyang@snqu.com>
151 lines
2.5 KiB
Go
151 lines
2.5 KiB
Go
package addr
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
var (
|
|
privateBlocks []*net.IPNet
|
|
)
|
|
|
|
func init() {
|
|
blocks := []string{
|
|
"10.0.0.0/8",
|
|
"172.16.0.0/12",
|
|
"192.168.0.0/16",
|
|
"100.64.0.0/10",
|
|
"fd00::/8",
|
|
}
|
|
AppendPrivateBlocks(blocks...)
|
|
}
|
|
|
|
// AppendPrivateBlocks append private network blocks
|
|
func AppendPrivateBlocks(bs ...string) {
|
|
for _, b := range bs {
|
|
if _, block, err := net.ParseCIDR(b); err == nil {
|
|
privateBlocks = append(privateBlocks, block)
|
|
}
|
|
}
|
|
}
|
|
|
|
func isPrivateIP(ipAddr string) bool {
|
|
ip := net.ParseIP(ipAddr)
|
|
if ip == nil {
|
|
return false
|
|
}
|
|
|
|
for _, blocks := range privateBlocks {
|
|
if blocks.Contains(ip) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func addrToIP(addr net.Addr) net.IP {
|
|
switch v := addr.(type) {
|
|
case *net.IPAddr:
|
|
return v.IP
|
|
case *net.IPNet:
|
|
return v.IP
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func localIPs() []string {
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
var ipAddrs []string
|
|
|
|
for _, iface := range ifaces {
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
continue // ignore error
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
if ip := addrToIP(addr); ip != nil {
|
|
ipAddrs = append(ipAddrs, ip.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
return ipAddrs
|
|
}
|
|
|
|
// 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 localIPs() {
|
|
if addr == ip {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Extract returns a real ip
|
|
func Extract(addr string) (string, error) {
|
|
// if addr specified then its returned
|
|
if len(addr) > 0 {
|
|
if addr != "0.0.0.0" && addr != "[::]" && addr != "::" {
|
|
return addr, nil
|
|
}
|
|
}
|
|
|
|
var privateAddrs []string
|
|
var publicAddrs []string
|
|
var loopbackAddrs []string
|
|
|
|
for _, ipAddr := range localIPs() {
|
|
ip := net.ParseIP(ipAddr)
|
|
if ip == nil {
|
|
continue
|
|
}
|
|
|
|
if ip.IsUnspecified() {
|
|
continue
|
|
}
|
|
|
|
if ip.IsLoopback() {
|
|
loopbackAddrs = append(loopbackAddrs, ipAddr)
|
|
} else if isPrivateIP(ipAddr) {
|
|
privateAddrs = append(privateAddrs, ipAddr)
|
|
} else {
|
|
publicAddrs = append(publicAddrs, ipAddr)
|
|
}
|
|
}
|
|
|
|
if len(privateAddrs) > 0 {
|
|
return privateAddrs[0], nil
|
|
} else if len(publicAddrs) > 0 {
|
|
return publicAddrs[0], nil
|
|
} else if len(loopbackAddrs) > 0 {
|
|
return loopbackAddrs[0], nil
|
|
}
|
|
|
|
return "", fmt.Errorf("No IP address found, and explicit IP not provided")
|
|
}
|
|
|
|
// IPs returns all known ips
|
|
func IPs() []string {
|
|
return localIPs()
|
|
}
|