1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-22 10:08:15 -05:00

sub domain matcher

This commit is contained in:
Darien Raymond 2017-05-08 12:18:13 +02:00
parent a0ac334703
commit a0bde091d4
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
6 changed files with 146 additions and 60 deletions

View File

@ -114,6 +114,31 @@ func (v *RegexpDomainMatcher) Apply(ctx context.Context) bool {
return v.pattern.MatchString(strings.ToLower(domain))
}
type SubDomainMatcher struct {
pattern string
}
func NewSubDomainMatcher(p string) *SubDomainMatcher {
return &SubDomainMatcher{
pattern: p,
}
}
func (m *SubDomainMatcher) Apply(ctx context.Context) bool {
dest, ok := proxy.TargetFromContext(ctx)
if !ok {
return false
}
if !dest.Address.Family().IsDomain() {
return false
}
domain := dest.Address.Domain()
if !strings.HasSuffix(domain, m.pattern) {
return false
}
return len(domain) == len(m.pattern) || domain[len(domain)-len(m.pattern)-1] == '.'
}
type CIDRMatcher struct {
cidr *net.IPNet
onSource bool

View File

@ -0,0 +1,46 @@
package router_test
import (
"context"
"testing"
. "v2ray.com/core/app/router"
"v2ray.com/core/common/net"
"v2ray.com/core/proxy"
"v2ray.com/core/testing/assert"
)
func TestSubDomainMatcher(t *testing.T) {
assert := assert.On(t)
cases := []struct {
pattern string
input context.Context
output bool
}{
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com"), 80)),
output: true,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)),
output: true,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v3ray.com"), 80)),
output: false,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("2ray.com"), 80)),
output: false,
},
}
for _, test := range cases {
matcher := NewSubDomainMatcher(test.pattern)
assert.Bool(matcher.Apply(test.input) == test.output).IsTrue()
}
}

View File

