1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-27 09:55:22 +00:00

field domain and ip accepts list of strings

This commit is contained in:
Darien Raymond 2015-11-26 11:22:34 +00:00
parent d4dcbbc734
commit 759efb0cfa
3 changed files with 120 additions and 88 deletions

View File

@ -10,24 +10,73 @@ import (
v2netjson "github.com/v2ray/v2ray-core/common/net/json" 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))
}
type FieldRule struct { type FieldRule struct {
Rule Rule
Domain string Domain *StringList
IP *net.IPNet IP []*net.IPNet
Port v2net.PortRange Port v2net.PortRange
Network v2net.NetworkList Network v2net.NetworkList
} }
func (this *FieldRule) Apply(dest v2net.Destination) bool { func (this *FieldRule) Apply(dest v2net.Destination) bool {
address := dest.Address() address := dest.Address()
if len(this.Domain) > 0 { if this.Domain != nil && this.Domain.Len() > 0 {
if !address.IsDomain() || !strings.Contains(address.Domain(), this.Domain) { if !address.IsDomain() {
return false
}
foundMatch := false
for _, domain := range *this.Domain {
if strings.Contains(address.Domain(), domain) {
foundMatch = true
}
}
if !foundMatch {
return false return false
} }
} }
if this.IP != nil { if this.IP != nil && len(this.IP) > 0 {
if !(address.IsIPv4() || address.IsIPv6()) || !this.IP.Contains(address.IP()) { if !(address.IsIPv4() || address.IsIPv6()) {
return false
}
foundMatch := false
for _, ipnet := range this.IP {
if ipnet.Contains(address.IP()) {
foundMatch = true
}
}
if !foundMatch {
return false return false
} }
} }
@ -51,8 +100,8 @@ func (this *FieldRule) Apply(dest v2net.Destination) bool {
func (this *FieldRule) UnmarshalJSON(data []byte) error { func (this *FieldRule) UnmarshalJSON(data []byte) error {
type RawFieldRule struct { type RawFieldRule struct {
Rule Rule
Domain string `json:"domain"` Domain *StringList `json:"domain"`
IP string `json:"ip"` IP *StringList `json:"ip"`
Port *v2netjson.PortRange `json:"port"` Port *v2netjson.PortRange `json:"port"`
Network *v2netjson.NetworkList `json:"network"` Network *v2netjson.NetworkList `json:"network"`
} }
@ -65,17 +114,20 @@ func (this *FieldRule) UnmarshalJSON(data []byte) error {
this.OutboundTag = rawFieldRule.OutboundTag this.OutboundTag = rawFieldRule.OutboundTag
hasField := false hasField := false
if len(rawFieldRule.Domain) > 0 { if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
this.Domain = rawFieldRule.Domain this.Domain = rawFieldRule.Domain
hasField = true hasField = true
} }
if len(rawFieldRule.IP) > 0 { if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
_, ipNet, err := net.ParseCIDR(rawFieldRule.IP) this.IP = make([]*net.IPNet, 0, rawFieldRule.IP.Len())
if err != nil { for _, ipStr := range *(rawFieldRule.IP) {
return errors.New("Invalid IP range in router rule: " + err.Error()) _, 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)
} }
this.IP = ipNet
hasField = true hasField = true
} }
if rawFieldRule.Port != nil { if rawFieldRule.Port != nil {

View File

@ -1,6 +1,7 @@
package json package json
import ( import (
"encoding/json"
"testing" "testing"
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
@ -8,11 +9,31 @@ import (
"github.com/v2ray/v2ray-core/testing/unit" "github.com/v2ray/v2ray-core/testing/unit"
) )
func TestStringListParsingList(t *testing.T) {
assert := unit.Assert(t)
rawJson := `["a", "b", "c", "d"]`
var strList StringList
err := json.Unmarshal([]byte(rawJson), &strList)
assert.Error(err).IsNil()
assert.Int(strList.Len()).Equals(4)
}
func TestStringListParsingString(t *testing.T) {
assert := unit.Assert(t)
rawJson := `"abcd"`
var strList StringList
err := json.Unmarshal([]byte(rawJson), &strList)
assert.Error(err).IsNil()
assert.Int(strList.Len()).Equals(1)
}
func TestDomainMatching(t *testing.T) { func TestDomainMatching(t *testing.T) {
assert := unit.Assert(t) assert := unit.Assert(t)
rule := &FieldRule{ rule := &FieldRule{
Domain: "v2ray.com", Domain: NewStringList("v2ray.com"),
} }
dest := v2net.NewTCPDestination(v2net.DomainAddress("www.v2ray.com", 80)) dest := v2net.NewTCPDestination(v2net.DomainAddress("www.v2ray.com", 80))
assert.Bool(rule.Apply(dest)).IsTrue() assert.Bool(rule.Apply(dest)).IsTrue()
@ -62,10 +83,23 @@ func TestDomainNotMatching(t *testing.T) {
rawJson := `{ rawJson := `{
"type": "field", "type": "field",
"domain": "google.com", "domain": ["google.com", "v2ray.com"],
"tag": "test" "tag": "test"
}` }`
rule := parseRule([]byte(rawJson)) rule := parseRule([]byte(rawJson))
dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}, 79)) dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}, 80))
assert.Bool(rule.Apply(dest)).IsFalse()
}
func TestDomainNotMatchingDomain(t *testing.T) {
assert := unit.Assert(t)
rawJson := `{
"type": "field",
"domain": ["google.com", "v2ray.com"],
"tag": "test"
}`
rule := parseRule([]byte(rawJson))
dest := v2net.NewTCPDestination(v2net.DomainAddress("baidu.com", 80))
assert.Bool(rule.Apply(dest)).IsFalse() assert.Bool(rule.Apply(dest)).IsFalse()
} }

View File

@ -39,77 +39,23 @@
"rules": [ "rules": [
{ {
"type": "field", "type": "field",
"ip": "0.0.0.0/8", "ip": [
"outboundTag": "direct" "0.0.0.0/8",
}, "10.0.0.0/8",
{ "100.64.0.0/10",
"type": "field", "127.0.0.0/8",
"ip": "10.0.0.0/8", "169.254.0.0/16",
"outboundTag": "direct" "172.16.0.0/12",
}, "192.0.0.0/24",
{ "192.0.2.0/24",
"type": "field", "192.168.0.0/16",
"ip": "100.64.0.0/10", "198.18.0.0/15",
"outboundTag": "direct" "198.51.100.0/24",
}, "203.0.113.0/24",
{ "::1/128",
"type": "field", "fc00::/7",
"ip": "127.0.0.0/8", "fe80::/10"
"outboundTag": "direct" ],
},
{
"type": "field",
"ip": "169.254.0.0/16",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "172.16.0.0/12",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.0.0.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.0.2.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.168.0.0/16",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "198.18.0.0/15",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "198.51.100.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "203.0.113.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "::1/128",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "fc00::/7",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "fe80::/10",
"outboundTag": "direct" "outboundTag": "direct"
} }
] ]