github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/xnet/addr.go (about)

     1  package xnet
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  )
     7  
     8  var (
     9  	privateBlocks []*net.IPNet
    10  )
    11  
    12  func init() {
    13  	for _, b := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"} {
    14  		if _, block, err := net.ParseCIDR(b); err == nil {
    15  			privateBlocks = append(privateBlocks, block)
    16  		}
    17  	}
    18  }
    19  
    20  func isPrivateIP(ipAddr string) bool {
    21  	ip := net.ParseIP(ipAddr)
    22  	for _, priv := range privateBlocks {
    23  		if priv.Contains(ip) {
    24  			return true
    25  		}
    26  	}
    27  	return false
    28  }
    29  
    30  // PrivateAddress returns a real ip
    31  func PrivateAddress() (string, error) {
    32  	ifaces, err := net.Interfaces()
    33  	if err != nil {
    34  		return "", fmt.Errorf("failed to get interfaces! Err: %v", err)
    35  	}
    36  
    37  	var addrs []net.Addr
    38  	for _, iface := range ifaces {
    39  		ifaceAddrs, err := iface.Addrs()
    40  		if err != nil {
    41  			// ignore error, interface can dissapear from system
    42  			continue
    43  		}
    44  		addrs = append(addrs, ifaceAddrs...)
    45  	}
    46  
    47  	var ipAddr []byte
    48  	var publicIP []byte
    49  
    50  	for _, rawAddr := range addrs {
    51  		var ip net.IP
    52  		switch addr := rawAddr.(type) {
    53  		case *net.IPAddr:
    54  			ip = addr.IP
    55  		case *net.IPNet:
    56  			ip = addr.IP
    57  		default:
    58  			continue
    59  		}
    60  
    61  		if !isPrivateIP(ip.String()) {
    62  			publicIP = ip
    63  			continue
    64  		}
    65  
    66  		ipAddr = ip
    67  		break
    68  	}
    69  
    70  	// return private ip
    71  	if ipAddr != nil {
    72  		return net.IP(ipAddr).String(), nil
    73  	}
    74  
    75  	// return public or virtual ip
    76  	if publicIP != nil {
    77  		return net.IP(publicIP).String(), nil
    78  	}
    79  
    80  	return "", fmt.Errorf("err: no IP address found, and explicit IP not provided")
    81  }
    82  
    83  // IPAddresses returns all known ips
    84  func IPAddresses() []string {
    85  	ifaces, err := net.Interfaces()
    86  	if err != nil {
    87  		return nil
    88  	}
    89  
    90  	var ipAddrs []string
    91  
    92  	for _, i := range ifaces {
    93  		addrs, err := i.Addrs()
    94  		if err != nil {
    95  			continue
    96  		}
    97  
    98  		for _, addr := range addrs {
    99  			var ip net.IP
   100  			switch v := addr.(type) {
   101  			case *net.IPNet:
   102  				ip = v.IP
   103  			case *net.IPAddr:
   104  				ip = v.IP
   105  			}
   106  
   107  			if ip == nil {
   108  				continue
   109  			}
   110  
   111  			// dont skip ipv6 addrs
   112  			/*
   113  				ip = ip.To4()
   114  				if ip == nil {
   115  					continue
   116  				}
   117  			*/
   118  
   119  			ipAddrs = append(ipAddrs, ip.String())
   120  		}
   121  	}
   122  
   123  	return ipAddrs
   124  }