| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 | 
							- // +build json
 
- package rules
 
- import (
 
- 	"encoding/json"
 
- 	"errors"
 
- 	"strings"
 
- 	router "v2ray.com/core/app/router"
 
- 	"v2ray.com/core/common/collect"
 
- 	"v2ray.com/core/common/log"
 
- 	v2net "v2ray.com/core/common/net"
 
- )
 
- type JsonRule struct {
 
- 	Type        string `json:"type"`
 
- 	OutboundTag string `json:"outboundTag"`
 
- }
 
- func parseFieldRule(msg json.RawMessage) (*Rule, error) {
 
- 	type RawFieldRule struct {
 
- 		JsonRule
 
- 		Domain  *collect.StringList `json:"domain"`
 
- 		IP      *collect.StringList `json:"ip"`
 
- 		Port    *v2net.PortRange    `json:"port"`
 
- 		Network *v2net.NetworkList  `json:"network"`
 
- 	}
 
- 	rawFieldRule := new(RawFieldRule)
 
- 	err := json.Unmarshal(msg, rawFieldRule)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	conds := NewConditionChan()
 
- 	if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
 
- 		anyCond := NewAnyCondition()
 
- 		for _, rawDomain := range *(rawFieldRule.Domain) {
 
- 			var matcher Condition
 
- 			if strings.HasPrefix(rawDomain, "regexp:") {
 
- 				rawMatcher, err := NewRegexpDomainMatcher(rawDomain[7:])
 
- 				if err != nil {
 
- 					return nil, err
 
- 				}
 
- 				matcher = rawMatcher
 
- 			} else {
 
- 				matcher = NewPlainDomainMatcher(rawDomain)
 
- 			}
 
- 			anyCond.Add(matcher)
 
- 		}
 
- 		conds.Add(anyCond)
 
- 	}
 
- 	if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
 
- 		anyCond := NewAnyCondition()
 
- 		for _, ipStr := range *(rawFieldRule.IP) {
 
- 			cidrMatcher, err := NewCIDRMatcher(ipStr)
 
- 			if err != nil {
 
- 				log.Error("Router: Invalid IP range in router rule: ", err)
 
- 				return nil, err
 
- 			}
 
- 			anyCond.Add(cidrMatcher)
 
- 		}
 
- 		conds.Add(anyCond)
 
- 	}
 
- 	if rawFieldRule.Port != nil {
 
- 		conds.Add(NewPortMatcher(*rawFieldRule.Port))
 
- 	}
 
- 	if rawFieldRule.Network != nil {
 
- 		conds.Add(NewNetworkMatcher(rawFieldRule.Network))
 
- 	}
 
- 	if conds.Len() == 0 {
 
- 		return nil, errors.New("Router: This rule has no effective fields.")
 
- 	}
 
- 	return &Rule{
 
- 		Tag:       rawFieldRule.OutboundTag,
 
- 		Condition: conds,
 
- 	}, nil
 
- }
 
- func ParseRule(msg json.RawMessage) *Rule {
 
- 	rawRule := new(JsonRule)
 
- 	err := json.Unmarshal(msg, rawRule)
 
- 	if err != nil {
 
- 		log.Error("Router: Invalid router rule: ", err)
 
- 		return nil
 
- 	}
 
- 	if rawRule.Type == "field" {
 
- 		fieldrule, err := parseFieldRule(msg)
 
- 		if err != nil {
 
- 			log.Error("Invalid field rule: ", err)
 
- 			return nil
 
- 		}
 
- 		return fieldrule
 
- 	}
 
- 	if rawRule.Type == "chinaip" {
 
- 		chinaiprule, err := parseChinaIPRule(msg)
 
- 		if err != nil {
 
- 			log.Error("Router: Invalid chinaip rule: ", err)
 
- 			return nil
 
- 		}
 
- 		return chinaiprule
 
- 	}
 
- 	if rawRule.Type == "chinasites" {
 
- 		chinasitesrule, err := parseChinaSitesRule(msg)
 
- 		if err != nil {
 
- 			log.Error("Invalid chinasites rule: ", err)
 
- 			return nil
 
- 		}
 
- 		return chinasitesrule
 
- 	}
 
- 	log.Error("Unknown router rule type: ", rawRule.Type)
 
- 	return nil
 
- }
 
- func init() {
 
- 	router.RegisterRouterConfig("rules", func(data []byte) (interface{}, error) {
 
- 		type JsonConfig struct {
 
- 			RuleList       []json.RawMessage `json:"rules"`
 
- 			DomainStrategy string            `json:"domainStrategy"`
 
- 		}
 
- 		jsonConfig := new(JsonConfig)
 
- 		if err := json.Unmarshal(data, jsonConfig); err != nil {
 
- 			return nil, err
 
- 		}
 
- 		config := &RouterRuleConfig{
 
- 			Rules:          make([]*Rule, len(jsonConfig.RuleList)),
 
- 			DomainStrategy: DomainAsIs,
 
- 		}
 
- 		domainStrategy := strings.ToLower(jsonConfig.DomainStrategy)
 
- 		if domainStrategy == "alwaysip" {
 
- 			config.DomainStrategy = AlwaysUseIP
 
- 		} else if domainStrategy == "ipifnonmatch" {
 
- 			config.DomainStrategy = UseIPIfNonMatch
 
- 		}
 
- 		for idx, rawRule := range jsonConfig.RuleList {
 
- 			rule := ParseRule(rawRule)
 
- 			config.Rules[idx] = rule
 
- 		}
 
- 		return config, nil
 
- 	})
 
- }
 
 
  |