@ -22,14 +22,19 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
if len(rr.Domain) > 0 {
anyCond := NewAnyCondition()
for _, domain := range rr.Domain {
if domain.Type == Domain_Plain {
switch domain.Type {
case Domain_Plain:
anyCond.Add(NewPlainDomainMatcher(domain.Value))
} else {
case Domain_Regex:
matcher, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return nil, err
}
anyCond.Add(matcher)
case Domain_Domain:
anyCond.Add(NewSubDomainMatcher(domain.Value))
default:
panic("Unknown domain type.")
}
}
conds.Add(anyCond)

View File

@ -25,15 +25,19 @@ const (
Domain_Plain Domain_Type = 0
// The value is used as a regular expression.
Domain_Regex Domain_Type = 1
// The value is a domain.
Domain_Domain Domain_Type = 2
)
var Domain_Type_name = map[int32]string{
0: "Plain",
1: "Regex",
2: "Domain",
}
var Domain_Type_value = map[string]int32{
"Plain": 0,
"Regex": 1,
"Plain": 0,
"Regex": 1,
"Domain": 2,
}
func (x Domain_Type) String() string {
@ -230,39 +234,39 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/app/router/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 531 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xd1, 0x6e, 0xd3, 0x30,
0x14, 0x86, 0x49, 0x9b, 0x85, 0xe5, 0x64, 0x94, 0xc8, 0x62, 0x28, 0x0c, 0x26, 0xa2, 0x08, 0x41,
0x2f, 0x50, 0x22, 0x15, 0x01, 0x37, 0x20, 0x34, 0xba, 0x5d, 0x54, 0x82, 0x69, 0x32, 0x1b, 0x17,
0xdc, 0x44, 0x5e, 0xea, 0x05, 0x8b, 0xc4, 0xb6, 0x1c, 0x67, 0xac, 0x0f, 0xc1, 0x8b, 0xf0, 0x34,
0x3c, 0x12, 0xb2, 0x9d, 0x89, 0x0d, 0xad, 0x70, 0x77, 0x8e, 0xfb, 0xfd, 0xc7, 0x7f, 0x8f, 0xff,
0xc0, 0xd3, 0xf3, 0x99, 0x22, 0xab, 0xbc, 0x12, 0x6d, 0x51, 0x09, 0x45, 0x0b, 0x22, 0x65, 0xa1,
0x44, 0xaf, 0xa9, 0x2a, 0x2a, 0xc1, 0xcf, 0x58, 0x9d, 0x4b, 0x25, 0xb4, 0x40, 0xdb, 0x97, 0x9c,
0xa2, 0x39, 0x91, 0x32, 0x77, 0xcc, 0xce, 0x93, 0xbf, 0xe4, 0x95, 0x68, 0x5b, 0xc1, 0x0b, 0x4e,
0x75, 0x21, 0x85, 0xd2, 0x4e, 0xbc, 0xf3, 0x6c, 0x3d, 0xc5, 0xa9, 0xfe, 0x2e, 0xd4, 0x37, 0x07,
0x66, 0x1a, 0x82, 0x7d, 0xd1, 0x12, 0xc6, 0xd1, 0x2b, 0xf0, 0xf5, 0x4a, 0xd2, 0xc4, 0x4b, 0xbd,
0xe9, 0x64, 0x96, 0xe5, 0x37, 0x5e, 0x9f, 0x3b, 0x38, 0x3f, 0x5e, 0x49, 0x8a, 0x2d, 0x8f, 0xee,
0xc1, 0xc6, 0x39, 0x69, 0x7a, 0x9a, 0x8c, 0x52, 0x6f, 0x1a, 0x62, 0xd7, 0x64, 0x8f, 0xc0, 0x37,
0x0c, 0x0a, 0x61, 0xe3, 0xa8, 0x21, 0x8c, 0xc7, 0xb7, 0x4c, 0x89, 0x69, 0x4d, 0x2f, 0x62, 0x2f,
0xcb, 0xc1, 0x9f, 0x2f, 0xf6, 0x31, 0x9a, 0xc0, 0x88, 0x49, 0x7b, 0xe3, 0x16, 0x1e, 0x31, 0x89,
0xee, 0x43, 0x20, 0x15, 0x3d, 0x63, 0x17, 0x76, 0xd8, 0x1d, 0x3c, 0x74, 0xd9, 0x8f, 0x31, 0x44,
0x58, 0xf4, 0x9a, 0xf1, 0x1a, 0xf7, 0x0d, 0x45, 0x31, 0x8c, 0x35, 0xa9, 0xad, 0x30, 0xc4, 0xa6,
0x44, 0x2f, 0x21, 0x58, 0x5a, 0x6b, 0xc9, 0x28, 0x1d, 0x4f, 0xa3, 0xd9, 0xee, 0x3f, 0xfd, 0xe3,
0x01, 0x46, 0x05, 0xf8, 0x15, 0x5b, 0xaa, 0x64, 0x6c, 0x45, 0x0f, 0xd7, 0x88, 0x8c, 0x57, 0x6c,
0x41, 0xf4, 0x0e, 0xc0, 0xac, 0xb9, 0x54, 0x84, 0xd7, 0x34, 0xf1, 0x53, 0x6f, 0x1a, 0xcd, 0xd2,
0xab, 0x32, 0xb7, 0xe9, 0x9c, 0x53, 0x9d, 0x1f, 0x09, 0xa5, 0xb1, 0xe1, 0x70, 0x28, 0x2f, 0x4b,
0x74, 0x00, 0x5b, 0xc3, 0x0b, 0x94, 0x0d, 0xeb, 0x74, 0xb2, 0x61, 0x47, 0x64, 0x6b, 0x46, 0x1c,
0x3a, 0xf4, 0x03, 0xeb, 0x34, 0x8e, 0xf8, 0x9f, 0x06, 0xbd, 0x81, 0xa8, 0x13, 0xbd, 0xaa, 0x68,
0x69, 0xfd, 0x07, 0xff, 0xf7, 0x0f, 0x8e, 0x9f, 0x9b, 0x7f, 0xb1, 0x0b, 0xd0, 0x77, 0x54, 0x95,
0xb4, 0x25, 0xac, 0x49, 0x6e, 0xa7, 0xe3, 0x69, 0x88, 0x43, 0x73, 0x72, 0x60, 0x0e, 0xd0, 0x63,
0x88, 0x18, 0x3f, 0x15, 0x3d, 0x5f, 0x96, 0x66, 0xcd, 0x9b, 0xf6, 0x77, 0x18, 0x8e, 0x8e, 0x49,
0x9d, 0xfd, 0xf2, 0x20, 0x98, 0xdb, 0xb0, 0xa2, 0x13, 0xb8, 0xeb, 0x76, 0x59, 0x76, 0x5a, 0x11,
0x4d, 0xeb, 0xd5, 0x90, 0xa0, 0xe7, 0xeb, 0xcc, 0xb8, 0x90, 0xbb, 0x87, 0xf8, 0x34, 0x68, 0xf0,
0x64, 0x79, 0xad, 0x37, 0x69, 0x54, 0x7d, 0x43, 0x87, 0xd7, 0x5c, 0x97, 0xc6, 0x2b, 0x99, 0xc0,
0x96, 0xcf, 0x5e, 0xc3, 0xe4, 0xfa, 0x64, 0xb4, 0x09, 0xfe, 0x5e, 0xb7, 0xe8, 0x5c, 0x00, 0x4f,
0x3a, 0xba, 0x90, 0xb1, 0x87, 0x62, 0xd8, 0x5a, 0xc8, 0xc5, 0xd9, 0xa1, 0xe0, 0x1f, 0x89, 0xae,
0xbe, 0xc6, 0xa3, 0xf7, 0x6f, 0xe1, 0x41, 0x25, 0xda, 0x9b, 0xef, 0x39, 0xf2, 0xbe, 0x04, 0xae,
0xfa, 0x39, 0xda, 0xfe, 0x3c, 0xc3, 0x64, 0x95, 0xcf, 0x0d, 0xb1, 0x27, 0xa5, 0xb5, 0x40, 0xd5,
0x69, 0x60, 0x3f, 0xa7, 0x17, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x22, 0xdd, 0x6c, 0xde,
0x03, 0x00, 0x00,
// 538 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xc1, 0x6e, 0xd4, 0x30,
0x10, 0x86, 0x49, 0x76, 0x1b, 0xba, 0x93, 0xb2, 0x44, 0x16, 0x45, 0xa1, 0xa8, 0x22, 0x8a, 0x10,
0xe4, 0x80, 0x12, 0x69, 0x11, 0x70, 0x01, 0xa1, 0xb2, 0xed, 0x61, 0x25, 0xa8, 0x2a, 0xd3, 0x72,
0xe0, 0x12, 0xb9, 0x59, 0x37, 0x58, 0x24, 0xb6, 0xe5, 0x38, 0xa5, 0x7b, 0xe3, 0x05, 0x78, 0x11,
0x9e, 0x86, 0x47, 0x42, 0xb6, 0x53, 0xd1, 0xa2, 0x2e, 0xdc, 0x66, 0x9c, 0xef, 0x9f, 0x19, 0x8f,
0xff, 0xc0, 0x93, 0xf3, 0x99, 0x22, 0xab, 0xbc, 0x12, 0x6d, 0x51, 0x09, 0x45, 0x0b, 0x22, 0x65,
0xa1, 0x44, 0xaf, 0xa9, 0x2a, 0x2a, 0xc1, 0xcf, 0x58, 0x9d, 0x4b, 0x25, 0xb4, 0x40, 0xdb, 0x97,
0x9c, 0xa2, 0x39, 0x91, 0x32, 0x77, 0xcc, 0xce, 0xe3, 0xbf, 0xe4, 0x95, 0x68, 0x5b, 0xc1, 0x0b,
0x4e, 0x75, 0x21, 0x85, 0xd2, 0x4e, 0xbc, 0xf3, 0x74, 0x3d, 0xc5, 0xa9, 0xfe, 0x26, 0xd4, 0x57,
0x07, 0xa6, 0xdf, 0x3d, 0x08, 0xf6, 0x45, 0x4b, 0x18, 0x47, 0x2f, 0x61, 0xac, 0x57, 0x92, 0xc6,
0x5e, 0xe2, 0x65, 0xd3, 0x59, 0x9a, 0xdf, 0xd8, 0x3f, 0x77, 0x70, 0x7e, 0xbc, 0x92, 0x14, 0x5b,
0x1e, 0xdd, 0x83, 0x8d, 0x73, 0xd2, 0xf4, 0x34, 0xf6, 0x13, 0x2f, 0x9b, 0x60, 0x97, 0xa4, 0x19,
0x8c, 0x0d, 0x83, 0x26, 0xb0, 0x71, 0xd4, 0x10, 0xc6, 0xa3, 0x5b, 0x26, 0xc4, 0xb4, 0xa6, 0x17,
0x91, 0x87, 0xe0, 0xb2, 0x6b, 0xe4, 0xa7, 0x39, 0x8c, 0xe7, 0x8b, 0x7d, 0x8c, 0xa6, 0xe0, 0x33,
0x69, 0xbb, 0x6f, 0x61, 0x9f, 0x49, 0x74, 0x1f, 0x02, 0xa9, 0xe8, 0x19, 0xbb, 0xb0, 0x85, 0xef,
0xe0, 0x21, 0x4b, 0x7f, 0x8c, 0x20, 0xc4, 0xa2, 0xd7, 0x8c, 0xd7, 0xb8, 0x6f, 0x28, 0x8a, 0x60,
0xa4, 0x49, 0x6d, 0x85, 0x13, 0x6c, 0x42, 0xf4, 0x02, 0x82, 0xa5, 0xad, 0x1e, 0xfb, 0xc9, 0x28,
0x0b, 0x67, 0xbb, 0xff, 0xbc, 0x0b, 0x1e, 0x60, 0x54, 0xc0, 0xb8, 0x62, 0x4b, 0x15, 0x8f, 0xac,
0xe8, 0xe1, 0x1a, 0x91, 0x99, 0x15, 0x5b, 0x10, 0xbd, 0x05, 0x30, 0x3b, 0x2f, 0x15, 0xe1, 0x35,
0x8d, 0xc7, 0x89, 0x97, 0x85, 0xb3, 0xe4, 0xaa, 0xcc, 0xad, 0x3d, 0xe7, 0x54, 0xe7, 0x47, 0x42,
0x69, 0x6c, 0x38, 0x3c, 0x91, 0x97, 0x21, 0x3a, 0x80, 0xad, 0xe1, 0x39, 0xca, 0x86, 0x75, 0x3a,
0xde, 0xb0, 0x25, 0xd2, 0x35, 0x25, 0x0e, 0x1d, 0xfa, 0x9e, 0x75, 0x1a, 0x87, 0xfc, 0x4f, 0x82,
0x5e, 0x43, 0xd8, 0x89, 0x5e, 0x55, 0xb4, 0xb4, 0xf3, 0x07, 0xff, 0x9f, 0x1f, 0x1c, 0x3f, 0x37,
0xb7, 0xd8, 0x05, 0xe8, 0x3b, 0xaa, 0x4a, 0xda, 0x12, 0xd6, 0xc4, 0xb7, 0x93, 0x51, 0x36, 0xc1,
0x13, 0x73, 0x72, 0x60, 0x0e, 0xd0, 0x23, 0x08, 0x19, 0x3f, 0x15, 0x3d, 0x5f, 0x96, 0x66, 0xcd,
0x9b, 0xf6, 0x3b, 0x0c, 0x47, 0xc7, 0xa4, 0x4e, 0x7f, 0x79, 0x10, 0xcc, 0xad, 0x73, 0xd1, 0x09,
0xdc, 0x75, 0xbb, 0x2c, 0x3b, 0xad, 0x88, 0xa6, 0xf5, 0x6a, 0x70, 0xd3, 0xb3, 0x75, 0xc3, 0x38,
0xc7, 0xbb, 0x87, 0xf8, 0x38, 0x68, 0xf0, 0x74, 0x79, 0x2d, 0x37, 0xce, 0x54, 0x7d, 0x43, 0x87,
0xd7, 0x5c, 0xe7, 0xcc, 0x2b, 0x9e, 0xc0, 0x96, 0x4f, 0x5f, 0xc1, 0xf4, 0x7a, 0x65, 0xb4, 0x09,
0xe3, 0xbd, 0x6e, 0xd1, 0x39, 0x33, 0x9e, 0x74, 0x74, 0x21, 0x23, 0x0f, 0x45, 0xb0, 0xb5, 0x90,
0x8b, 0xb3, 0x43, 0xc1, 0x3f, 0x10, 0x5d, 0x7d, 0x89, 0xfc, 0x77, 0x6f, 0xe0, 0x41, 0x25, 0xda,
0x9b, 0xfb, 0x1c, 0x79, 0x9f, 0x03, 0x17, 0xfd, 0xf4, 0xb7, 0x3f, 0xcd, 0x30, 0x59, 0xe5, 0x73,
0x43, 0xec, 0x49, 0x69, 0x47, 0xa0, 0xea, 0x34, 0xb0, 0xff, 0xd6, 0xf3, 0xdf, 0x01, 0x00, 0x00,
0xff, 0xff, 0xa7, 0x6a, 0x97, 0x93, 0xeb, 0x03, 0x00, 0x00,
}

View File

@ -17,6 +17,8 @@ message Domain {
Plain = 0;
// The value is used as a regular expression.
Regex = 1;
// The value is a domain.
Domain = 2;
}
// Domain matching type.

View File

@ -22,13 +22,13 @@ type RouterConfig struct {
Settings *RouterRulesConfig `json:"settings"`
}
func (v *RouterConfig) Build() (*router.Config, error) {
if v.Settings == nil {
return nil, newError("Config: Router settings is not specified.")
func (c *RouterConfig) Build() (*router.Config, error) {
if c.Settings == nil {
return nil, newError("Router settings is not specified.")
}
config := new(router.Config)
settings := v.Settings
settings := c.Settings
config.DomainStrategy = router.Config_AsIs
config.Rule = make([]*router.RoutingRule, len(settings.RuleList))
domainStrategy := strings.ToLower(settings.DomainStrategy)
@ -68,12 +68,12 @@ func parseIP(s string) (*router.CIDR, error) {
if len(mask) > 0 {
bits64, err := strconv.ParseUint(mask, 10, 32)
if err != nil {
return nil, newError("Config: invalid network mask for router: ", mask).Base(err)
return nil, newError("invalid network mask for router: ", mask).Base(err)
}
bits = uint32(bits64)
}
if bits > 32 {
return nil, newError("Config: invalid network mask for router: ", bits)
return nil, newError("invalid network mask for router: ", bits)
}
return &router.CIDR{
Ip: []byte(ip.IP()),
@ -84,19 +84,19 @@ func parseIP(s string) (*router.CIDR, error) {
if len(mask) > 0 {
bits64, err := strconv.ParseUint(mask, 10, 32)
if err != nil {
return nil, newError("Config: invalid network mask for router: ", mask).Base(err)
return nil, newError("invalid network mask for router: ", mask).Base(err)
}
bits = uint32(bits64)
}
if bits > 128 {
return nil, newError("Config: invalid network mask for router: ", bits)
return nil, newError("invalid network mask for router: ", bits)
}
return &router.CIDR{
Ip: []byte(ip.IP()),
Prefix: bits,
}, nil
default:
return nil, newError("Config: unsupported address for router: ", s)
return nil, newError("unsupported address for router: ", s)
}
}
@ -123,10 +123,14 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
if rawFieldRule.Domain != nil {
for _, domain := range *rawFieldRule.Domain {
domainRule := new(router.Domain)
if strings.HasPrefix(domain, "regexp:") {
switch {
case strings.HasPrefix(domain, "regexp:"):
domainRule.Type = router.Domain_Regex
domainRule.Value = domain[7:]
} else {
case strings.HasPrefix(domain, "domain:"):
domainRule.Type = router.Domain_Domain
domainRule.Value = domain[7:]
default:
domainRule.Type = router.Domain_Plain
domainRule.Value = domain
}
@ -138,7 +142,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
for _, ip := range *rawFieldRule.IP {
ipRule, err := parseIP(ip)
if err != nil {
return nil, newError("Config: invalid IP: ", ip).Base(err)
return nil, newError("invalid IP: ", ip).Base(err)
}
rule.Cidr = append(rule.Cidr, ipRule)
}
@ -156,7 +160,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
for _, ip := range *rawFieldRule.SourceIP {
ipRule, err := parseIP(ip)
if err != nil {
return nil, newError("Config: invalid IP: ", ip).Base(err)
return nil, newError("invalid IP: ", ip).Base(err)
}
rule.SourceCidr = append(rule.SourceCidr, ipRule)
}
@ -181,41 +185,41 @@ func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(msg, rawRule)
if err != nil {
return nil, newError("Config: Invalid router rule.").Base(err)
return nil, newError("invalid router rule").Base(err)
}
if rawRule.Type == "field" {
fieldrule, err := parseFieldRule(msg)
if err != nil {
return nil, newError("Config: Invalid field rule.").Base(err)
return nil, newError("invalid field rule").Base(err)
}
return fieldrule, nil
}
if rawRule.Type == "chinaip" {
chinaiprule, err := parseChinaIPRule(msg)
if err != nil {
return nil, newError("Config: Invalid chinaip rule.").Base(err)
return nil, newError("invalid chinaip rule").Base(err)
}
return chinaiprule, nil
}
if rawRule.Type == "chinasites" {
chinasitesrule, err := parseChinaSitesRule(msg)
if err != nil {
return nil, newError("Config: Invalid chinasites rule.").Base(err)
return nil, newError("invalid chinasites rule").Base(err)
}
return chinasitesrule, nil
}
return nil, newError("Config: Unknown router rule type: ", rawRule.Type)
return nil, newError("unknown router rule type: ", rawRule.Type)
}
func parseChinaIPRule(data []byte) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
return nil, newError("Config: Invalid router rule.").Base(err)
return nil, newError("invalid router rule").Base(err)
}
var chinaIPs geoip.CountryIPRange
if err := proto.Unmarshal(geoip.ChinaIPs, &chinaIPs); err != nil {
return nil, newError("Config: Invalid china ips.").Base(err)
return nil, newError("invalid china ips").Base(err)
}
return &router.RoutingRule{
Tag: rawRule.OutboundTag,
@ -227,7 +231,7 @@ func parseChinaSitesRule(data []byte) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
log.Trace(newError("Router: Invalid router rule: ", err).AtError())
log.Trace(newError("invalid router rule: ", err).AtError())
return nil, err
}
return &router.RoutingRule{