github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/util/addr/addr.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/util/addr/addr.go
    14  
    15  package addr
    16  
    17  import (
    18  	"fmt"
    19  	"net"
    20  )
    21  
    22  var (
    23  	privateBlocks []*net.IPNet
    24  )
    25  
    26  func init() {
    27  	blocks := []string{
    28  		"10.0.0.0/8",
    29  		"172.16.0.0/12",
    30  		"192.168.0.0/16",
    31  		"100.64.0.0/10",
    32  		"fd00::/8",
    33  	}
    34  	AppendPrivateBlocks(blocks...)
    35  }
    36  
    37  // AppendPrivateBlocks append private network blocks
    38  func AppendPrivateBlocks(bs ...string) {
    39  	for _, b := range bs {
    40  		if _, block, err := net.ParseCIDR(b); err == nil {
    41  			privateBlocks = append(privateBlocks, block)
    42  		}
    43  	}
    44  }
    45  
    46  func isPrivateIP(ipAddr string) bool {
    47  	ip := net.ParseIP(ipAddr)
    48  	if ip == nil {
    49  		return false
    50  	}
    51  
    52  	for _, blocks := range privateBlocks {
    53  		if blocks.Contains(ip) {
    54  			return true
    55  		}
    56  	}
    57  	return false
    58  }
    59  
    60  func addrToIP(addr net.Addr) net.IP {
    61  	switch v := addr.(type) {
    62  	case *net.IPAddr:
    63  		return v.IP
    64  	case *net.IPNet:
    65  		return v.IP
    66  	default:
    67  		return nil
    68  	}
    69  }
    70  
    71  func localIPs() []string {
    72  	ifaces, err := net.Interfaces()
    73  	if err != nil {
    74  		return nil
    75  	}
    76  
    77  	var ipAddrs []string
    78  
    79  	for _, iface := range ifaces {
    80  		addrs, err := iface.Addrs()
    81  		if err != nil {
    82  			continue // ignore error
    83  		}
    84  
    85  		for _, addr := range addrs {
    86  			if ip := addrToIP(addr); ip != nil {
    87  				ipAddrs = append(ipAddrs, ip.String())
    88  			}
    89  		}
    90  	}
    91  
    92  	return ipAddrs
    93  }
    94  
    95  // IsLocal tells us whether an ip is local
    96  func IsLocal(addr string) bool {
    97  	// extract the host
    98  	host, _, err := net.SplitHostPort(addr)
    99  	if err == nil {
   100  		addr = host
   101  	}
   102  
   103  	// check if its localhost
   104  	if addr == "localhost" {
   105  		return true
   106  	}
   107  
   108  	// check against all local ips
   109  	for _, ip := range localIPs() {
   110  		if addr == ip {
   111  			return true
   112  		}
   113  	}
   114  
   115  	return false
   116  }
   117  
   118  // Extract returns a real ip
   119  func Extract(addr string) (string, error) {
   120  	// if addr specified then its returned
   121  	if len(addr) > 0 {
   122  		if addr != "0.0.0.0" && addr != "[::]" && addr != "::" {
   123  			return addr, nil
   124  		}
   125  	}
   126  
   127  	var privateAddrs []string
   128  	var publicAddrs []string
   129  	var loopbackAddrs []string
   130  
   131  	for _, ipAddr := range localIPs() {
   132  		ip := net.ParseIP(ipAddr)
   133  		if ip == nil {
   134  			continue
   135  		}
   136  
   137  		if ip.IsUnspecified() {
   138  			continue
   139  		}
   140  
   141  		if ip.IsLoopback() {
   142  			loopbackAddrs = append(loopbackAddrs, ipAddr)
   143  		} else if isPrivateIP(ipAddr) {
   144  			privateAddrs = append(privateAddrs, ipAddr)
   145  		} else {
   146  			publicAddrs = append(publicAddrs, ipAddr)
   147  		}
   148  	}
   149  
   150  	if len(privateAddrs) > 0 {
   151  		return privateAddrs[0], nil
   152  	} else if len(publicAddrs) > 0 {
   153  		return publicAddrs[0], nil
   154  	} else if len(loopbackAddrs) > 0 {
   155  		return loopbackAddrs[0], nil
   156  	}
   157  
   158  	return "", fmt.Errorf("No IP address found, and explicit IP not provided")
   159  }
   160  
   161  // IPs returns all known ips
   162  func IPs() []string {
   163  	return localIPs()
   164  }