1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-28 23:06:14 -04:00

Merge branch 'raymaster' into flymaster

This commit is contained in:
vcptr 2019-11-25 15:29:35 +08:00
commit ca0ca362d3
12 changed files with 501 additions and 69 deletions

View File

@ -4,6 +4,7 @@ import (
fmt "fmt" fmt "fmt"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
math "math" math "math"
router "v2ray.com/core/app/router"
net "v2ray.com/core/common/net" net "v2ray.com/core/common/net"
) )
@ -52,6 +53,7 @@ func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
type NameServer struct { type NameServer struct {
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -96,6 +98,13 @@ func (m *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
return nil return nil
} }
func (m *NameServer) GetGeoip() []*router.GeoIP {
if m != nil {
return m.Geoip
}
return nil
}
type NameServer_PriorityDomain struct { type NameServer_PriorityDomain struct {
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=v2ray.core.app.dns.DomainMatchingType" json:"type,omitempty"` Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=v2ray.core.app.dns.DomainMatchingType" json:"type,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
@ -310,40 +319,42 @@ func init() {
} }
var fileDescriptor_ed5695198e3def8f = []byte{ var fileDescriptor_ed5695198e3def8f = []byte{
// 552 bytes of a gzipped FileDescriptorProto // 583 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0xd1, 0x6e, 0xd3, 0x30, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xdf, 0x6e, 0xd3, 0x3e,
0x14, 0x25, 0x49, 0xdb, 0xad, 0x37, 0x5d, 0x55, 0xfc, 0x30, 0x45, 0x45, 0x82, 0x32, 0xb4, 0x51, 0x18, 0xfd, 0x25, 0xfd, 0xb3, 0xf5, 0xcb, 0x56, 0xf5, 0xe7, 0x8b, 0x29, 0x2a, 0x08, 0xc6, 0xd0,
0x81, 0x70, 0xa4, 0x80, 0x04, 0xec, 0x65, 0x62, 0x5b, 0x11, 0x15, 0x1a, 0x54, 0x1e, 0xe2, 0x01, 0x46, 0x05, 0xc2, 0x91, 0x02, 0x12, 0xb0, 0x9b, 0x89, 0x6d, 0x05, 0x2a, 0x34, 0xa8, 0x3c, 0xc4,
0x90, 0x2a, 0x2f, 0x31, 0x9d, 0x45, 0x63, 0x5b, 0x8e, 0x5b, 0x16, 0x7e, 0x81, 0x1f, 0xe0, 0x1b, 0x05, 0x20, 0x55, 0x5e, 0x62, 0x32, 0x8b, 0xc6, 0xb6, 0x1c, 0x77, 0x2c, 0x3c, 0x09, 0xcf, 0xc0,
0xf8, 0x0d, 0x7e, 0x0c, 0xd5, 0xee, 0x68, 0x61, 0x1d, 0xf0, 0xb2, 0xb7, 0xf8, 0xfa, 0x9c, 0x7b, 0x4b, 0x70, 0xc1, 0x8b, 0xa1, 0xda, 0x19, 0xed, 0xb6, 0x0e, 0xb8, 0xe1, 0xce, 0x7f, 0xce, 0xf9,
0x8e, 0xcf, 0xbd, 0x81, 0x3b, 0xd3, 0x44, 0xd3, 0x12, 0xa7, 0x32, 0x8f, 0x53, 0xa9, 0x59, 0x4c, 0xce, 0xf9, 0x8e, 0xbf, 0x04, 0x6e, 0x9f, 0xc4, 0x9a, 0x96, 0x38, 0x91, 0x79, 0x94, 0x48, 0xcd,
0x95, 0x8a, 0x33, 0x51, 0xc4, 0xa9, 0x14, 0x1f, 0xf9, 0x08, 0x2b, 0x2d, 0x8d, 0x44, 0xe8, 0x1c, 0x22, 0xaa, 0x54, 0x94, 0x8a, 0x22, 0x4a, 0xa4, 0xf8, 0xc8, 0x33, 0xac, 0xb4, 0x34, 0x12, 0xa1,
0xa4, 0x19, 0xa6, 0x4a, 0xe1, 0x4c, 0x14, 0xed, 0xbb, 0x7f, 0x10, 0x53, 0x99, 0xe7, 0x52, 0xc4, 0x33, 0x90, 0x66, 0x98, 0x2a, 0x85, 0x53, 0x51, 0x74, 0xef, 0x5c, 0x20, 0x26, 0x32, 0xcf, 0xa5,
0x82, 0x99, 0x98, 0x66, 0x99, 0x66, 0x45, 0xe1, 0xc8, 0xed, 0xfb, 0x97, 0x03, 0x33, 0x56, 0x18, 0x88, 0x04, 0x33, 0x11, 0x4d, 0x53, 0xcd, 0x8a, 0xc2, 0x91, 0xbb, 0xf7, 0xae, 0x06, 0xa6, 0xac,
0x2e, 0xa8, 0xe1, 0x52, 0x38, 0xf0, 0xd6, 0x57, 0x1f, 0xe0, 0x15, 0xcd, 0xd9, 0x31, 0xd3, 0x53, 0x30, 0x5c, 0x50, 0xc3, 0xa5, 0xa8, 0xc0, 0x5b, 0x0b, 0xec, 0x68, 0x39, 0x31, 0x4c, 0x9f, 0x73,
0xa6, 0xd1, 0x53, 0x58, 0x9b, 0x37, 0x8b, 0xbc, 0x8e, 0xd7, 0x0d, 0x93, 0x5b, 0x78, 0xc9, 0x8a, 0xb4, 0xf1, 0xdd, 0x07, 0x78, 0x45, 0x73, 0x76, 0xc8, 0xf4, 0x09, 0xd3, 0xe8, 0x09, 0x2c, 0x55,
0xeb, 0x84, 0x05, 0x33, 0xb8, 0x27, 0x32, 0x25, 0xb9, 0x30, 0xe4, 0x1c, 0x8f, 0x3e, 0x00, 0x52, 0xa2, 0xa1, 0xb7, 0xee, 0xf5, 0x82, 0xf8, 0x26, 0x9e, 0xb3, 0xec, 0x14, 0xb1, 0x60, 0x06, 0xf7,
0x9a, 0x4b, 0xcd, 0x0d, 0xff, 0xc2, 0xb2, 0x61, 0x26, 0x73, 0xca, 0x45, 0xe4, 0x77, 0x82, 0x6e, 0x45, 0xaa, 0x24, 0x17, 0x86, 0x9c, 0xe1, 0xd1, 0x07, 0x40, 0x4a, 0x73, 0xa9, 0xb9, 0xe1, 0x5f,
0x98, 0x3c, 0xc0, 0x17, 0x1f, 0x84, 0x17, 0xb2, 0x78, 0xe0, 0x88, 0xe5, 0xa1, 0x25, 0x91, 0xeb, 0x58, 0x3a, 0x4a, 0x65, 0x4e, 0xb9, 0x08, 0xfd, 0xf5, 0x5a, 0x2f, 0x88, 0xef, 0xe3, 0xcb, 0x8d,
0x4b, 0x8d, 0x5c, 0xa9, 0x9d, 0x41, 0xf3, 0x77, 0x10, 0xda, 0x85, 0x8a, 0x29, 0x15, 0xb3, 0x3e, 0xe3, 0x99, 0x2c, 0x1e, 0x3a, 0x62, 0xb9, 0x6f, 0x49, 0xe4, 0xff, 0xb9, 0x42, 0xee, 0x08, 0xc5,
0x9b, 0xc9, 0xce, 0x2a, 0x05, 0x87, 0x3c, 0xa2, 0x26, 0x3d, 0xe5, 0x62, 0xf4, 0xa6, 0x54, 0x8c, 0xd0, 0xc8, 0x98, 0xe4, 0x2a, 0xac, 0xd9, 0x82, 0xd7, 0x2f, 0x16, 0x74, 0xbd, 0xe1, 0xe7, 0x4c,
0x58, 0x0e, 0xda, 0x84, 0xda, 0x2f, 0x7f, 0x5e, 0xb7, 0x4e, 0xe6, 0xa7, 0xad, 0x1f, 0x15, 0xa8, 0x0e, 0x86, 0xc4, 0x41, 0xbb, 0x29, 0xb4, 0xcf, 0x17, 0x46, 0xdb, 0x50, 0x37, 0xa5, 0x62, 0xb6,
0x1d, 0xd8, 0x41, 0xa0, 0x1e, 0x84, 0x0b, 0x83, 0xb3, 0x34, 0x82, 0xff, 0x48, 0x63, 0xdf, 0x8f, 0xb7, 0x76, 0xbc, 0xb5, 0xc8, 0x95, 0x43, 0x1e, 0x50, 0x93, 0x1c, 0x73, 0x91, 0xbd, 0x29, 0x15,
0x3c, 0xb2, 0xcc, 0x43, 0x7b, 0x10, 0x0a, 0x9a, 0xb3, 0x61, 0x61, 0xcf, 0x51, 0xd5, 0xb6, 0xb9, 0x23, 0x96, 0x83, 0xd6, 0xa0, 0xf9, 0xab, 0x27, 0xaf, 0xd7, 0x22, 0xd5, 0x6e, 0xe3, 0x47, 0x1d,
0xf9, 0xf7, 0x38, 0x08, 0x88, 0xc5, 0x44, 0xf6, 0xa0, 0xfa, 0x42, 0x16, 0xa6, 0x98, 0x27, 0xb9, 0x9a, 0x7b, 0x36, 0x52, 0xd4, 0x87, 0x60, 0xd6, 0xd4, 0x34, 0xc1, 0xda, 0x5f, 0x24, 0xb8, 0xeb,
0xbd, 0x8a, 0xea, 0x2c, 0x63, 0x8b, 0xeb, 0x09, 0xa3, 0x4b, 0xeb, 0xc3, 0xf1, 0xd0, 0x0d, 0xa8, 0x87, 0x1e, 0x99, 0xe7, 0xa1, 0x1d, 0x08, 0x04, 0xcd, 0xd9, 0xa8, 0xb0, 0xfb, 0xb0, 0x61, 0xcb,
0xa7, 0x63, 0xce, 0x84, 0x19, 0x72, 0x15, 0x05, 0x1d, 0xaf, 0xdb, 0x20, 0xeb, 0xae, 0xd0, 0x57, 0xdc, 0xf8, 0x7d, 0x84, 0x04, 0xc4, 0xec, 0x15, 0x77, 0xa0, 0xf1, 0x42, 0x16, 0xa6, 0xa8, 0xd2,
0xa8, 0x0f, 0x8d, 0xc2, 0x50, 0xc3, 0xd3, 0xe1, 0xa9, 0x15, 0xa9, 0x58, 0x91, 0x9d, 0x7f, 0x88, 0xdf, 0x5c, 0x44, 0x75, 0x96, 0xb1, 0xc5, 0xf5, 0x85, 0xd1, 0xa5, 0xf5, 0xe1, 0x78, 0xe8, 0x1a,
0x1c, 0x51, 0xa5, 0xb8, 0x18, 0x91, 0xd0, 0x71, 0x9d, 0x4e, 0x0b, 0x02, 0x43, 0x47, 0x51, 0xcd, 0xb4, 0x92, 0x31, 0x67, 0xc2, 0x8c, 0x6c, 0xe2, 0x5e, 0x6f, 0x85, 0x2c, 0xbb, 0x83, 0x81, 0x42,
0x06, 0x3a, 0xfb, 0x6c, 0xbf, 0x07, 0x58, 0x58, 0x9a, 0xdd, 0x7f, 0x62, 0xa5, 0x1d, 0x57, 0x9d, 0x03, 0x58, 0x29, 0x0c, 0x35, 0x3c, 0x19, 0x1d, 0x5b, 0x91, 0xba, 0x15, 0xd9, 0xfa, 0x83, 0xc8,
0xcc, 0x3e, 0xd1, 0x63, 0xa8, 0x4e, 0xe9, 0x78, 0xc2, 0xec, 0x10, 0xc2, 0xe4, 0xf6, 0x25, 0xe1, 0x01, 0x55, 0x8a, 0x8b, 0x8c, 0x04, 0x8e, 0xeb, 0x74, 0x3a, 0x50, 0x33, 0x34, 0x0b, 0x9b, 0x36,
0xf6, 0x07, 0xaf, 0xf5, 0x7c, 0x31, 0x1c, 0x7e, 0xd7, 0x7f, 0xe2, 0xb5, 0xbf, 0x79, 0x10, 0x2e, 0xd0, 0xe9, 0xb2, 0xfb, 0x1e, 0x60, 0x66, 0x69, 0x7a, 0xff, 0x89, 0x95, 0xf6, 0xb9, 0x5a, 0x64,
0x79, 0xb9, 0x8a, 0x75, 0x40, 0x4d, 0xf0, 0x6d, 0x66, 0x41, 0xb7, 0x41, 0x7c, 0xae, 0xd0, 0x36, 0xba, 0x44, 0x8f, 0xa0, 0x71, 0x42, 0xc7, 0x13, 0x66, 0x1f, 0x21, 0x88, 0x6f, 0x5d, 0x11, 0xee,
0x34, 0x95, 0x96, 0x67, 0x7c, 0xb1, 0xde, 0x15, 0x8b, 0xdf, 0x98, 0x57, 0x9d, 0xc0, 0xbd, 0x1e, 0x60, 0xf8, 0x5a, 0x57, 0xc3, 0xe4, 0xf0, 0xdb, 0xfe, 0x63, 0xaf, 0xfb, 0xd5, 0x83, 0x60, 0xce,
0xa0, 0x8b, 0x52, 0x68, 0x1d, 0x2a, 0xcf, 0x27, 0xe3, 0x71, 0xeb, 0x1a, 0xda, 0x80, 0xfa, 0xf1, 0xcb, 0xbf, 0x18, 0x07, 0xd4, 0x06, 0xbf, 0x9a, 0xd2, 0x15, 0xe2, 0x73, 0x85, 0x36, 0xa1, 0xad,
0xe4, 0xc4, 0x75, 0x68, 0x79, 0x28, 0x84, 0xb5, 0x97, 0xac, 0xfc, 0x2c, 0x75, 0xd6, 0xf2, 0x51, 0xb4, 0x3c, 0xe5, 0xb3, 0x4f, 0xa2, 0x6e, 0xf1, 0xab, 0xd5, 0xa9, 0x13, 0xb8, 0xdb, 0x07, 0x74,
0x1d, 0xaa, 0x84, 0x8d, 0xd8, 0x59, 0x2b, 0xd8, 0x7f, 0x04, 0x9b, 0xa9, 0xcc, 0x57, 0x3c, 0x64, 0x59, 0x0a, 0x2d, 0x43, 0xfd, 0xd9, 0x64, 0x3c, 0xee, 0xfc, 0x87, 0x56, 0xa1, 0x75, 0x38, 0x39,
0xe0, 0xbd, 0x0b, 0x32, 0x51, 0x7c, 0xf7, 0xd1, 0xdb, 0x84, 0xd0, 0x12, 0x1f, 0xcc, 0xee, 0x9e, 0x72, 0x15, 0x3a, 0x1e, 0x0a, 0x60, 0xe9, 0x25, 0x2b, 0x3f, 0x4b, 0x9d, 0x76, 0x7c, 0xd4, 0x82,
0x29, 0x85, 0x0f, 0x45, 0x71, 0x52, 0xb3, 0xff, 0xf5, 0xc3, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x06, 0x61, 0x19, 0x3b, 0xed, 0xd4, 0x76, 0x1f, 0xc2, 0x5a, 0x22, 0xf3, 0x05, 0x8d, 0x0c, 0xbd,
0x15, 0xed, 0x7b, 0x41, 0x68, 0x04, 0x00, 0x00, 0x77, 0xb5, 0x54, 0x14, 0xdf, 0x7c, 0xf4, 0x36, 0x26, 0xb4, 0xc4, 0x7b, 0xd3, 0xbb, 0xa7, 0x4a,
0xe1, 0x7d, 0x51, 0x1c, 0x35, 0xed, 0xbf, 0xe0, 0xc1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c,
0x2a, 0x66, 0x8a, 0xc4, 0x04, 0x00, 0x00,
} }

View File

@ -8,6 +8,7 @@ option java_multiple_files = true;
import "v2ray.com/core/common/net/address.proto"; import "v2ray.com/core/common/net/address.proto";
import "v2ray.com/core/common/net/destination.proto"; import "v2ray.com/core/common/net/destination.proto";
import "v2ray.com/core/app/router/config.proto";
message NameServer { message NameServer {
v2ray.core.common.net.Endpoint address = 1; v2ray.core.common.net.Endpoint address = 1;
@ -18,6 +19,7 @@ message NameServer {
} }
repeated PriorityDomain prioritized_domain = 2; repeated PriorityDomain prioritized_domain = 2;
repeated v2ray.core.app.router.GeoIP geoip = 3;
} }
enum DomainMatchingType { enum DomainMatchingType {
@ -39,7 +41,7 @@ message Config {
// Deprecated. Use static_hosts. // Deprecated. Use static_hosts.
map<string, v2ray.core.common.net.IPOrDomain> Hosts = 2 [deprecated = true]; map<string, v2ray.core.common.net.IPOrDomain> Hosts = 2 [deprecated = true];
// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes (IPv6). // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes (IPv6).
bytes client_ip = 3; bytes client_ip = 3;
message HostMapping { message HostMapping {

View File

@ -10,7 +10,9 @@ import (
"time" "time"
"v2ray.com/core" "v2ray.com/core"
"v2ray.com/core/app/router"
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/errors"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/session" "v2ray.com/core/common/session"
"v2ray.com/core/common/strmatcher" "v2ray.com/core/common/strmatcher"
@ -28,9 +30,32 @@ type Server struct {
clientIP net.IP clientIP net.IP
domainMatcher strmatcher.IndexMatcher domainMatcher strmatcher.IndexMatcher
domainIndexMap map[uint32]uint32 domainIndexMap map[uint32]uint32
ipIndexMap map[uint32]*MultiGeoIPMatcher
tag string tag string
} }
// MultiGeoIPMatcher for match
type MultiGeoIPMatcher struct {
matchers []*router.GeoIPMatcher
}
var errExpectedIPNonMatch = errors.New("expected ip not match")
// Match check ip match
func (c *MultiGeoIPMatcher) Match(ip net.IP) bool {
for _, matcher := range c.matchers {
if matcher.Match(ip) {
return true
}
}
return false
}
// HasMatcher check has matcher
func (c *MultiGeoIPMatcher) HasMatcher() bool {
return len(c.matchers) > 0
}
func generateRandomTag() string { func generateRandomTag() string {
id := uuid.New() id := uuid.New()
return "v2ray.system." + id.String() return "v2ray.system." + id.String()
@ -81,15 +106,16 @@ func New(ctx context.Context, config *Config) (*Server, error) {
if len(config.NameServers) > 0 { if len(config.NameServers) > 0 {
features.PrintDeprecatedFeatureWarning("simple DNS server") features.PrintDeprecatedFeatureWarning("simple DNS server")
} for _, destPB := range config.NameServers {
addNameServer(destPB)
for _, destPB := range config.NameServers { }
addNameServer(destPB)
} }
if len(config.NameServer) > 0 { if len(config.NameServer) > 0 {
domainMatcher := &strmatcher.MatcherGroup{} domainMatcher := &strmatcher.MatcherGroup{}
domainIndexMap := make(map[uint32]uint32) domainIndexMap := make(map[uint32]uint32)
ipIndexMap := make(map[uint32]*MultiGeoIPMatcher)
var geoIPMatcherContainer router.GeoIPMatcherContainer
for _, ns := range config.NameServer { for _, ns := range config.NameServer {
idx := addNameServer(ns.Address) idx := addNameServer(ns.Address)
@ -102,10 +128,22 @@ func New(ctx context.Context, config *Config) (*Server, error) {
midx := domainMatcher.Add(matcher) midx := domainMatcher.Add(matcher)
domainIndexMap[midx] = uint32(idx) domainIndexMap[midx] = uint32(idx)
} }
var matchers []*router.GeoIPMatcher
for _, geoip := range ns.Geoip {
matcher, err := geoIPMatcherContainer.Add(geoip)
if err != nil {
return nil, newError("failed to create ip matcher").Base(err).AtWarning()
}
matchers = append(matchers, matcher)
}
matcher := &MultiGeoIPMatcher{matchers: matchers}
ipIndexMap[uint32(idx)] = matcher
} }
server.domainMatcher = domainMatcher server.domainMatcher = domainMatcher
server.domainIndexMap = domainIndexMap server.domainIndexMap = domainIndexMap
server.ipIndexMap = ipIndexMap
} }
if len(server.clients) == 0 { if len(server.clients) == 0 {
@ -135,7 +173,35 @@ func (s *Server) IsOwnLink(ctx context.Context) bool {
return inbound != nil && inbound.Tag == s.tag return inbound != nil && inbound.Tag == s.tag
} }
func (s *Server) queryIPTimeout(client Client, domain string, option IPOption) ([]net.IP, error) { // Match check dns ip match geoip
func (s *Server) Match(idx uint32, client Client, domain string, ips []net.IP) ([]net.IP, error) {
matcher, exist := s.ipIndexMap[idx]
if !exist {
newError("domain ", domain, " server not in ipIndexMap: ", client.Name(), " idx:", idx, " just return").AtDebug().WriteToLog()
return ips, nil
}
if !matcher.HasMatcher() {
newError("domain ", domain, " server has not valid matcher: ", client.Name(), " idx:", idx, " just return").AtDebug().WriteToLog()
return ips, nil
}
newIps := []net.IP{}
for _, ip := range ips {
if matcher.Match(ip) {
newIps = append(newIps, ip)
newError("domain ", domain, " ip ", ip, " is match at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
} else {
newError("domain ", domain, " ip ", ip, " is not match at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
}
}
if len(newIps) == 0 {
return nil, errExpectedIPNonMatch
}
return newIps, nil
}
func (s *Server) queryIPTimeout(idx uint32, client Client, domain string, option IPOption) ([]net.IP, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) ctx, cancel := context.WithTimeout(context.Background(), time.Second*4)
if len(s.tag) > 0 { if len(s.tag) > 0 {
ctx = session.ContextWithInbound(ctx, &session.Inbound{ ctx = session.ContextWithInbound(ctx, &session.Inbound{
@ -144,6 +210,12 @@ func (s *Server) queryIPTimeout(client Client, domain string, option IPOption) (
} }
ips, err := client.QueryIP(ctx, domain, option) ips, err := client.QueryIP(ctx, domain, option)
cancel() cancel()
if err != nil {
return ips, err
}
ips, err = s.Match(idx, client, domain, ips)
return ips, err return ips, err
} }
@ -217,12 +289,13 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
} }
var lastErr error var lastErr error
var matchedClient Client
if s.domainMatcher != nil { if s.domainMatcher != nil {
idx := s.domainMatcher.Match(domain) idx := s.domainMatcher.Match(domain)
if idx > 0 { if idx > 0 {
ns := s.clients[s.domainIndexMap[idx]] matchedClient = s.clients[s.domainIndexMap[idx]]
newError("querying domain ", domain, " at ", ns.Name()).WriteToLog() newError("domain matched, direct lookup ip for domain ", domain, " at ", matchedClient.Name()).WriteToLog()
ips, err := s.queryIPTimeout(ns, domain, option) ips, err := s.queryIPTimeout(s.domainIndexMap[idx], matchedClient, domain, option)
if len(ips) > 0 { if len(ips) > 0 {
return ips, nil return ips, nil
} }
@ -230,22 +303,30 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
return nil, err return nil, err
} }
if err != nil { if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", ns.Name()).Base(err).WriteToLog() newError("failed to lookup ip for domain ", domain, " at server ", matchedClient.Name()).Base(err).WriteToLog()
lastErr = err lastErr = err
} }
} }
} }
for _, client := range s.clients { for idx, client := range s.clients {
ips, err := s.queryIPTimeout(client, domain, option) if client == matchedClient {
newError("domain ", domain, " at server ", client.Name(), " idx:", idx, " already lookup failed, just ignore").AtDebug().WriteToLog()
continue
}
newError("try to lookup ip for domain ", domain, " at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
ips, err := s.queryIPTimeout(uint32(idx), client, domain, option)
if len(ips) > 0 { if len(ips) > 0 {
newError("lookup ip for domain ", domain, " success: ", ips, " at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
return ips, nil return ips, nil
} }
if err != nil { if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog() newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
lastErr = err lastErr = err
} }
if err != context.Canceled && err != context.DeadlineExceeded { if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
return nil, err return nil, err
} }
} }

View File

@ -13,6 +13,7 @@ import (
"v2ray.com/core/app/policy" "v2ray.com/core/app/policy"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
_ "v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/proxyman/outbound"
"v2ray.com/core/app/router"
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
@ -426,3 +427,113 @@ func TestStaticHostDomain(t *testing.T) {
dnsServer.Shutdown() dnsServer.Shutdown()
} }
func TestIPMatch(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{
NameServer: []*NameServer{
// private dns, not match
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
Geoip: []*router.GeoIP{
{
CountryCode: "local",
Cidr: []*router.CIDR{
{
// inner ip, will not match
Ip: []byte{192, 168, 11, 1},
Prefix: 32,
},
},
},
},
},
// second dns, match ip
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
Geoip: []*router.GeoIP{
{
CountryCode: "test",
Cidr: []*router.CIDR{
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
},
},
{
CountryCode: "test",
Cidr: []*router.CIDR{
{
Ip: []byte{8, 8, 8, 4},
Prefix: 32,
},
},
},
},
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
startTime := time.Now()
{
ips, err := client.LookupIP("google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.")
}
}

View File

@ -131,7 +131,7 @@ func (b *Buffer) IsEmpty() bool {
// IsFull returns true if the buffer has no more room to grow. // IsFull returns true if the buffer has no more room to grow.
func (b *Buffer) IsFull() bool { func (b *Buffer) IsFull() bool {
return b.end == int32(len(b.v)) return b != nil && b.end == int32(len(b.v))
} }
// Write implements Write method in io.Writer. // Write implements Write method in io.Writer.

View File

@ -46,6 +46,62 @@ func TestBufferString(t *testing.T) {
} }
} }
func TestBufferByte(t *testing.T) {
{
buffer := New()
common.Must(buffer.WriteByte('m'))
if buffer.String() != "m" {
t.Error("expect buffer content as ", "m", " but actually ", buffer.String())
}
buffer.Release()
}
{
buffer := StackNew()
common.Must(buffer.WriteByte('n'))
if buffer.String() != "n" {
t.Error("expect buffer content as ", "n", " but actually ", buffer.String())
}
buffer.Release()
}
{
buffer := StackNew()
common.Must2(buffer.WriteString("HELLOWORLD"))
if b := buffer.Byte(5); b != 'W' {
t.Error("unexpected byte ", b)
}
buffer.SetByte(5, 'M')
if buffer.String() != "HELLOMORLD" {
t.Error("expect buffer content as ", "n", " but actually ", buffer.String())
}
buffer.Release()
}
}
func TestBufferResize(t *testing.T) {
buffer := New()
defer buffer.Release()
const payload = "Test String"
common.Must2(buffer.WriteString(payload))
if buffer.String() != payload {
t.Error("expect buffer content as ", payload, " but actually ", buffer.String())
}
buffer.Resize(-6, -3)
if l := buffer.Len(); int(l) != 3 {
t.Error("len error ", l)
}
if s := buffer.String(); s != "Str" {
t.Error("unexpect buffer ", s)
}
buffer.Resize(int32(len(payload)), 200)
if l := buffer.Len(); int(l) != 200-len(payload) {
t.Error("len error ", l)
}
}
func TestBufferSlice(t *testing.T) { func TestBufferSlice(t *testing.T) {
{ {
b := New() b := New()

View File

@ -0,0 +1,39 @@
???8+?$??I????+??????+?+++?IO7$ZD88ZDMD8OZ$7II7+++++++++++++
+??7++???I????????+?+++?+I?IZI$OND7ODDDDDD7Z$IZI++++++++++++
???I????????????~,...~?++I?777$DD8O8DDD88O$O7$7I++++++++++?+
???????????????.,::~...,+?I77ZZD8ZDNDDDDD8ZZ7$$7+++++++?+?+?
??????????????.,,:~~~==,I?7$$ZOD8ODNDD8DDZ$87777++?+++?????+
?????????I?=...:~~~~=~=+I?$$ZODD88ND8N8DDOZOZ77?????++??????
???II?????.,,,:==~~===I?IIZ$O$88ODD8ODNDDDOO$7$??I?++?++++??
???I????+..,,~=+???+?????7OOZZ8O$$778DDDDDO87I$I++++++++????
I??????..,,:~=??????+=,~?ZZZ$$I??II$DDDDD8Z8I~,+=?II$777IIII
II???,.,,::~??I?I?....,,~==I?+===+?$ODN8DD$O=,......+?????II
I?I?..,,:~~????,...,,::::~~~~~~~~=+$88ODD88=~,,,.......IIIII
II,..,,:~~I?:..,,,::::~~~~~~~~~~~~~+IOZ87?~~~::::,,,,...=?II
I,...,:::....,:::::::~~~~~~~~~~~~~~~=++=~~~~~~~~~~~:::,,,?II
,,,,~....,,,::::::::::::::~~~~~~~~~~~~~~~~~~~~~~~~~~~::,,,??
:~:...,,,:::::::::::::::::::~~~~~~~~~~~~~~~~~~~~~~~~~~::,,II
:::::::::::::::::::~+++::::::~~~~~~~~~~~~~~~~~~~~~~~~::::,,7
::::::::::::::~IIII?????:::::::~~~~~~~~~~~~~~~~~~~~~::::::,I
:,,,,,,,:+ZIIIIIIIIIIIII:::~::~~~~~~~~~~~~~~~~~~~~=~::::::::
7I777IIZI7ZIIIIIIIIIIII7?:~~~~~~~~~~~~~~~~~~~~~~~~~=~:::::::
$$$77$7Z77$7I77IIII7III$$:~~~~~~~~~~~~~~~~~~~~~~~=II~:::::::
$$$8$Z7$7$Z777777777777Z7~:~~~~~~~~~~~~~~~~~~~~~~$777::::::,
ZOZOZOZZ$7$$ZZ$8DDDZ777$$=~~~~~~~~~~~~~~~~~~~~~~~$$$7~:::::,
OOZOOOZZOOZO$ZZZ$O$$$$7ZZ$~~~~~~~~~~~~~~~~~~~~~~~ZZ$ZZ:::::,
O88OOOOO8ODOZZZZZOOZ8OOOOO:~~~~~~~~~~~~~~~~~~~~~ZOZZZZ~:::::
8888O8OODZ8ZOZOZZOOZOOOOOZ:::~~~~~~~~~~~~~~~~~~~,Z$ZOOO:::::
Z88O88D8Z88ZZOOZZOZ$$Z$$OZ:::~~~~~~~~~~~~~~~~~~~,,ZOOOOO::::
888D88OODD8DNDNDNNDDDD88OI:::::~~~~~~~~~~~~~~~~~.,:8ZO8O::::
D8D88DO88ZOOZOO8DDDNOZ$$O8~::::~~~~~~~~~~~~~===~..,88O8OO:::
8OD8O8OODO$D8DO88DO8O8888O~~::~~::~~~~~~~~~~~===...:8OOOZ~::
:..................,~,..~,~~:~:~~~~~~~~~~~~~~===...,+.....~~
.........................~~~:~~~~~~~~~~~~~~~~~==:..,......:~
.Made with love.........,~~~~~~~~:~~~~::~~~~~~~==..,,......:
........................~~~~~~~~~~~~~~:~~~~~~~~===,.,......~
...................,,..~~~~~~~~~~~~~~~~~~~~~~~~~==~,,.......
..................,,::~~~~~~~~~~~~~~~~~~~~~~~~~====~.,....,.
....................:~~~~~~~~~~~~~~~~~~~~~~~~~~~~==~:......,
......................,~================,.==~~~=~===~,......
.Thank you for your support.....................:~=,,,,,,,..

View File

@ -1,6 +1,7 @@
package buf_test package buf_test
import ( import (
"bytes"
"crypto/rand" "crypto/rand"
"io" "io"
"testing" "testing"
@ -96,6 +97,66 @@ func TestMultiBufferSplitFirst(t *testing.T) {
} }
} }
func TestMultiBufferReadAllToByte(t *testing.T) {
lb := make([]byte, 8*1024)
common.Must2(io.ReadFull(rand.Reader, lb))
rd := bytes.NewBuffer(lb)
b, err := ReadAllToBytes(rd)
common.Must(err)
if l := len(b); l != 8*1024 {
t.Error("unexpceted length from ReadAllToBytes", l)
}
}
func TestMultiBufferCopy(t *testing.T) {
lb := make([]byte, 8*1024)
common.Must2(io.ReadFull(rand.Reader, lb))
reader := bytes.NewBuffer(lb)
mb, err := ReadFrom(reader)
common.Must(err)
lbdst := make([]byte, 8*1024)
mb.Copy(lbdst)
if d := cmp.Diff(lb, lbdst); d != "" {
t.Error("unexpceted different from MultiBufferCopy ", d)
}
}
func TestSplitFirstBytes(t *testing.T) {
a := New()
common.Must2(a.WriteString("ab"))
b := New()
common.Must2(b.WriteString("bc"))
mb := MultiBuffer{a, b}
o := make([]byte, 2)
_, cnt := SplitFirstBytes(mb, o)
if cnt != 2 {
t.Error("unexpected cnt from SplitFirstBytes ", cnt)
}
if d := cmp.Diff(string(o), "ab"); d != "" {
t.Error("unexpected splited result from SplitFirstBytes ", d)
}
}
func TestCompact(t *testing.T) {
a := New()
common.Must2(a.WriteString("ab"))
b := New()
common.Must2(b.WriteString("bc"))
mb := MultiBuffer{a, b}
cmb := Compact(mb)
if w := cmb.String(); w != "abbc" {
t.Error("unexpected Compact result ", w)
}
}
func BenchmarkSplitBytes(b *testing.B) { func BenchmarkSplitBytes(b *testing.B) {
var mb MultiBuffer var mb MultiBuffer
raw := make([]byte, Size) raw := make([]byte, Size)

View File

@ -27,12 +27,12 @@ func readOneUDP(r io.Reader) (*Buffer, error) {
// ReadBuffer reads a Buffer from the given reader. // ReadBuffer reads a Buffer from the given reader.
func ReadBuffer(r io.Reader) (*Buffer, error) { func ReadBuffer(r io.Reader) (*Buffer, error) {
b := New() b := New()
_, err := b.ReadFrom(r) n, err := b.ReadFrom(r)
if err != nil { if n > 0 {
b.Release() return b, err
return nil, err
} }
return b, nil b.Release()
return nil, err
} }
// BufferedReader is a Reader that keeps its internal buffer. // BufferedReader is a Reader that keeps its internal buffer.
@ -156,10 +156,7 @@ type SingleReader struct {
// ReadMultiBuffer implements Reader. // ReadMultiBuffer implements Reader.
func (r *SingleReader) ReadMultiBuffer() (MultiBuffer, error) { func (r *SingleReader) ReadMultiBuffer() (MultiBuffer, error) {
b, err := ReadBuffer(r.Reader) b, err := ReadBuffer(r.Reader)
if err != nil { return MultiBuffer{b}, err
return nil, err
}
return MultiBuffer{b}, nil
} }
// PacketReader is a Reader that read one Buffer every time. // PacketReader is a Reader that read one Buffer every time.

View File

@ -1,10 +1,14 @@
package buf_test package buf_test
import ( import (
"bytes"
"io" "io"
"io/ioutil"
"os"
"strings" "strings"
"testing" "testing"
"github.com/google/go-cmp/cmp"
"v2ray.com/core/common" "v2ray.com/core/common"
. "v2ray.com/core/common/buf" . "v2ray.com/core/common/buf"
"v2ray.com/core/transport/pipe" "v2ray.com/core/transport/pipe"
@ -65,6 +69,9 @@ func TestReadByte(t *testing.T) {
if b != 'a' { if b != 'a' {
t.Error("unexpected byte: ", b, " want a") t.Error("unexpected byte: ", b, " want a")
} }
if reader.BufferedBytes() != 3 { // 3 bytes left in buffer
t.Error("unexpected buffered Bytes: ", reader.BufferedBytes())
}
nBytes, err := reader.WriteTo(DiscardBytes) nBytes, err := reader.WriteTo(DiscardBytes)
common.Must(err) common.Must(err)
@ -73,6 +80,67 @@ func TestReadByte(t *testing.T) {
} }
} }
func TestReadBuffer(t *testing.T) {
{
sr := strings.NewReader("abcd")
buf, err := ReadBuffer(sr)
common.Must(err)
if s := buf.String(); s != "abcd" {
t.Error("unexpected str: ", s, " want abcd")
}
buf.Release()
}
{
const dat = "data/test_ReadBuffer.dat"
f, err := os.Open(dat)
common.Must(err)
defer f.Close()
buf2, err := ReadBuffer(f)
common.Must(err)
cnt, err := ioutil.ReadFile(dat)
common.Must(err)
if cmp.Diff(buf2.Bytes(), cnt) != "" {
t.Error("fail to read from file")
}
buf2.Release()
}
}
func TestReadAtMost(t *testing.T) {
sr := strings.NewReader("abcd")
reader := &BufferedReader{
Reader: NewReader(sr),
}
mb, err := reader.ReadAtMost(3)
common.Must(err)
if s := mb.String(); s != "abc" {
t.Error("unexpected read result: ", s)
}
nBytes, err := reader.WriteTo(DiscardBytes)
common.Must(err)
if nBytes != 1 {
t.Error("unexpect bytes written: ", nBytes)
}
}
func TestPacketReader_ReadMultiBuffer(t *testing.T) {
const alpha = "abcefg"
buf := bytes.NewBufferString(alpha)
reader := &PacketReader{buf}
mb, err := reader.ReadMultiBuffer()
common.Must(err)
if s := mb.String(); s != alpha {
t.Error("content: ", s)
}
}
func TestReaderInterface(t *testing.T) { func TestReaderInterface(t *testing.T) {
_ = (io.Reader)(new(ReadVReader)) _ = (io.Reader)(new(ReadVReader))
_ = (Reader)(new(ReadVReader)) _ = (Reader)(new(ReadVReader))

View File

@ -120,13 +120,10 @@ func (r *ReadVReader) readMulti() (MultiBuffer, error) {
func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) { func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
if r.alloc.Current() == 1 { if r.alloc.Current() == 1 {
b, err := ReadBuffer(r.Reader) b, err := ReadBuffer(r.Reader)
if err != nil {
return nil, err
}
if b.IsFull() { if b.IsFull() {
r.alloc.Adjust(1) r.alloc.Adjust(1)
} }
return MultiBuffer{b}, nil return MultiBuffer{b}, err
} }
mb, err := r.readMulti() mb, err := r.readMulti()

View File

@ -11,9 +11,10 @@ import (
) )
type NameServerConfig struct { type NameServerConfig struct {
Address *Address Address *Address
Port uint16 Port uint16
Domains []string Domains []string
ExpectIPs StringList
} }
func (c *NameServerConfig) UnmarshalJSON(data []byte) error { func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
@ -25,14 +26,16 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
} }
var advanced struct { var advanced struct {
Address *Address `json:"address"` Address *Address `json:"address"`
Port uint16 `json:"port"` Port uint16 `json:"port"`
Domains []string `json:"domains"` Domains []string `json:"domains"`
ExpectIPs StringList `json:"expectIps"`
} }
if err := json.Unmarshal(data, &advanced); err == nil { if err := json.Unmarshal(data, &advanced); err == nil {
c.Address = advanced.Address c.Address = advanced.Address
c.Port = advanced.Port c.Port = advanced.Port
c.Domains = advanced.Domains c.Domains = advanced.Domains
c.ExpectIPs = advanced.ExpectIPs
return nil return nil
} }
@ -75,6 +78,11 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
} }
} }
geoipList, err := toCidrList(c.ExpectIPs)
if err != nil {
return nil, newError("invalid ip rule: ", c.ExpectIPs).Base(err)
}
return &dns.NameServer{ return &dns.NameServer{
Address: &net.Endpoint{ Address: &net.Endpoint{
Network: net.Network_UDP, Network: net.Network_UDP,
@ -82,6 +90,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
Port: uint32(c.Port), Port: uint32(c.Port),
}, },
PrioritizedDomain: domains, PrioritizedDomain: domains,
Geoip: geoipList,
}, nil }, nil
} }