package tool import ( "encoding/binary" "errors" "fmt" "net" ) var ( privateIPv4Blocks []*net.IPNet privateIPv6Blocks []*net.IPNet ) func init() { // IPv4私有地址段 for _, cidr := range []string{ "10.0.0.0/8", // A类私有地址 "172.16.0.0/12", // B类私有地址 "192.168.0.0/16", // C类私有地址 "169.254.0.0/16", // 链路本地地址 "127.0.0.0/8", // 环回地址 } { _, block, _ := net.ParseCIDR(cidr) privateIPv4Blocks = append(privateIPv4Blocks, block) } // IPv6私有地址段 for _, cidr := range []string{ "fc00::/7", // 唯一本地地址 "fe80::/10", // 链路本地地址 "::1/128", // 环回地址 } { _, block, _ := net.ParseCIDR(cidr) privateIPv6Blocks = append(privateIPv6Blocks, block) } } func IsPrivateIP(ipStr string) bool { ip := net.ParseIP(ipStr) if ip == nil { return false } // 处理IPv4和IPv4映射的IPv6地址 if ip4 := ip.To4(); ip4 != nil { for _, block := range privateIPv4Blocks { if block.Contains(ip4) { return true } } return false } // 处理IPv6地址 for _, block := range privateIPv6Blocks { if block.Contains(ip) { return true } } return false } func IP2Int(ip net.IP) uint32 { if ip == nil { return 0 } ip = ip.To4() if ip == nil { return 0 } return binary.BigEndian.Uint32(ip) } func Int2IP(ip uint32) net.IP { data := make(net.IP, 4) binary.BigEndian.PutUint32(data, ip) return data } func IPStr2Int(ipStr string) *uint32 { ip := IP2Int(net.ParseIP(ipStr)) if ip == 0 { return nil } return &ip } func Int2IPStr(ip uint32) string { return Int2IP(ip).String() } func GetLastIP4(cidr string) (lastIP4 uint32, err error) { ip, ipNet, err := net.ParseCIDR(cidr) if err != nil { return } firstIP4 := IP2Int(ip.Mask(ipNet.Mask)) ipNetMaskInt := binary.BigEndian.Uint32(ipNet.Mask) lastIP4 = firstIP4 | ^ipNetMaskInt return } func IsCIDRConflict(cidr1, cidr2 string) (conflict bool, err error) { _, ipNet1, err := net.ParseCIDR(cidr1) if err != nil { return } _, ipNet2, err := net.ParseCIDR(cidr2) if err != nil { return } if ipNet2.Contains(ipNet1.IP) || ipNet1.Contains(ipNet2.IP) { conflict = true } return } func GetCIDRs(startCIDR, endCIDR string, mask uint8) (cidrs []string, err error) { cidrs = append(cidrs, startCIDR) currentCIDR := startCIDR for { lastIP4, err := GetLastIP4(currentCIDR) if err != nil { return cidrs, err } nextCIDR := Int2IPStr(lastIP4+1) + fmt.Sprintf("/%d", mask) cidrs = append(cidrs, nextCIDR) conflict, err := IsCIDRConflict(nextCIDR, endCIDR) if err != nil { return cidrs, err } if conflict { break } currentCIDR = nextCIDR } return } func GetLocalIP() (ip string, err error) { ifaces, err := net.Interfaces() if err != nil { return } for _, iface := range ifaces { if iface.Name != "eth0" { continue } addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { switch v := addr.(type) { case *net.IPNet: ip = v.IP.String() if ip == "192.168.88.88" { continue } return ip, err case *net.IPAddr: ip = v.IP.String() if ip == "192.168.88.88" { continue } return ip, err } } } ip = "127.0.0.1" return } func LookupIP(host string) (ip string, err error) { ips, err := net.LookupIP(host) if err != nil { return } for _, i := range ips { if ipv4 := i.To4(); ipv4 != nil { ip = ipv4.String() break } } return } func LookupIPv4(host string) (uint32, error) { ips, err := net.LookupIP(host) if err != nil { return 0, err } for _, i := range ips { if ipv4 := i.To4(); ipv4 != nil { return binary.BigEndian.Uint32(ipv4), nil } } return 0, errors.New("host not found " + host) } func ResolveIPv4(host string) (uint32, error) { addr, err := net.ResolveIPAddr("ip4", host) if err == nil && addr != nil { addrV4 := binary.BigEndian.Uint32(addr.IP.To4()) return addrV4, err } return 0, err }