1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-26 05:46:10 -04:00

Merge pull request #2037 from weaving118/master

add ip match feature for dns
This commit is contained in:
Kslr 2019-11-21 22:15:26 +08:00 committed by GitHub
commit e52d3fa90b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 51 deletions

View File

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

View File

@ -10,7 +10,9 @@ import (
"time"
"v2ray.com/core"
"v2ray.com/core/app/router"
"v2ray.com/core/common"
"v2ray.com/core/common/errors"
"v2ray.com/core/common/net"
"v2ray.com/core/common/session"
"v2ray.com/core/common/strmatcher"
@ -28,9 +30,35 @@ type Server struct {
clientIP net.IP
domainMatcher strmatcher.IndexMatcher
domainIndexMap map[uint32]uint32
ipIndexMap map[uint32]*MultiGeoIPMatcher
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 {
if len(c.matchers) > 0 {
return true
}
return false
}
func generateRandomTag() string {
id := uuid.New()
return "v2ray.system." + id.String()
@ -87,9 +115,12 @@ func New(ctx context.Context, config *Config) (*Server, error) {
addNameServer(destPB)
}
var geoIPMatcherContainer router.GeoIPMatcherContainer
if len(config.NameServer) > 0 {
domainMatcher := &strmatcher.MatcherGroup{}
domainIndexMap := make(map[uint32]uint32)
ipIndexMap := make(map[uint32]*MultiGeoIPMatcher)
for _, ns := range config.NameServer {
idx := addNameServer(ns.Address)
@ -102,10 +133,23 @@ func New(ctx context.Context, config *Config) (*Server, error) {
midx := domainMatcher.Add(matcher)
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.domainIndexMap = domainIndexMap
server.ipIndexMap = ipIndexMap
}
if len(server.clients) == 0 {
@ -135,7 +179,35 @@ func (s *Server) IsOwnLink(ctx context.Context) bool {
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 == false {
newError("domain ", domain, " server not in ipIndexMap: ", client.Name(), " idx:", idx, " just return").AtDebug().WriteToLog()
return ips, nil
}
if matcher.HasMatcher() == false {
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)
if len(s.tag) > 0 {
ctx = session.ContextWithInbound(ctx, &session.Inbound{
@ -144,6 +216,12 @@ func (s *Server) queryIPTimeout(client Client, domain string, option IPOption) (
}
ips, err := client.QueryIP(ctx, domain, option)
cancel()
if err != nil {
return ips, err
}
ips, err = s.Match(idx, client, domain, ips)
return ips, err
}
@ -217,12 +295,13 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
}
var lastErr error
var matchedClient Client
if s.domainMatcher != nil {
idx := s.domainMatcher.Match(domain)
if idx > 0 {
ns := s.clients[s.domainIndexMap[idx]]
newError("querying domain ", domain, " at ", ns.Name()).WriteToLog()
ips, err := s.queryIPTimeout(ns, domain, option)
matchedClient = s.clients[s.domainIndexMap[idx]]
newError("domain matched, direct lookup ip for domain ", domain, " at ", matchedClient.Name()).WriteToLog()
ips, err := s.queryIPTimeout(s.domainIndexMap[idx], matchedClient, domain, option)
if len(ips) > 0 {
return ips, nil
}
@ -230,22 +309,30 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
return nil, err
}
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
}
}
}
for _, client := range s.clients {
ips, err := s.queryIPTimeout(client, domain, option)
for idx, client := range s.clients {
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 {
newError("lookup ip for domain ", domain, " success: ", ips, " at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
return ips, nil
}
if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
lastErr = err
}
if err != context.Canceled && err != context.DeadlineExceeded {
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
return nil, err
}
}

View File

@ -13,6 +13,7 @@ import (
"v2ray.com/core/app/policy"
"v2ray.com/core/app/proxyman"
_ "v2ray.com/core/app/proxyman/outbound"
"v2ray.com/core/app/router"
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
@ -426,3 +427,124 @@ func TestStaticHostDomain(t *testing.T) {
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{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
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

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