Преглед изворни кода

field domain and ip accepts list of strings

Darien Raymond пре 10 година
родитељ
комит
759efb0cfa

+ 66 - 14
app/router/rules/config/json/fieldrule.go

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

+ 37 - 3
app/router/rules/config/json/fieldrule_test.go

@@ -1,6 +1,7 @@
 package json
 
 import (
+	"encoding/json"
 	"testing"
 
 	v2net "github.com/v2ray/v2ray-core/common/net"
@@ -8,11 +9,31 @@ import (
 	"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) {
 	assert := unit.Assert(t)
 
 	rule := &FieldRule{
-		Domain: "v2ray.com",
+		Domain: NewStringList("v2ray.com"),
 	}
 	dest := v2net.NewTCPDestination(v2net.DomainAddress("www.v2ray.com", 80))
 	assert.Bool(rule.Apply(dest)).IsTrue()
@@ -62,10 +83,23 @@ func TestDomainNotMatching(t *testing.T) {
 
 	rawJson := `{
     "type": "field",
-    "domain": "google.com",
+    "domain": ["google.com", "v2ray.com"],
     "tag": "test"
   }`
 	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()
 }

+ 17 - 71
release/config/vpoint_socks_vmess.json

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