mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 10:08:15 -05:00
field domain and ip accepts list of strings
This commit is contained in:
parent
d4dcbbc734
commit
759efb0cfa
@ -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())
|
||||||
|
for _, ipStr := range *(rawFieldRule.IP) {
|
||||||
|
_, ipNet, err := net.ParseCIDR(ipStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Invalid IP range in router rule: " + err.Error())
|
return errors.New("Invalid IP range in router rule: " + err.Error())
|
||||||
}
|
}
|
||||||
this.IP = ipNet
|
this.IP = append(this.IP, ipNet)
|
||||||
|
}
|
||||||
hasField = true
|
hasField = true
|
||||||
}
|
}
|
||||||
if rawFieldRule.Port != nil {
|
if rawFieldRule.Port != nil {
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user