|  | @@ -10,24 +10,73 @@ import (
 | 
											
												
													
														|  |  	v2netjson "github.com/v2ray/v2ray-core/common/net/json"
 |  |  	v2netjson "github.com/v2ray/v2ray-core/common/net/json"
 | 
											
												
													
														|  |  )
 |  |  )
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +type StringList []string
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func NewStringList(str ...string) *StringList {
 | 
											
												
													
														|  | 
 |  | +	list := StringList(str)
 | 
											
												
													
														|  | 
 |  | +	return &list
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func (this *StringList) UnmarshalJSON(data []byte) error {
 | 
											
												
													
														|  | 
 |  | +	var strList []string
 | 
											
												
													
														|  | 
 |  | +	err := json.Unmarshal(data, &strList)
 | 
											
												
													
														|  | 
 |  | +	if err == nil {
 | 
											
												
													
														|  | 
 |  | +		*this = make([]string, len(strList))
 | 
											
												
													
														|  | 
 |  | +		copy(*this, strList)
 | 
											
												
													
														|  | 
 |  | +		return nil
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	var str string
 | 
											
												
													
														|  | 
 |  | +	err = json.Unmarshal(data, &str)
 | 
											
												
													
														|  | 
 |  | +	if err == nil {
 | 
											
												
													
														|  | 
 |  | +		*this = make([]string, 0, 1)
 | 
											
												
													
														|  | 
 |  | +		*this = append(*this, str)
 | 
											
												
													
														|  | 
 |  | +		return nil
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	return errors.New("Failed to unmarshal string list: " + string(data))
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func (this *StringList) Len() int {
 | 
											
												
													
														|  | 
 |  | +	return len([]string(*this))
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  type FieldRule struct {
 |  |  type FieldRule struct {
 | 
											
												
													
														|  |  	Rule
 |  |  	Rule
 | 
											
												
													
														|  | -	Domain  string
 |  | 
 | 
											
												
													
														|  | -	IP      *net.IPNet
 |  | 
 | 
											
												
													
														|  | 
 |  | +	Domain  *StringList
 | 
											
												
													
														|  | 
 |  | +	IP      []*net.IPNet
 | 
											
												
													
														|  |  	Port    v2net.PortRange
 |  |  	Port    v2net.PortRange
 | 
											
												
													
														|  |  	Network v2net.NetworkList
 |  |  	Network v2net.NetworkList
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  func (this *FieldRule) Apply(dest v2net.Destination) bool {
 |  |  func (this *FieldRule) Apply(dest v2net.Destination) bool {
 | 
											
												
													
														|  |  	address := dest.Address()
 |  |  	address := dest.Address()
 | 
											
												
													
														|  | -	if len(this.Domain) > 0 {
 |  | 
 | 
											
												
													
														|  | -		if !address.IsDomain() || !strings.Contains(address.Domain(), this.Domain) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if this.Domain != nil && this.Domain.Len() > 0 {
 | 
											
												
													
														|  | 
 |  | +		if !address.IsDomain() {
 | 
											
												
													
														|  | 
 |  | +			return false
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		foundMatch := false
 | 
											
												
													
														|  | 
 |  | +		for _, domain := range *this.Domain {
 | 
											
												
													
														|  | 
 |  | +			if strings.Contains(address.Domain(), domain) {
 | 
											
												
													
														|  | 
 |  | +				foundMatch = true
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		if !foundMatch {
 | 
											
												
													
														|  |  			return false
 |  |  			return false
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	if this.IP != nil {
 |  | 
 | 
											
												
													
														|  | -		if !(address.IsIPv4() || address.IsIPv6()) || !this.IP.Contains(address.IP()) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if this.IP != nil && len(this.IP) > 0 {
 | 
											
												
													
														|  | 
 |  | +		if !(address.IsIPv4() || address.IsIPv6()) {
 | 
											
												
													
														|  | 
 |  | +			return false
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		foundMatch := false
 | 
											
												
													
														|  | 
 |  | +		for _, ipnet := range this.IP {
 | 
											
												
													
														|  | 
 |  | +			if ipnet.Contains(address.IP()) {
 | 
											
												
													
														|  | 
 |  | +				foundMatch = true
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		if !foundMatch {
 | 
											
												
													
														|  |  			return false
 |  |  			return false
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -51,8 +100,8 @@ func (this *FieldRule) Apply(dest v2net.Destination) bool {
 | 
											
												
													
														|  |  func (this *FieldRule) UnmarshalJSON(data []byte) error {
 |  |  func (this *FieldRule) UnmarshalJSON(data []byte) error {
 | 
											
												
													
														|  |  	type RawFieldRule struct {
 |  |  	type RawFieldRule struct {
 | 
											
												
													
														|  |  		Rule
 |  |  		Rule
 | 
											
												
													
														|  | -		Domain  string                 `json:"domain"`
 |  | 
 | 
											
												
													
														|  | -		IP      string                 `json:"ip"`
 |  | 
 | 
											
												
													
														|  | 
 |  | +		Domain  *StringList            `json:"domain"`
 | 
											
												
													
														|  | 
 |  | +		IP      *StringList            `json:"ip"`
 | 
											
												
													
														|  |  		Port    *v2netjson.PortRange   `json:"port"`
 |  |  		Port    *v2netjson.PortRange   `json:"port"`
 | 
											
												
													
														|  |  		Network *v2netjson.NetworkList `json:"network"`
 |  |  		Network *v2netjson.NetworkList `json:"network"`
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -65,17 +114,20 @@ func (this *FieldRule) UnmarshalJSON(data []byte) error {
 | 
											
												
													
														|  |  	this.OutboundTag = rawFieldRule.OutboundTag
 |  |  	this.OutboundTag = rawFieldRule.OutboundTag
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	hasField := false
 |  |  	hasField := false
 | 
											
												
													
														|  | -	if len(rawFieldRule.Domain) > 0 {
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
 | 
											
												
													
														|  |  		this.Domain = rawFieldRule.Domain
 |  |  		this.Domain = rawFieldRule.Domain
 | 
											
												
													
														|  |  		hasField = true
 |  |  		hasField = true
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	if len(rawFieldRule.IP) > 0 {
 |  | 
 | 
											
												
													
														|  | -		_, ipNet, err := net.ParseCIDR(rawFieldRule.IP)
 |  | 
 | 
											
												
													
														|  | -		if err != nil {
 |  | 
 | 
											
												
													
														|  | -			return errors.New("Invalid IP range in router rule: " + err.Error())
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
 | 
											
												
													
														|  | 
 |  | +		this.IP = make([]*net.IPNet, 0, rawFieldRule.IP.Len())
 | 
											
												
													
														|  | 
 |  | +		for _, ipStr := range *(rawFieldRule.IP) {
 | 
											
												
													
														|  | 
 |  | +			_, ipNet, err := net.ParseCIDR(ipStr)
 | 
											
												
													
														|  | 
 |  | +			if err != nil {
 | 
											
												
													
														|  | 
 |  | +				return errors.New("Invalid IP range in router rule: " + err.Error())
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +			this.IP = append(this.IP, ipNet)
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | -		this.IP = ipNet
 |  | 
 | 
											
												
													
														|  |  		hasField = true
 |  |  		hasField = true
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  	if rawFieldRule.Port != nil {
 |  |  	if rawFieldRule.Port != nil {
 |