github.com/TeaOSLab/EdgeNode@v1.3.8/internal/waf/values/ip_range.go (about)

     1  // Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package values
     4  
     5  import (
     6  	"bytes"
     7  	"net"
     8  	"strings"
     9  )
    10  
    11  type IPRangeType = string
    12  
    13  const (
    14  	IPRangeTypeCIDR    IPRangeType = "cidr"     // CIDR
    15  	IPRangeTypeSingeIP IPRangeType = "singleIP" // 单个IP
    16  	IPRangeTypeRange   IPRangeType = "range"    // IP范围,IP1-IP2
    17  )
    18  
    19  type IPRange struct {
    20  	Type   IPRangeType
    21  	CIDR   *net.IPNet
    22  	IPFrom net.IP
    23  	IPTo   net.IP
    24  }
    25  
    26  func (this *IPRange) Contains(netIP net.IP) bool {
    27  	if netIP == nil {
    28  		return false
    29  	}
    30  	switch this.Type {
    31  	case IPRangeTypeCIDR:
    32  		if this.CIDR != nil {
    33  			return this.CIDR.Contains(netIP)
    34  		}
    35  	case IPRangeTypeSingeIP:
    36  		if this.IPFrom != nil {
    37  			return this.IPFrom.Equal(netIP)
    38  		}
    39  	case IPRangeTypeRange:
    40  		return bytes.Compare(this.IPFrom, netIP) <= 0 && bytes.Compare(this.IPTo, netIP) >= 0
    41  	}
    42  	return false
    43  }
    44  
    45  type IPRangeList struct {
    46  	Ranges []*IPRange
    47  }
    48  
    49  func NewIPRangeList() *IPRangeList {
    50  	return &IPRangeList{}
    51  }
    52  
    53  func ParseIPRangeList(value string) *IPRangeList {
    54  	var list = NewIPRangeList()
    55  
    56  	if len(value) == 0 {
    57  		return list
    58  	}
    59  
    60  	var lines = strings.Split(value, "\n")
    61  	for _, line := range lines {
    62  		line = strings.TrimSpace(line)
    63  		if len(line) == 0 {
    64  			continue
    65  		}
    66  
    67  		if strings.Contains(line, ",") { // IPFrom,IPTo
    68  			var pieces = strings.SplitN(line, ",", 2)
    69  			if len(pieces) == 2 {
    70  				var ipFromString = strings.TrimSpace(pieces[0])
    71  				if len(ipFromString) == 0 {
    72  					ipFromString = "0.0.0.0"
    73  				}
    74  				var ipFrom = net.ParseIP(ipFromString)
    75  				var ipTo = net.ParseIP(strings.TrimSpace(pieces[1]))
    76  				if ipFrom != nil && ipTo != nil {
    77  					if bytes.Compare(ipFrom, ipTo) > 0 {
    78  						ipFrom, ipTo = ipTo, ipFrom
    79  					}
    80  					list.Ranges = append(list.Ranges, &IPRange{
    81  						Type:   IPRangeTypeRange,
    82  						IPFrom: ipFrom,
    83  						IPTo:   ipTo,
    84  					})
    85  				}
    86  			}
    87  		} else if strings.Contains(line, "-") { // IPFrom-IPTo
    88  			var pieces = strings.SplitN(line, "-", 2)
    89  			if len(pieces) == 2 {
    90  				var ipFrom = net.ParseIP(strings.TrimSpace(pieces[0]))
    91  				var ipTo = net.ParseIP(strings.TrimSpace(pieces[1]))
    92  				if ipFrom != nil && ipTo != nil {
    93  					if bytes.Compare(ipFrom, ipTo) > 0 {
    94  						ipFrom, ipTo = ipTo, ipFrom
    95  					}
    96  					list.Ranges = append(list.Ranges, &IPRange{
    97  						Type:   IPRangeTypeRange,
    98  						IPFrom: ipFrom,
    99  						IPTo:   ipTo,
   100  					})
   101  				}
   102  			}
   103  		} else if strings.Contains(line, "/") { // CIDR
   104  			_, cidr, _ := net.ParseCIDR(line)
   105  			if cidr != nil {
   106  				list.Ranges = append(list.Ranges, &IPRange{
   107  					Type: IPRangeTypeCIDR,
   108  					CIDR: cidr,
   109  				})
   110  			}
   111  		} else { // single ip
   112  			var netIP = net.ParseIP(line)
   113  			if netIP != nil {
   114  				list.Ranges = append(list.Ranges, &IPRange{
   115  					Type:   IPRangeTypeSingeIP,
   116  					IPFrom: netIP,
   117  				})
   118  			}
   119  		}
   120  	}
   121  
   122  	return list
   123  }
   124  
   125  func (this *IPRangeList) Contains(ip string) bool {
   126  	var netIP = net.ParseIP(ip)
   127  	if netIP == nil {
   128  		return false
   129  	}
   130  	for _, r := range this.Ranges {
   131  		if r.Contains(netIP) {
   132  			return true
   133  		}
   134  	}
   135  	return false
   136  }