github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/znet/ip.go (about)

     1  package znet
     2  
     3  import (
     4  	"errors"
     5  	"math"
     6  	"math/big"
     7  	"net"
     8  	"net/http"
     9  	"strconv"
    10  	"strings"
    11  	"sync"
    12  )
    13  
    14  var (
    15  	RemoteIPHeaders = []string{"X-Forwarded-For", "X-Real-IP"}
    16  	TrustedProxies  = []string{"0.0.0.0/0"}
    17  	LocalNetworks   = []string{"127.0.0.0/8", "10.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "172.0.0.0/8", "192.168.0.0/16"}
    18  )
    19  
    20  var (
    21  	localNetworks     []*net.IPNet
    22  	localNetworksOnce sync.Once
    23  )
    24  
    25  func getLocalNetworks() []*net.IPNet {
    26  	localNetworksOnce.Do(func() {
    27  		localNetworks = make([]*net.IPNet, 0, len(LocalNetworks))
    28  		for _, sNetwork := range LocalNetworks {
    29  			_, network, err := net.ParseCIDR(sNetwork)
    30  			if err == nil {
    31  				localNetworks = append(localNetworks, network)
    32  			}
    33  		}
    34  	})
    35  	return localNetworks
    36  }
    37  
    38  // IsLocalAddrIP IsLocalAddrIP
    39  func IsLocalAddrIP(ip string) bool {
    40  	return IsLocalIP(net.ParseIP(ip))
    41  }
    42  
    43  // IsLocalIP IsLocalIP
    44  func IsLocalIP(ip net.IP) bool {
    45  	for _, network := range getLocalNetworks() {
    46  		if network.Contains(ip) {
    47  			return true
    48  		}
    49  	}
    50  	if ip.String() == "0.0.0.0" {
    51  		return true
    52  	}
    53  	return ip.IsLoopback() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast()
    54  }
    55  
    56  func getTrustedIP(r *http.Request, remoteIP string) string {
    57  	ip := remoteIP
    58  	for i := range RemoteIPHeaders {
    59  		key := RemoteIPHeaders[i]
    60  		val := r.Header.Get(key)
    61  		ips := parseHeadersIP(val)
    62  		for i := range ips {
    63  			Log.Debug(i, ips[i])
    64  		}
    65  	}
    66  	return ip
    67  }
    68  
    69  func getRemoteIP(r *http.Request) []string {
    70  	ips := make([]string, 0)
    71  	ip := RemoteIP(r)
    72  	trusted := ip == ""
    73  	if !trusted {
    74  		if len(TrustedProxies) > 0 {
    75  			for i := range TrustedProxies {
    76  				proxy := TrustedProxies[i]
    77  				if InNetwork(ip, proxy) {
    78  					trusted = true
    79  					break
    80  				}
    81  			}
    82  		} else {
    83  			trusted = true
    84  		}
    85  	}
    86  
    87  	if trusted {
    88  		for i := range RemoteIPHeaders {
    89  			key := RemoteIPHeaders[i]
    90  			val := r.Header.Get(key)
    91  			ips = append(ips, parseHeadersIP(val)...)
    92  		}
    93  	}
    94  	return append(ips, ip)
    95  }
    96  
    97  func parseHeadersIP(val string) []string {
    98  	if val == "" {
    99  		return []string{}
   100  	}
   101  	str := strings.Split(val, ",")
   102  	l := len(str)
   103  	ips := make([]string, l)
   104  	for i := l - 1; i >= 0; i-- {
   105  		ips[l-1-i] = strings.TrimSpace(str[i])
   106  	}
   107  	return ips
   108  }
   109  
   110  // ClientIP ClientIP
   111  func ClientIP(r *http.Request) (ip string) {
   112  	ips := getRemoteIP(r)
   113  	if len(ips) > 0 && ips[0] != "" {
   114  		return ips[0]
   115  	}
   116  	return
   117  }
   118  
   119  // ClientPublicIP ClientPublicIP
   120  func ClientPublicIP(r *http.Request) string {
   121  	var ip string
   122  	ips := getRemoteIP(r)
   123  	for i := range ips {
   124  		ip = ips[i]
   125  		if ip != "" && !IsLocalAddrIP(ip) {
   126  			return ip
   127  		}
   128  	}
   129  	return ""
   130  }
   131  
   132  // RemoteIP Remote IP
   133  func RemoteIP(r *http.Request) string {
   134  	if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
   135  		return ip
   136  	}
   137  
   138  	return ""
   139  }
   140  
   141  // IPToLong IPToLong
   142  func IPToLong(ip string) (i uint, err error) {
   143  	return NetIPToLong(net.ParseIP(ip))
   144  }
   145  
   146  // LongToIP LongToIP
   147  func LongToIP(i uint) (string, error) {
   148  	ip, err := LongToNetIP(i)
   149  	if err != nil {
   150  		return "", err
   151  	}
   152  
   153  	return ip.String(), nil
   154  }
   155  
   156  // NetIPToLong NetIPToLong
   157  func NetIPToLong(ip net.IP) (i uint, err error) {
   158  	b := ip.To4()
   159  	if b == nil {
   160  		err = errors.New("invalid ipv4 format")
   161  		return
   162  	}
   163  
   164  	i = uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24
   165  	return
   166  }
   167  
   168  // NetIPv6ToLong NetIPv6ToLong
   169  func NetIPv6ToLong(ip net.IP) (*big.Int, error) {
   170  	if ip == nil {
   171  		return nil, errors.New("invalid ipv6 format")
   172  	}
   173  	IPv6Int := big.NewInt(0)
   174  	IPv6Int.SetBytes(ip.To16())
   175  	return IPv6Int, nil
   176  }
   177  
   178  // LongToNetIP LongToNetIP
   179  func LongToNetIP(i uint) (ip net.IP, err error) {
   180  	if i > math.MaxUint32 {
   181  		err = errors.New("beyond the scope of ipv4")
   182  		return
   183  	}
   184  
   185  	ip = make(net.IP, net.IPv4len)
   186  	ip[0] = byte(i >> 24)
   187  	ip[1] = byte(i >> 16)
   188  	ip[2] = byte(i >> 8)
   189  	ip[3] = byte(i)
   190  
   191  	return
   192  }
   193  
   194  // LongToNetIPv6 LongToNetIPv6
   195  func LongToNetIPv6(i *big.Int) (ip net.IP, err error) {
   196  	ip = i.Bytes()
   197  	return
   198  }
   199  
   200  // IsIP IsIP
   201  func IsIP(ip string) bool {
   202  	return net.ParseIP(ip) != nil
   203  }
   204  
   205  // GetIPv GetIPv
   206  func GetIPv(s string) int {
   207  	for i := 0; i < len(s); i++ {
   208  		switch s[i] {
   209  		case '.':
   210  			return 4
   211  		case ':':
   212  			return 6
   213  		}
   214  	}
   215  	return 0
   216  }
   217  
   218  func netCIDR(network string) (*net.IPNet, error) {
   219  	_, n, err := net.ParseCIDR(network)
   220  	if err != nil && IsIP(network) {
   221  		_, n, err = net.ParseCIDR(network + "/24")
   222  	}
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	return n, nil
   227  }
   228  
   229  // InNetwork InNetwork
   230  func InNetwork(ip, network string) bool {
   231  	n, err := netCIDR(network)
   232  	if err != nil {
   233  		return false
   234  	}
   235  	netIP := net.ParseIP(ip)
   236  	return n.Contains(netIP)
   237  }
   238  
   239  // Port GetPort Check if the port is available, if not, then automatically get an available
   240  func Port(port int, change bool) (newPort int, err error) {
   241  	host := ":" + strconv.Itoa(port)
   242  	listener, err := net.Listen("tcp", host)
   243  	if err != nil {
   244  		if !change && port != 0 {
   245  			return 0, err
   246  		}
   247  		listener, err = net.Listen("tcp", ":0")
   248  		if err != nil {
   249  			return 0, err
   250  		}
   251  	}
   252  	defer listener.Close()
   253  	addr := listener.Addr().String()
   254  	_, portString, err := net.SplitHostPort(addr)
   255  	if err != nil {
   256  		return 0, err
   257  	}
   258  	return strconv.Atoi(portString)
   259  }
   260  
   261  // MultiplePort Check if the multiple port is available, if not, then automatically get an available
   262  func MultiplePort(ports []int, change bool) (int, error) {
   263  	last := len(ports) - 1
   264  	for k, v := range ports {
   265  		c := false
   266  		if last == k {
   267  			c = change
   268  		}
   269  		n, err := Port(v, c)
   270  		if err == nil {
   271  			return n, nil
   272  		}
   273  	}
   274  	return 0, errors.New("no available port")
   275  }