| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- 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
- }
|