mirror of
				https://github.com/TeaOSLab/EdgeCommon.git
				synced 2025-11-04 13:10:24 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			148 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package shared
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"errors"
 | 
						|
	"github.com/iwind/TeaGo/utils/string"
 | 
						|
	"net"
 | 
						|
	"regexp"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// IPRangeType IP Range类型
 | 
						|
type IPRangeType = int
 | 
						|
 | 
						|
const (
 | 
						|
	IPRangeTypeRange    IPRangeType = 1
 | 
						|
	IPRangeTypeCIDR     IPRangeType = 2
 | 
						|
	IPRangeTypeAll      IPRangeType = 3
 | 
						|
	IPRangeTypeWildcard IPRangeType = 4 // 通配符,可以使用*
 | 
						|
)
 | 
						|
 | 
						|
// IPRangeConfig IP Range
 | 
						|
type IPRangeConfig struct {
 | 
						|
	Id string `yaml:"id" json:"id"`
 | 
						|
 | 
						|
	Type IPRangeType `yaml:"type" json:"type"`
 | 
						|
 | 
						|
	Param  string `yaml:"param" json:"param"`
 | 
						|
	CIDR   string `yaml:"cidr" json:"cidr"`
 | 
						|
	IPFrom string `yaml:"ipFrom" json:"ipFrom"`
 | 
						|
	IPTo   string `yaml:"ipTo" json:"ipTo"`
 | 
						|
 | 
						|
	cidr   *net.IPNet
 | 
						|
	ipFrom net.IP
 | 
						|
	ipTo   net.IP
 | 
						|
	reg    *regexp.Regexp
 | 
						|
}
 | 
						|
 | 
						|
// NewIPRangeConfig 获取新对象
 | 
						|
func NewIPRangeConfig() *IPRangeConfig {
 | 
						|
	return &IPRangeConfig{
 | 
						|
		Id: stringutil.Rand(16),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ParseIPRange 从字符串中分析
 | 
						|
func ParseIPRange(s string) (*IPRangeConfig, error) {
 | 
						|
	if len(s) == 0 {
 | 
						|
		return nil, errors.New("invalid ip range")
 | 
						|
	}
 | 
						|
 | 
						|
	ipRange := &IPRangeConfig{}
 | 
						|
 | 
						|
	if s == "*" || s == "all" || s == "ALL" || s == "0.0.0.0" {
 | 
						|
		ipRange.Type = IPRangeTypeAll
 | 
						|
		return ipRange, nil
 | 
						|
	}
 | 
						|
 | 
						|
	if strings.Contains(s, "/") {
 | 
						|
		ipRange.Type = IPRangeTypeCIDR
 | 
						|
		ipRange.CIDR = strings.Replace(s, " ", "", -1)
 | 
						|
	} else if strings.Contains(s, "-") {
 | 
						|
		ipRange.Type = IPRangeTypeRange
 | 
						|
		pieces := strings.SplitN(s, "-", 2)
 | 
						|
		ipRange.IPFrom = strings.TrimSpace(pieces[0])
 | 
						|
		ipRange.IPTo = strings.TrimSpace(pieces[1])
 | 
						|
	} else if strings.Contains(s, ",") {
 | 
						|
		ipRange.Type = IPRangeTypeRange
 | 
						|
		pieces := strings.SplitN(s, ",", 2)
 | 
						|
		ipRange.IPFrom = strings.TrimSpace(pieces[0])
 | 
						|
		ipRange.IPTo = strings.TrimSpace(pieces[1])
 | 
						|
	} else if strings.Contains(s, "*") {
 | 
						|
		ipRange.Type = IPRangeTypeWildcard
 | 
						|
		s = "^" + strings.Replace(regexp.QuoteMeta(s), `\*`, `\d+`, -1) + "$"
 | 
						|
		ipRange.reg = regexp.MustCompile(s)
 | 
						|
	} else {
 | 
						|
		ipRange.Type = IPRangeTypeRange
 | 
						|
		ipRange.IPFrom = s
 | 
						|
		ipRange.IPTo = s
 | 
						|
	}
 | 
						|
 | 
						|
	err := ipRange.Init()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return ipRange, nil
 | 
						|
}
 | 
						|
 | 
						|
// Init 初始化校验
 | 
						|
func (this *IPRangeConfig) Init() error {
 | 
						|
	if this.Type == IPRangeTypeCIDR {
 | 
						|
		if len(this.CIDR) == 0 {
 | 
						|
			return errors.New("cidr should not be empty")
 | 
						|
		}
 | 
						|
 | 
						|
		_, cidr, err := net.ParseCIDR(this.CIDR)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		this.cidr = cidr
 | 
						|
	}
 | 
						|
 | 
						|
	if this.Type == IPRangeTypeRange {
 | 
						|
		this.ipFrom = net.ParseIP(this.IPFrom)
 | 
						|
		this.ipTo = net.ParseIP(this.IPTo)
 | 
						|
 | 
						|
		if this.ipFrom.To4() == nil && this.ipFrom.To16() == nil {
 | 
						|
			return errors.New("from ip should in IPv4 or IPV6 format")
 | 
						|
		}
 | 
						|
 | 
						|
		if this.ipTo.To4() == nil && this.ipTo.To16() == nil {
 | 
						|
			return errors.New("to ip should in IPv4 or IPV6 format")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Contains 是否包含某个IP
 | 
						|
func (this *IPRangeConfig) Contains(ipString string) bool {
 | 
						|
	ip := net.ParseIP(ipString)
 | 
						|
	if ip == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if this.Type == IPRangeTypeCIDR {
 | 
						|
		if this.cidr == nil {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
		return this.cidr.Contains(ip)
 | 
						|
	}
 | 
						|
	if this.Type == IPRangeTypeRange {
 | 
						|
		if this.ipFrom == nil || this.ipTo == nil {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
		return bytes.Compare(ip, this.ipFrom) >= 0 && bytes.Compare(ip, this.ipTo) <= 0
 | 
						|
	}
 | 
						|
	if this.Type == IPRangeTypeWildcard {
 | 
						|
		if this.reg == nil {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
		return this.reg.MatchString(ipString)
 | 
						|
	}
 | 
						|
	if this.Type == IPRangeTypeAll {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 |