|
|
@@ -1,166 +0,0 @@
|
|
|
-package json
|
|
|
-
|
|
|
-import (
|
|
|
- "encoding/json"
|
|
|
- "errors"
|
|
|
- "net"
|
|
|
- "regexp"
|
|
|
- "strings"
|
|
|
-
|
|
|
- v2net "github.com/v2ray/v2ray-core/common/net"
|
|
|
- "github.com/v2ray/v2ray-core/common/serial"
|
|
|
-)
|
|
|
-
|
|
|
-type DomainMatcher interface {
|
|
|
- Match(domain string) bool
|
|
|
-}
|
|
|
-
|
|
|
-type PlainDomainMatcher struct {
|
|
|
- pattern string
|
|
|
-}
|
|
|
-
|
|
|
-func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
|
|
|
- return &PlainDomainMatcher{
|
|
|
- pattern: strings.ToLower(pattern),
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (this *PlainDomainMatcher) Match(domain string) bool {
|
|
|
- return strings.Contains(strings.ToLower(domain), this.pattern)
|
|
|
-}
|
|
|
-
|
|
|
-type RegexpDomainMatcher struct {
|
|
|
- pattern *regexp.Regexp
|
|
|
-}
|
|
|
-
|
|
|
-func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
|
|
|
- r, err := regexp.Compile(pattern)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return &RegexpDomainMatcher{
|
|
|
- pattern: r,
|
|
|
- }, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (this *RegexpDomainMatcher) Match(domain string) bool {
|
|
|
- return this.pattern.MatchString(strings.ToLower(domain))
|
|
|
-}
|
|
|
-
|
|
|
-type FieldRule struct {
|
|
|
- Rule
|
|
|
- Domain []DomainMatcher
|
|
|
- IP []*net.IPNet
|
|
|
- Port *v2net.PortRange
|
|
|
- Network *v2net.NetworkList
|
|
|
-}
|
|
|
-
|
|
|
-func (this *FieldRule) Apply(dest v2net.Destination) bool {
|
|
|
- address := dest.Address()
|
|
|
- if len(this.Domain) > 0 {
|
|
|
- if !address.IsDomain() {
|
|
|
- return false
|
|
|
- }
|
|
|
- foundMatch := false
|
|
|
- for _, domain := range this.Domain {
|
|
|
- if domain.Match(address.Domain()) {
|
|
|
- foundMatch = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !foundMatch {
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !foundMatch {
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if this.Port != nil {
|
|
|
- port := dest.Port()
|
|
|
- if port.Value() < this.Port.From.Value() || port.Value() > this.Port.To.Value() {
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if this.Network != nil {
|
|
|
- if !this.Network.HasNetwork(v2net.Network(dest.Network())) {
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-func (this *FieldRule) UnmarshalJSON(data []byte) error {
|
|
|
- type RawFieldRule struct {
|
|
|
- Rule
|
|
|
- Domain *serial.StringLiteralList `json:"domain"`
|
|
|
- IP *serial.StringLiteralList `json:"ip"`
|
|
|
- Port *v2net.PortRange `json:"port"`
|
|
|
- Network *v2net.NetworkList `json:"network"`
|
|
|
- }
|
|
|
- rawFieldRule := RawFieldRule{}
|
|
|
- err := json.Unmarshal(data, &rawFieldRule)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- this.Type = rawFieldRule.Type
|
|
|
- this.OutboundTag = rawFieldRule.OutboundTag
|
|
|
-
|
|
|
- hasField := false
|
|
|
- if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
|
|
|
- this.Domain = make([]DomainMatcher, rawFieldRule.Domain.Len())
|
|
|
- for idx, rawDomain := range *(rawFieldRule.Domain) {
|
|
|
- var matcher DomainMatcher
|
|
|
- if strings.HasPrefix(rawDomain.String(), "regexp:") {
|
|
|
- rawMatcher, err := NewRegexpDomainMatcher(rawDomain.String()[7:])
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- matcher = rawMatcher
|
|
|
- } else {
|
|
|
- matcher = NewPlainDomainMatcher(rawDomain.String())
|
|
|
- }
|
|
|
- this.Domain[idx] = matcher
|
|
|
- }
|
|
|
- hasField = true
|
|
|
- }
|
|
|
-
|
|
|
- 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.String())
|
|
|
- if err != nil {
|
|
|
- return errors.New("Invalid IP range in router rule: " + err.Error())
|
|
|
- }
|
|
|
- this.IP = append(this.IP, ipNet)
|
|
|
- }
|
|
|
- hasField = true
|
|
|
- }
|
|
|
- if rawFieldRule.Port != nil {
|
|
|
- this.Port = rawFieldRule.Port
|
|
|
- hasField = true
|
|
|
- }
|
|
|
- if rawFieldRule.Network != nil {
|
|
|
- this.Network = rawFieldRule.Network
|
|
|
- hasField = true
|
|
|
- }
|
|
|
- if !hasField {
|
|
|
- return errors.New("This rule has no effective fields.")
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|