mirror of https://github.com/v2ray/v2ray-core
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
// +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"`
|
|
ResolveDomain bool `json:"resolveDomain"`
|
|
}
|
|
jsonConfig := new(JsonConfig)
|
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
|
return nil, err
|
|
}
|
|
config := &RouterRuleConfig{
|
|
Rules: make([]*Rule, len(jsonConfig.RuleList)),
|
|
ResolveDomain: jsonConfig.ResolveDomain,
|
|
}
|
|
for idx, rawRule := range jsonConfig.RuleList {
|
|
rule := ParseRule(rawRule)
|
|
config.Rules[idx] = rule
|
|
}
|
|
return config, nil
|
|
})
|
|
}
|