Files
hiscaler-gox/ipx/ip.go

124 lines
2.4 KiB
Go
Raw Normal View History

2025-04-08 19:16:39 +02:00
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
}