| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- // +build json
- package rules
- import (
- "encoding/json"
- "errors"
- "strings"
- router "github.com/v2ray/v2ray-core/app/router"
- "github.com/v2ray/v2ray-core/common/log"
- v2net "github.com/v2ray/v2ray-core/common/net"
- "github.com/v2ray/v2ray-core/common/serial"
- )
- type JsonRule struct {
- Type string `json:"type"`
- OutboundTag string `json:"outboundTag"`
- }
- func parseFieldRule(msg json.RawMessage) (*Rule, error) {
- type RawFieldRule struct {
- JsonRule
- Domain *serial.StringLiteralList `json:"domain"`
- IP *serial.StringLiteralList `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.String(), "regexp:") {
- rawMatcher, err := NewRegexpDomainMatcher(rawDomain.String()[7:])
- if err != nil {
- return nil, err
- }
- matcher = rawMatcher
- } else {
- matcher = NewPlainDomainMatcher(rawDomain.String())
- }
- 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.String())
- 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 := serial.StringLiteral(jsonConfig.DomainStrategy).ToLower()
- if domainStrategy.String() == "alwaysip" {
- config.DomainStrategy = AlwaysUseIP
- } else if domainStrategy.String() == "ipifnonmatch" {
- config.DomainStrategy = UseIPIfNonMatch
- }
- for idx, rawRule := range jsonConfig.RuleList {
- rule := ParseRule(rawRule)
- config.Rules[idx] = rule
- }
- return config, nil
- })
- }
|