package ipx import ( "fmt" "math" "math/rand" "net" "net/http" "strings" ) func RemoteAddr(r *http.Request, mustPublic bool) string { if r == nil { return "" } for _, key := range []string{"X-Forwarded-For", "X-Real-IP", "X-Appengine-Remote-Addr"} { value := r.Header.Get(key) if value != "" { for _, item := range strings.Split(value, ",") { var ip string if strings.ContainsRune(item, ':') { if host, _, err := net.SplitHostPort(strings.TrimSpace(item)); err != nil { continue } else { ip = host } } else { ip = strings.TrimSpace(item) } if mustPublic { if v, e := IsPublic(ip); e != nil && v { return ip } } else { return ip } } } } return r.RemoteAddr } func LocalAddr() string { addresses, err := net.InterfaceAddrs() if err != nil { return "" } addr := "" for _, address := range addresses { if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && !ipNet.IP.IsPrivate() && !ipNet.IP.IsLinkLocalUnicast() { if ipNet.IP.To4() != nil { addr = ipNet.IP.String() break } } } if addr == "" { for _, address := range []string{"114.114.114.114:53", "8.8.8.8:53"} { var conn net.Conn conn, err = net.Dial("udp", address) if err == nil { conn.Close() localAddr := conn.LocalAddr().(*net.UDPAddr) addr = strings.Split(localAddr.String(), ":")[0] break } } } return addr } func IsPrivate(ip string) (v bool, err error) { addr := net.ParseIP(ip) if addr == nil { err = fmt.Errorf("ipx: %s address is invalid", ip) } else { v = addr.IsLoopback() || addr.IsPrivate() || addr.IsLinkLocalUnicast() } return } func IsPublic(ip string) (v bool, err error) { v, err = IsPrivate(ip) v = err == nil && !v return } func Number(ip string) (uint, error) { addr := net.ParseIP(ip) if addr == nil { return 0, fmt.Errorf("ipx: %s is invalid ip", ip) } return uint(addr[3]) | uint(addr[2])<<8 | uint(addr[1])<<16 | uint(addr[0])<<24, nil } func Random() string { size := 4 ip := make([]byte, size) for i := 0; i < size; i++ { ip[i] = byte(rand.Intn(256)) } return net.IP(ip).To4().String() } func String(ip uint) (string, error) { if ip > math.MaxUint32 { return "", fmt.Errorf("ipx: %d is not valid ipv4", ip) } addr := make(net.IP, net.IPv4len) addr[0] = byte(ip >> 24) addr[1] = byte(ip >> 16) addr[2] = byte(ip >> 8) addr[3] = byte(ip) return addr.String(), nil }