mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 01:57:12 -05:00
169 lines
3.7 KiB
Go
169 lines
3.7 KiB
Go
// +build json
|
|
|
|
package router
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"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 parseIP(s string) *IP {
|
|
var addr, mask string
|
|
i := strings.Index(s, "/")
|
|
if i < 0 {
|
|
addr = s
|
|
} else {
|
|
addr = s[:i]
|
|
mask = s[i+1:]
|
|
}
|
|
ip := v2net.ParseAddress(addr)
|
|
if !ip.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
|
|
return nil
|
|
}
|
|
bits := uint32(32)
|
|
if len(mask) > 0 {
|
|
bits64, err := strconv.ParseUint(mask, 10, 32)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
bits = uint32(bits64)
|
|
}
|
|
if bits > 32 {
|
|
log.Warning("Router: invalid network mask: ", bits)
|
|
return nil
|
|
}
|
|
return &IP{
|
|
Ip: []byte(ip.IP()),
|
|
UnmatchingBits: 32 - bits,
|
|
}
|
|
}
|
|
|
|
func parseFieldRule(msg json.RawMessage) (*RoutingRule, 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
|
|
}
|
|
|
|
rule := new(RoutingRule)
|
|
rule.Tag = rawFieldRule.OutboundTag
|
|
|
|
if rawFieldRule.Domain != nil {
|
|
for _, domain := range *rawFieldRule.Domain {
|
|
domainRule := new(Domain)
|
|
if strings.HasPrefix(domain, "regexp:") {
|
|
domainRule.Type = Domain_Regex
|
|
domainRule.Value = domain[7:]
|
|
} else {
|
|
domainRule.Type = Domain_Plain
|
|
domainRule.Value = domain
|
|
}
|
|
rule.Domain = append(rule.Domain, domainRule)
|
|
}
|
|
}
|
|
|
|
if rawFieldRule.IP != nil {
|
|
for _, ip := range *rawFieldRule.IP {
|
|
ipRule := parseIP(ip)
|
|
if ipRule != nil {
|
|
rule.Ip = append(rule.Ip, ipRule)
|
|
}
|
|
}
|
|
}
|
|
|
|
if rawFieldRule.Port != nil {
|
|
rule.PortRange = rawFieldRule.Port
|
|
}
|
|
|
|
if rawFieldRule.Network != nil {
|
|
rule.NetworkList = rawFieldRule.Network
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func ParseRule(msg json.RawMessage) *RoutingRule {
|
|
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 (this *Config) UnmarshalJSON(data []byte) error {
|
|
type JsonRulesConfig struct {
|
|
RuleList []json.RawMessage `json:"rules"`
|
|
DomainStrategy string `json:"domainStrategy"`
|
|
}
|
|
type JsonConfig struct {
|
|
Settings *JsonRulesConfig `json:"settings"`
|
|
}
|
|
jsonConfig := new(JsonConfig)
|
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
|
return err
|
|
}
|
|
if jsonConfig.Settings == nil {
|
|
return errors.New("Router settings is not specified.")
|
|
}
|
|
settings := jsonConfig.Settings
|
|
this.DomainStrategy = Config_AsIs
|
|
this.Rule = make([]*RoutingRule, len(settings.RuleList))
|
|
domainStrategy := strings.ToLower(settings.DomainStrategy)
|
|
if domainStrategy == "alwaysip" {
|
|
this.DomainStrategy = Config_UseIp
|
|
} else if domainStrategy == "ipifnonmatch" {
|
|
this.DomainStrategy = Config_IpIfNonMatch
|
|
}
|
|
for idx, rawRule := range settings.RuleList {
|
|
rule := ParseRule(rawRule)
|
|
this.Rule[idx] = rule
|
|
}
|
|
return nil
|
|
}
|