github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/ip.go (about)

     1  package util
     2  
     3  import (
     4  	"net"
     5  	"net/http"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  // InternalIPv4 获取内网地址 (IPv4)
    11  func InternalIPv4() string {
    12  	return InternalIP("", "udp4")
    13  }
    14  
    15  // InternalIPv6 获取内网地址 (临时 IPv6 地址)
    16  func InternalIPv6() string {
    17  	return InternalIP("[2001:4860:4860::8888]:53", "udp6")
    18  }
    19  
    20  // InternalIP 获取内网地址 (出口本地地址)
    21  func InternalIP(dstAddr, network string) string {
    22  	if dstAddr == "" {
    23  		dstAddr = "8.8.8.8:53"
    24  	}
    25  	if network == "" {
    26  		network = "udp"
    27  	}
    28  
    29  	conn, err := net.DialTimeout(network, dstAddr, time.Second)
    30  	if err != nil {
    31  		return ""
    32  	}
    33  
    34  	defer func() {
    35  		_ = conn.Close()
    36  	}()
    37  
    38  	addr := conn.LocalAddr().String()
    39  	ip := net.ParseIP(addr).String()
    40  	if ip == "<nil>" {
    41  		ip, _, _ = net.SplitHostPort(addr)
    42  	}
    43  
    44  	return ip
    45  }
    46  
    47  // LocalIP 获取本地地址 (第一个)
    48  func LocalIP() string {
    49  	addrs, err := net.InterfaceAddrs()
    50  	if err == nil {
    51  		for _, addr := range addrs {
    52  			if ipnet, ok := addr.(*net.IPNet); ok &&
    53  				!ipnet.IP.IsLinkLocalUnicast() && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
    54  				return ipnet.IP.String()
    55  			}
    56  		}
    57  	}
    58  
    59  	return ""
    60  }
    61  
    62  // LocalIPv4s 获取所有本地地址 IPv4
    63  func LocalIPv4s() (ips []string) {
    64  	addrs, err := net.InterfaceAddrs()
    65  	if err == nil {
    66  		for _, addr := range addrs {
    67  			if ipnet, ok := addr.(*net.IPNet); ok &&
    68  				!ipnet.IP.IsLinkLocalUnicast() && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
    69  				ips = append(ips, ipnet.IP.String())
    70  			}
    71  		}
    72  	}
    73  
    74  	return
    75  }
    76  
    77  // InterfaceAddrs 获取所有带 IP 的接口和对应的所有 IP
    78  // 排除本地链路地址和环回地址
    79  func InterfaceAddrs(v ...string) (map[string][]net.IP, error) {
    80  	ifAddrs := make(map[string][]net.IP)
    81  	ifaces, err := net.Interfaces()
    82  	if err != nil {
    83  		return ifAddrs, err
    84  	}
    85  
    86  	var (
    87  		ip net.IP
    88  		t  string
    89  	)
    90  	if len(v) > 0 {
    91  		t = strings.ToLower(v[0])
    92  	}
    93  
    94  	for _, i := range ifaces {
    95  		addrs, err := i.Addrs()
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  		for _, addr := range addrs {
   100  			switch v := addr.(type) {
   101  			case *net.IPNet:
   102  				ip = v.IP
   103  			case *net.IPAddr:
   104  				ip = v.IP
   105  			default:
   106  				ip = net.IPv4zero
   107  			}
   108  			if ip.IsLinkLocalUnicast() || ip.IsLoopback() {
   109  				continue
   110  			}
   111  			switch t {
   112  			case "ipv6":
   113  				if ip.To4() != nil {
   114  					continue
   115  				}
   116  			case "ipv4":
   117  				if ip.To4() == nil {
   118  					continue
   119  				}
   120  			}
   121  			ifAddrs[i.Name] = append(ifAddrs[i.Name], ip)
   122  		}
   123  	}
   124  	return ifAddrs, nil
   125  }
   126  
   127  // GetRealIP get user real ip
   128  func GetRealIP(r *http.Request) (ip string) {
   129  	var header = r.Header
   130  	var index int
   131  	if ip = header.Get("X-Forwarded-For"); ip != "" {
   132  		index = strings.IndexByte(ip, ',')
   133  		if index < 0 {
   134  			return ip
   135  		}
   136  		if ip = ip[:index]; ip != "" {
   137  			return ip
   138  		}
   139  	}
   140  	if ip = header.Get("X-Real-Ip"); ip != "" {
   141  		index = strings.IndexByte(ip, ',')
   142  		if index < 0 {
   143  			return ip
   144  		}
   145  		if ip = ip[:index]; ip != "" {
   146  			return ip
   147  		}
   148  	}
   149  	if ip = header.Get("Proxy-Forwarded-For"); ip != "" {
   150  		index = strings.IndexByte(ip, ',')
   151  		if index < 0 {
   152  			return ip
   153  		}
   154  		if ip = ip[:index]; ip != "" {
   155  			return ip
   156  		}
   157  	}
   158  	ip, _, err := net.SplitHostPort(r.RemoteAddr)
   159  	if err != nil {
   160  		return ""
   161  	}
   162  
   163  	return ip
   164  }