1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-19 19:06:43 -05:00
v2fly/app/router/rules/json/fieldrule.go

198 lines
4.2 KiB
Go
Raw Normal View History

2015-11-21 15:43:40 -05:00
package json
import (
"encoding/json"
"errors"
"net"
2015-12-07 05:58:43 -05:00
"regexp"
2015-11-21 15:43:40 -05:00
"strings"
v2net "github.com/v2ray/v2ray-core/common/net"
v2netjson "github.com/v2ray/v2ray-core/common/net/json"
)
type StringList []string
func NewStringList(str ...string) *StringList {
list := StringList(str)
return &list
}
func (this *StringList) UnmarshalJSON(data []byte) error {
var strList []string
err := json.Unmarshal(data, &strList)
if err == nil {
*this = make([]string, len(strList))
copy(*this, strList)
return nil
}
var str string
err = json.Unmarshal(data, &str)
if err == nil {
*this = make([]string, 0, 1)
*this = append(*this, str)
return nil
}
return errors.New("Failed to unmarshal string list: " + string(data))
}
func (this *StringList) Len() int {
return len([]string(*this))
}
2015-12-07 05:58:43 -05:00
type DomainMatcher interface {
Match(domain string) bool
}
type PlainDomainMatcher struct {
pattern string
}
2015-12-07 06:10:27 -05:00
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
return &PlainDomainMatcher{
pattern: strings.ToLower(pattern),
}
}
2015-12-07 05:58:43 -05:00
func (this *PlainDomainMatcher) Match(domain string) bool {
2015-12-12 11:15:29 -05:00
return strings.Contains(strings.ToLower(domain), this.pattern)
2015-12-07 05:58:43 -05:00
}
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 {
2015-12-07 06:10:27 -05:00
return this.pattern.MatchString(strings.ToLower(domain))
2015-12-07 05:58:43 -05:00
}
2015-11-21 15:43:40 -05:00
type FieldRule struct {
Rule
2015-12-07 05:58:43 -05:00
Domain []DomainMatcher
IP []*net.IPNet
2015-11-21 15:43:40 -05:00
Port v2net.PortRange
Network v2net.NetworkList
}
func (this *FieldRule) Apply(dest v2net.Destination) bool {
address := dest.Address()
2015-12-07 05:58:43 -05:00
if len(this.Domain) > 0 {
if !address.IsDomain() {
return false
}
foundMatch := false
2015-12-07 05:58:43 -05:00
for _, domain := range this.Domain {
if domain.Match(address.Domain()) {
foundMatch = true
2015-11-30 07:46:09 -05:00
break
}
}
if !foundMatch {
2015-11-21 15:43:40 -05:00
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
2015-11-30 07:46:09 -05:00
break
}
}
if !foundMatch {
2015-11-21 15:43:40 -05:00
return false
}
}
if this.Port != nil {
port := address.Port()
2015-12-02 06:47:54 -05:00
if port.Value() < this.Port.From().Value() || port.Value() > this.Port.To().Value() {
2015-11-21 15:43:40 -05:00
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 *StringList `json:"domain"`
IP *StringList `json:"ip"`
2015-11-22 16:14:27 -05:00
Port *v2netjson.PortRange `json:"port"`
Network *v2netjson.NetworkList `json:"network"`
2015-11-21 15:43:40 -05:00
}
rawFieldRule := RawFieldRule{}
err := json.Unmarshal(data, &rawFieldRule)
if err != nil {
return err
}
this.Type = rawFieldRule.Type
this.OutboundTag = rawFieldRule.OutboundTag
2015-11-22 16:14:27 -05:00
hasField := false
if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
2015-12-07 05:58:43 -05:00
this.Domain = make([]DomainMatcher, rawFieldRule.Domain.Len())
for idx, rawDomain := range *(rawFieldRule.Domain) {
var matcher DomainMatcher
if strings.HasPrefix(rawDomain, "regexp:") {
rawMatcher, err := NewRegexpDomainMatcher(rawDomain[7:])
if err != nil {
return err
}
matcher = rawMatcher
} else {
2015-12-07 06:10:27 -05:00
matcher = NewPlainDomainMatcher(rawDomain)
2015-12-07 05:58:43 -05:00
}
this.Domain[idx] = matcher
}
2015-11-22 16:14:27 -05:00
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)
if err != nil {
return errors.New("Invalid IP range in router rule: " + err.Error())
}
this.IP = append(this.IP, ipNet)
2015-11-22 16:14:27 -05:00
}
hasField = true
2015-11-21 15:43:40 -05:00
}
if rawFieldRule.Port != nil {
this.Port = rawFieldRule.Port
2015-11-22 16:14:27 -05:00
hasField = true
2015-11-21 15:43:40 -05:00
}
if rawFieldRule.Network != nil {
this.Network = rawFieldRule.Network
2015-11-22 16:14:27 -05:00
hasField = true
}
if !hasField {
return errors.New("This rule has no effective fields.")
2015-11-21 15:43:40 -05:00
}
return nil
}