Merge branch 'dns' into dns-geo

This commit is contained in:
秋のかえで 2021-04-10 13:02:48 +08:00
commit b0a66e650c
No known key found for this signature in database
GPG Key ID: C687746B27587C0D
29 changed files with 540 additions and 399 deletions

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0 // protoc-gen-go v1.25.0
// protoc v3.15.6 // protoc v3.15.8
// source: app/dns/config.proto // source: app/dns/config.proto
package dns package dns
@ -77,6 +77,55 @@ func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{0} return file_app_dns_config_proto_rawDescGZIP(), []int{0}
} }
type CacheStrategy int32
const (
CacheStrategy_Cache_ALL CacheStrategy = 0
CacheStrategy_Cache_NOERROR CacheStrategy = 1
CacheStrategy_Cache_DISABLE CacheStrategy = 2
)
// Enum value maps for CacheStrategy.
var (
CacheStrategy_name = map[int32]string{
0: "Cache_ALL",
1: "Cache_NOERROR",
2: "Cache_DISABLE",
}
CacheStrategy_value = map[string]int32{
"Cache_ALL": 0,
"Cache_NOERROR": 1,
"Cache_DISABLE": 2,
}
)
func (x CacheStrategy) Enum() *CacheStrategy {
p := new(CacheStrategy)
*p = x
return p
}
func (x CacheStrategy) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CacheStrategy) Descriptor() protoreflect.EnumDescriptor {
return file_app_dns_config_proto_enumTypes[1].Descriptor()
}
func (CacheStrategy) Type() protoreflect.EnumType {
return &file_app_dns_config_proto_enumTypes[1]
}
func (x CacheStrategy) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use CacheStrategy.Descriptor instead.
func (CacheStrategy) EnumDescriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
}
type NameServer struct { type NameServer struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -84,6 +133,7 @@ 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"`
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
PrioritizedDomain []*domain.Domain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` PrioritizedDomain []*domain.Domain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
Geoip []*geoip.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"` Geoip []*geoip.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"` OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
@ -135,6 +185,13 @@ func (x *NameServer) GetClientIp() []byte {
return nil return nil
} }
func (x *NameServer) GetSkipFallback() bool {
if x != nil {
return x.SkipFallback
}
return false
}
func (x *NameServer) GetPrioritizedDomain() []*domain.Domain { func (x *NameServer) GetPrioritizedDomain() []*domain.Domain {
if x != nil { if x != nil {
return x.PrioritizedDomain return x.PrioritizedDomain
@ -180,9 +237,10 @@ type Config struct {
StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"` StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"`
// Tag is the inbound tag of DNS client. // Tag is the inbound tag of DNS client.
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"` Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
// DisableCache Disable DNS cache // DisableCache disables DNS cache
DisableCache bool `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"` CacheStrategy CacheStrategy `protobuf:"varint,8,opt,name=cache_strategy,json=cacheStrategy,proto3,enum=xray.app.dns.CacheStrategy" json:"cache_strategy,omitempty"`
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"` QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
} }
func (x *Config) Reset() { func (x *Config) Reset() {
@ -261,11 +319,11 @@ func (x *Config) GetTag() string {
return "" return ""
} }
func (x *Config) GetDisableCache() bool { func (x *Config) GetCacheStrategy() CacheStrategy {
if x != nil { if x != nil {
return x.DisableCache return x.CacheStrategy
} }
return false return CacheStrategy_Cache_ALL
} }
func (x *Config) GetQueryStrategy() QueryStrategy { func (x *Config) GetQueryStrategy() QueryStrategy {
@ -275,6 +333,13 @@ func (x *Config) GetQueryStrategy() QueryStrategy {
return QueryStrategy_USE_IP return QueryStrategy_USE_IP
} }
func (x *Config) GetDisableFallback() bool {
if x != nil {
return x.DisableFallback
}
return false
}
type NameServer_OriginalRule struct { type NameServer_OriginalRule struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -417,80 +482,91 @@ var file_app_dns_config_proto_rawDesc = []byte{
0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xef, 0x02, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x74, 0x6f, 0x22, 0x93, 0x03, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x49, 0x70, 0x12, 0x51, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62,
0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46,
0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x51, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72,
0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x67, 0x65,
0x70, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e,
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f,
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72,
0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61,
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x1a, 0x36, 0x0a, 0x0c, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c,
0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73,
0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65,
0x73, 0x69, 0x7a, 0x65, 0x22, 0x95, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xdf, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f,
0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x76, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72,
0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x05, 0x48, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12,
0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x02, 0x18, 0x01, 0x52, 0x39, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f,
0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42,
0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x02, 0x18, 0x01, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x42, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x42,
0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74,
0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x1a, 0x55, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x67, 0x79, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9a, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x1a, 0x55, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x76, 0x61,
0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9a, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74,
0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x35, 0x0a, 0x0d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61,
0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x69, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52,
0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a,
0x36, 0x10, 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a,
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f,
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75,
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55,
0x74, 0x6f, 0x33, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49,
0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10,
0x02, 0x2a, 0x44, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x41, 0x4c, 0x4c, 0x10,
0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x4e, 0x4f, 0x45, 0x52, 0x52,
0x4f, 0x52, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x44, 0x49,
0x53, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73,
0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -505,38 +581,40 @@ func file_app_dns_config_proto_rawDescGZIP() []byte {
return file_app_dns_config_proto_rawDescData return file_app_dns_config_proto_rawDescData
} }
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_app_dns_config_proto_goTypes = []interface{}{ var file_app_dns_config_proto_goTypes = []interface{}{
(QueryStrategy)(0), // 0: xray.app.dns.QueryStrategy (QueryStrategy)(0), // 0: xray.app.dns.QueryStrategy
(*NameServer)(nil), // 1: xray.app.dns.NameServer (CacheStrategy)(0), // 1: xray.app.dns.CacheStrategy
(*Config)(nil), // 2: xray.app.dns.Config (*NameServer)(nil), // 2: xray.app.dns.NameServer
(*NameServer_OriginalRule)(nil), // 3: xray.app.dns.NameServer.OriginalRule (*Config)(nil), // 3: xray.app.dns.Config
nil, // 4: xray.app.dns.Config.HostsEntry (*NameServer_OriginalRule)(nil), // 4: xray.app.dns.NameServer.OriginalRule
(*Config_HostMapping)(nil), // 5: xray.app.dns.Config.HostMapping nil, // 5: xray.app.dns.Config.HostsEntry
(*net.Endpoint)(nil), // 6: xray.common.net.Endpoint (*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
(*domain.Domain)(nil), // 7: xray.common.matcher.domain.Domain (*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
(*geoip.GeoIP)(nil), // 8: xray.common.matcher.geoip.GeoIP (*domain.Domain)(nil), // 8: xray.common.matcher.domain.Domain
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain (*geoip.GeoIP)(nil), // 9: xray.common.matcher.geoip.GeoIP
(domain.MatchingType)(0), // 10: xray.common.matcher.domain.MatchingType (*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
(domain.MatchingType)(0), // 11: xray.common.matcher.domain.MatchingType
} }
var file_app_dns_config_proto_depIdxs = []int32{ var file_app_dns_config_proto_depIdxs = []int32{
6, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint 7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
7, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.common.matcher.domain.Domain 8, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.common.matcher.domain.Domain
8, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.common.matcher.geoip.GeoIP 9, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.common.matcher.geoip.GeoIP
3, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule 4, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
6, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint 7, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint
1, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer 2, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
4, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry 5, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry
5, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping 6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
0, // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy 1, // 8: xray.app.dns.Config.cache_strategy:type_name -> xray.app.dns.CacheStrategy
9, // 9: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain 0, // 9: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
10, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.common.matcher.domain.MatchingType 10, // 10: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain
11, // [11:11] is the sub-list for method output_type 11, // 11: xray.app.dns.Config.HostMapping.type:type_name -> xray.common.matcher.domain.MatchingType
11, // [11:11] is the sub-list for method input_type 12, // [12:12] is the sub-list for method output_type
11, // [11:11] is the sub-list for extension type_name 12, // [12:12] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension extendee 12, // [12:12] is the sub-list for extension type_name
0, // [0:11] is the sub-list for field type_name 12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
} }
func init() { file_app_dns_config_proto_init() } func init() { file_app_dns_config_proto_init() }
@ -599,7 +677,7 @@ func file_app_dns_config_proto_init() {
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_dns_config_proto_rawDesc, RawDescriptor: file_app_dns_config_proto_rawDesc,
NumEnums: 1, NumEnums: 2,
NumMessages: 5, NumMessages: 5,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,

View File

@ -14,6 +14,7 @@ import "common/matcher/geoip/geoip.proto";
message NameServer { message NameServer {
xray.common.net.Endpoint address = 1; xray.common.net.Endpoint address = 1;
bytes client_ip = 5; bytes client_ip = 5;
bool skipFallback = 6;
message OriginalRule { message OriginalRule {
string rule = 1; string rule = 1;
@ -31,6 +32,12 @@ enum QueryStrategy {
USE_IP6 = 2; USE_IP6 = 2;
} }
enum CacheStrategy {
Cache_ALL = 0;
Cache_NOERROR = 1;
Cache_DISABLE = 2;
}
message Config { message Config {
// Nameservers used by this DNS. Only traditional UDP servers are support at // Nameservers used by this DNS. Only traditional UDP servers are support at
// the moment. A special value 'localhost' as a domain address can be set to // the moment. A special value 'localhost' as a domain address can be set to
@ -67,8 +74,10 @@ message Config {
reserved 7; reserved 7;
// DisableCache Disable DNS cache // DisableCache disables DNS cache
bool disableCache = 8; CacheStrategy cache_strategy = 8;
QueryStrategy query_strategy = 9; QueryStrategy query_strategy = 9;
bool disableFallback = 10;
} }

View File

@ -23,7 +23,8 @@ import (
type DNS struct { type DNS struct {
sync.Mutex sync.Mutex
tag string tag string
disableCache bool cs CacheStrategy
disableFallback bool
ipOption *dns.IPOption ipOption *dns.IPOption
hosts *StaticHosts hosts *StaticHosts
clients []*Client clients []*Client
@ -138,7 +139,8 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
ctx: ctx, ctx: ctx,
domainMatcher: domainMatcher, domainMatcher: domainMatcher,
matcherInfos: matcherInfos, matcherInfos: matcherInfos,
disableCache: config.DisableCache, cs: config.CacheStrategy,
disableFallback: config.DisableFallback,
}, nil }, nil
} }
@ -165,35 +167,42 @@ func (s *DNS) IsOwnLink(ctx context.Context) bool {
// LookupIP implements dns.Client. // LookupIP implements dns.Client.
func (s *DNS) LookupIP(domain string) ([]net.IP, error) { func (s *DNS) LookupIP(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, dns.IPOption{ return s.lookupIPInternal(domain, s.ipOption.Copy())
IPv4Enable: true, }
IPv6Enable: true,
FakeEnable: false, // LookupOptions implements dns.Client.
}) func (s *DNS) LookupOptions(domain string, opts ...dns.Option) ([]net.IP, error) {
opt := s.ipOption.Copy()
for _, o := range opts {
if o != nil {
o(opt)
}
}
return s.lookupIPInternal(domain, opt)
} }
// LookupIPv4 implements dns.IPv4Lookup. // LookupIPv4 implements dns.IPv4Lookup.
func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) { func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, dns.IPOption{ return s.lookupIPInternal(domain, &dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: false,
FakeEnable: false,
}) })
} }
// LookupIPv6 implements dns.IPv6Lookup. // LookupIPv6 implements dns.IPv6Lookup.
func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) { func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, dns.IPOption{ return s.lookupIPInternal(domain, &dns.IPOption{
IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false,
}) })
} }
func (s *DNS) lookupIPInternal(domain string, option dns.IPOption) ([]net.IP, error) { func (s *DNS) lookupIPInternal(domain string, option *dns.IPOption) ([]net.IP, error) {
if domain == "" { if domain == "" {
return nil, newError("empty domain name") return nil, newError("empty domain name")
} }
if isQuery(option) {
return nil, newError("empty option: Impossible.").AtWarning()
}
// Normalize the FQDN form query // Normalize the FQDN form query
if strings.HasSuffix(domain, ".") { if strings.HasSuffix(domain, ".") {
@ -209,20 +218,20 @@ func (s *DNS) lookupIPInternal(domain string, option dns.IPOption) ([]net.IP, er
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
newError("domain replaced: ", domain, " -> ", addrs[0].Domain()).WriteToLog() newError("domain replaced: ", domain, " -> ", addrs[0].Domain()).WriteToLog()
domain = addrs[0].Domain() domain = addrs[0].Domain()
default: // Successfully found ip records in static host default:
// Successfully found ip records in static host.
// Skip hosts mapping result in FakeDNS query.
if isIPQuery(option) {
newError("returning ", len(addrs), " IPs for domain ", domain).WriteToLog() newError("returning ", len(addrs), " IPs for domain ", domain).WriteToLog()
return toNetIP(addrs) return toNetIP(addrs)
} }
}
// Name servers lookup // Name servers lookup
errs := []error{} errs := []error{}
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag}) ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
for _, client := range s.sortClients(domain) { for _, client := range s.sortClients(domain, option) {
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") { ips, err := client.QueryIP(ctx, domain, *option, s.cs)
newError("skip DNS resolution for domain ", domain, " at server ", client.Name()).AtDebug().WriteToLog()
continue
}
ips, err := client.QueryIP(ctx, domain, option, s.disableCache)
if len(ips) > 0 { if len(ips) > 0 {
return ips, nil return ips, nil
} }
@ -238,33 +247,35 @@ func (s *DNS) lookupIPInternal(domain string, option dns.IPOption) ([]net.IP, er
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...)) return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...))
} }
// GetIPOption implements ClientWithIPOption. func (s *DNS) sortClients(domain string, option *dns.IPOption) []*Client {
func (s *DNS) GetIPOption() *dns.IPOption {
return s.ipOption
}
// SetQueryOption implements ClientWithIPOption.
func (s *DNS) SetQueryOption(isIPv4Enable, isIPv6Enable bool) {
s.ipOption.IPv4Enable = isIPv4Enable
s.ipOption.IPv6Enable = isIPv6Enable
}
// SetFakeDNSOption implements ClientWithIPOption.
func (s *DNS) SetFakeDNSOption(isFakeEnable bool) {
s.ipOption.FakeEnable = isFakeEnable
}
func (s *DNS) sortClients(domain string) []*Client {
clients := make([]*Client, 0, len(s.clients)) clients := make([]*Client, 0, len(s.clients))
clientUsed := make([]bool, len(s.clients)) clientUsed := make([]bool, len(s.clients))
clientNames := make([]string, 0, len(s.clients)) clientNames := make([]string, 0, len(s.clients))
domainRules := []string{} domainRules := []string{}
defer func() {
if len(domainRules) > 0 {
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
}
if len(clientNames) > 0 {
newError("domain ", domain, " will use DNS in order: ", clientNames).AtDebug().WriteToLog()
}
if len(clients) == 0 {
clients = append(clients, s.clients[0])
clientNames = append(clientNames, s.clients[0].Name())
newError("domain ", domain, " will use the first DNS: ", clientNames).AtDebug().WriteToLog()
}
}()
// Priority domain matching // Priority domain matching
for _, match := range s.domainMatcher.Match(domain) { for _, match := range s.domainMatcher.Match(domain) {
info := s.matcherInfos[match] info := s.matcherInfos[match]
client := s.clients[info.clientIdx] client := s.clients[info.clientIdx]
domainRule := client.domains[info.domainRuleIdx] domainRule := client.domains[info.domainRuleIdx]
if !canQueryOnClient(option, client) {
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
continue
}
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx)) domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx))
if clientUsed[info.clientIdx] { if clientUsed[info.clientIdx] {
continue continue
@ -274,22 +285,24 @@ func (s *DNS) sortClients(domain string) []*Client {
clientNames = append(clientNames, client.Name()) clientNames = append(clientNames, client.Name())
} }
if !s.disableFallback {
// Default round-robin query // Default round-robin query
for idx, client := range s.clients { for idx, client := range s.clients {
if clientUsed[idx] { if clientUsed[idx] || client.skipFallback {
continue continue
} }
if !canQueryOnClient(option, client) {
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
continue
}
clientUsed[idx] = true clientUsed[idx] = true
clients = append(clients, client) clients = append(clients, client)
clientNames = append(clientNames, client.Name()) clientNames = append(clientNames, client.Name())
} }
}
if len(domainRules) > 0 {
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
}
if len(clientNames) > 0 {
newError("domain ", domain, " will use DNS in order: ", clientNames).AtDebug().WriteToLog()
}
return clients return clients
} }

View File

@ -74,7 +74,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
return sh, nil return sh, nil
} }
func filterIP(ips []net.Address, option dns.IPOption) []net.Address { func filterIP(ips []net.Address, option *dns.IPOption) []net.Address {
filtered := make([]net.Address, 0, len(ips)) filtered := make([]net.Address, 0, len(ips))
for _, ip := range ips { for _, ip := range ips {
if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) { if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) {
@ -95,7 +95,7 @@ func (h *StaticHosts) lookupInternal(domain string) []net.Address {
return ips return ips
} }
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address { func (h *StaticHosts) lookup(domain string, option *dns.IPOption, maxDepth int) []net.Address {
switch addrs := h.lookupInternal(domain); { switch addrs := h.lookupInternal(domain); {
case len(addrs) == 0: // Not recorded in static hosts, return nil case len(addrs) == 0: // Not recorded in static hosts, return nil
return nil return nil
@ -113,6 +113,6 @@ func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) [
} }
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts. // Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address { func (h *StaticHosts) Lookup(domain string, option *dns.IPOption) []net.Address {
return h.lookup(domain, option, 5) return h.lookup(domain, option, 5)
} }

View File

@ -41,7 +41,7 @@ func TestStaticHosts(t *testing.T) {
common.Must(err) common.Must(err)
{ {
ips := hosts.Lookup("example.com", dns.IPOption{ ips := hosts.Lookup("example.com", &dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@ -54,7 +54,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
ips := hosts.Lookup("www.example.cn", dns.IPOption{ ips := hosts.Lookup("www.example.cn", &dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@ -67,7 +67,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
ips := hosts.Lookup("baidu.com", dns.IPOption{ ips := hosts.Lookup("baidu.com", &dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}) })

View File

@ -20,13 +20,14 @@ type Server interface {
// Name of the Client. // Name of the Client.
Name() string Name() string
// QueryIP sends IP queries to its configured server. // QueryIP sends IP queries to its configured server.
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, disableCache bool) ([]net.IP, error) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, cs CacheStrategy) ([]net.IP, error)
} }
// Client is the interface for DNS client. // Client is the interface for DNS client.
type Client struct { type Client struct {
server Server server Server
clientIP net.IP clientIP net.IP
skipFallback bool
domains []string domains []string
expectIPs []*geoip.GeoIPMatcher expectIPs []*geoip.GeoIPMatcher
} }
@ -65,6 +66,7 @@ func NewServer(dest net.Destination, dispatcher routing.Dispatcher) (Server, err
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs. // NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
func NewClient(ctx context.Context, ns *NameServer, clientIP net.IP, container geoip.GeoIPMatcherContainer, matcherInfos *[]DomainMatcherInfo, updateDomainRule func(str.Matcher, int, []DomainMatcherInfo) error) (*Client, error) { func NewClient(ctx context.Context, ns *NameServer, clientIP net.IP, container geoip.GeoIPMatcherContainer, matcherInfos *[]DomainMatcherInfo, updateDomainRule func(str.Matcher, int, []DomainMatcherInfo) error) (*Client, error) {
client := &Client{} client := &Client{}
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now // Create a new server for each client for now
server, err := NewServer(ns.Address.AsDestination(), dispatcher) server, err := NewServer(ns.Address.AsDestination(), dispatcher)
@ -177,9 +179,9 @@ func (c *Client) Name() string {
} }
// QueryIP send DNS query to the name server with the client's IP. // QueryIP send DNS query to the name server with the client's IP.
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) { func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, cs CacheStrategy) ([]net.IP, error) {
ctx, cancel := context.WithTimeout(ctx, 4*time.Second) ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache) ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, cs)
cancel() cancel()
if err != nil { if err != nil {

View File

@ -369,19 +369,21 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOpt
} }
// QueryIP implements Server. // QueryIP implements Server.
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { // nolint: dupl func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) { // nolint: dupl
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if disableCache { if cs == CacheStrategy_Cache_DISABLE {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err}) log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err return ips, err
} }
} }
}
// ipv4 and ipv6 belong to different subscription groups // ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber var sub4, sub6 *pubsub.Subscriber

View File

@ -23,7 +23,7 @@ func TestDOHNameServer(t *testing.T) {
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@ -40,7 +40,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@ -51,7 +51,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{ ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, true) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" { if r := cmp.Diff(ips2, ips); r != "" {

View File

@ -16,11 +16,13 @@ func NewFakeDNSServer() *FakeDNSServer {
return &FakeDNSServer{} return &FakeDNSServer{}
} }
const FakeDNSName = "FakeDNS"
func (FakeDNSServer) Name() string { func (FakeDNSServer) Name() string {
return "FakeDNS" return FakeDNSName
} }
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption, _ bool) ([]net.IP, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption, _ CacheStrategy) ([]net.IP, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
f.fakeDNSEngine = fd f.fakeDNSEngine = fd

View File

@ -14,7 +14,7 @@ type LocalNameServer struct {
} }
// QueryIP implements Server. // QueryIP implements Server.
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) ([]net.IP, error) { func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ CacheStrategy) ([]net.IP, error) {
var ips []net.IP var ips []net.IP
var err error var err error

View File

@ -17,7 +17,7 @@ func TestLocalNameServer(t *testing.T) {
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {

View File

@ -268,19 +268,21 @@ func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOp
} }
// QueryIP is called from dns.Server->queryIPTimeout // QueryIP is called from dns.Server->queryIPTimeout
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if disableCache { if cs == CacheStrategy_Cache_DISABLE {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err}) log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err return ips, err
} }
} }
}
// ipv4 and ipv6 belong to different subscription groups // ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber var sub4, sub6 *pubsub.Subscriber

View File

@ -23,7 +23,7 @@ func TestQUICNameServer(t *testing.T) {
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@ -40,7 +40,7 @@ func TestQUICNameServerWithCache(t *testing.T) {
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@ -51,7 +51,7 @@ func TestQUICNameServerWithCache(t *testing.T) {
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{ ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, true) }, CacheStrategy_Cache_ALL)
cancel() cancel()
common.Must(err) common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" { if r := cmp.Diff(ips2, ips); r != "" {

View File

@ -245,19 +245,21 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.I
} }
// QueryIP implements Server. // QueryIP implements Server.
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if disableCache { if cs == CacheStrategy_Cache_DISABLE {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err}) log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err return ips, err
} }
} }
}
// ipv4 and ipv6 belong to different subscription groups // ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber var sub4, sub6 *pubsub.Subscriber

16
app/dns/options.go Normal file
View File

@ -0,0 +1,16 @@
package dns
import "github.com/xtls/xray-core/features/dns"
func isIPQuery(o *dns.IPOption) bool {
return o.IPv4Enable || o.IPv6Enable
}
func canQueryOnClient(o *dns.IPOption, c *Client) bool {
isIPClient := !(c.Name() == FakeDNSName)
return isIPClient && isIPQuery(o)
}
func isQuery(o *dns.IPOption) bool {
return !(o.IPv4Enable || o.IPv6Enable || o.FakeEnable)
}

View File

@ -14,6 +14,12 @@ type IPOption struct {
FakeEnable bool FakeEnable bool
} }
func (p *IPOption) Copy() *IPOption {
return &IPOption{p.IPv4Enable, p.IPv6Enable, p.FakeEnable}
}
type Option func(dopt *IPOption) *IPOption
// Client is a Xray feature for querying DNS information. // Client is a Xray feature for querying DNS information.
// //
// xray:api:stable // xray:api:stable
@ -22,6 +28,9 @@ type Client interface {
// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses. // LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
LookupIP(domain string) ([]net.IP, error) LookupIP(domain string) ([]net.IP, error)
// LookupOptions query IP address for domain with *IPOption.
LookupOptions(domain string, opt ...Option) ([]net.IP, error)
} }
// IPv4Lookup is an optional feature for querying IPv4 addresses only. // IPv4Lookup is an optional feature for querying IPv4 addresses only.
@ -38,20 +47,6 @@ type IPv6Lookup interface {
LookupIPv6(domain string) ([]net.IP, error) LookupIPv6(domain string) ([]net.IP, error)
} }
// ClientWithIPOption is an optional feature for querying DNS information.
//
// xray:api:beta
type ClientWithIPOption interface {
// GetIPOption returns IPOption for the DNS client.
GetIPOption() *IPOption
// SetQueryOption sets IPv4Enable and IPv6Enable for the DNS client.
SetQueryOption(isIPv4Enable, isIPv6Enable bool)
// SetFakeDNSOption sets FakeEnable option for DNS client.
SetFakeDNSOption(isFakeEnable bool)
}
// ClientType returns the type of Client interface. Can be used for implementing common.HasType. // ClientType returns the type of Client interface. Can be used for implementing common.HasType.
// //
// xray:api:beta // xray:api:beta
@ -78,3 +73,35 @@ func RCodeFromError(err error) uint16 {
} }
return 0 return 0
} }
var (
LookupIPv4Only = func(d *IPOption) *IPOption {
d.IPv4Enable = true
d.IPv6Enable = false
return d
}
LookupIPv6Only = func(d *IPOption) *IPOption {
d.IPv4Enable = false
d.IPv6Enable = true
return d
}
LookupIP = func(d *IPOption) *IPOption {
d.IPv4Enable = true
d.IPv6Enable = true
return d
}
LookupFake = func(d *IPOption) *IPOption {
d.FakeEnable = true
return d
}
LookupNoFake = func(d *IPOption) *IPOption {
d.FakeEnable = false
return d
}
LookupAll = func(d *IPOption) *IPOption {
LookupIP(d)
LookupFake(d)
return d
}
)

View File

@ -38,6 +38,11 @@ func (*Client) LookupIP(host string) ([]net.IP, error) {
return parsedIPs, nil return parsedIPs, nil
} }
// LookupOptions implements Client.
func (c *Client) LookupOptions(host string, _ ...dns.Option) ([]net.IP, error) {
return c.LookupIP(host)
}
// LookupIPv4 implements IPv4Lookup. // LookupIPv4 implements IPv4Lookup.
func (c *Client) LookupIPv4(host string) ([]net.IP, error) { func (c *Client) LookupIPv4(host string) ([]net.IP, error) {
ips, err := c.LookupIP(host) ips, err := c.LookupIP(host)

View File

@ -26,40 +26,12 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
} }
if domain := ctx.GetTargetDomain(); len(domain) != 0 { if domain := ctx.GetTargetDomain(); len(domain) != 0 {
var lookupFunc func(string) ([]net.IP, error) = ctx.dnsClient.LookupIP ips, err := ctx.dnsClient.LookupIP(domain)
ipOption := &dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}
if c, ok := ctx.dnsClient.(dns.ClientWithIPOption); ok {
ipOption = c.GetIPOption()
c.SetFakeDNSOption(false) // Skip FakeDNS.
} else {
newError("ctx.dnsClient doesn't implement ClientWithIPOption").AtDebug().WriteToLog()
}
switch {
case ipOption.IPv4Enable && !ipOption.IPv6Enable:
if lookupIPv4, ok := ctx.dnsClient.(dns.IPv4Lookup); ok {
lookupFunc = lookupIPv4.LookupIPv4
} else {
newError("ctx.dnsClient doesn't implement IPv4Lookup. Use LookupIP instead.").AtDebug().WriteToLog()
}
case !ipOption.IPv4Enable && ipOption.IPv6Enable:
if lookupIPv6, ok := ctx.dnsClient.(dns.IPv6Lookup); ok {
lookupFunc = lookupIPv6.LookupIPv6
} else {
newError("ctx.dnsClient doesn't implement IPv6Lookup. Use LookupIP instead.").AtDebug().WriteToLog()
}
}
ips, err := lookupFunc(domain)
if err == nil { if err == nil {
ctx.resolvedIPs = ips ctx.resolvedIPs = ips
return ips return ips
} }
newError("resolve ip for ", domain).Base(err).WriteToLog() newError("failed to resolve ip for ", domain).Base(err).WriteToLog()
} }
return nil return nil

View File

@ -18,6 +18,7 @@ type NameServerConfig struct {
Address *Address Address *Address
ClientIP *Address ClientIP *Address
Port uint16 Port uint16
SkipFallback bool
Domains []string Domains []string
ExpectIPs StringList ExpectIPs StringList
} }
@ -33,6 +34,7 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
Address *Address `json:"address"` Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"` ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"` Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains []string `json:"domains"` Domains []string `json:"domains"`
ExpectIPs StringList `json:"expectIps"` ExpectIPs StringList `json:"expectIps"`
} }
@ -40,6 +42,7 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
c.Address = advanced.Address c.Address = advanced.Address
c.ClientIP = advanced.ClientIP c.ClientIP = advanced.ClientIP
c.Port = advanced.Port c.Port = advanced.Port
c.SkipFallback = advanced.SkipFallback
c.Domains = advanced.Domains c.Domains = advanced.Domains
c.ExpectIPs = advanced.ExpectIPs c.ExpectIPs = advanced.ExpectIPs
return nil return nil
@ -93,6 +96,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
Port: uint32(c.Port), Port: uint32(c.Port),
}, },
ClientIp: myClientIP, ClientIp: myClientIP,
SkipFallback: c.SkipFallback,
PrioritizedDomain: domains, PrioritizedDomain: domains,
Geoip: geoipList, Geoip: geoipList,
OriginalRules: originalRules, OriginalRules: originalRules,
@ -106,7 +110,9 @@ type DNSConfig struct {
ClientIP *Address `json:"clientIp"` ClientIP *Address `json:"clientIp"`
Tag string `json:"tag"` Tag string `json:"tag"`
QueryStrategy string `json:"queryStrategy"` QueryStrategy string `json:"queryStrategy"`
CacheStrategy string `json:"cacheStrategy"`
DisableCache bool `json:"disableCache"` DisableCache bool `json:"disableCache"`
DisableFallback bool `json:"disableFallback"`
} }
func getHostMapping(addr *Address) *dns.Config_HostMapping { func getHostMapping(addr *Address) *dns.Config_HostMapping {
@ -125,7 +131,12 @@ func getHostMapping(addr *Address) *dns.Config_HostMapping {
func (c *DNSConfig) Build() (*dns.Config, error) { func (c *DNSConfig) Build() (*dns.Config, error) {
config := &dns.Config{ config := &dns.Config{
Tag: c.Tag, Tag: c.Tag,
DisableCache: c.DisableCache, CacheStrategy: dns.CacheStrategy_Cache_ALL,
DisableFallback: c.DisableFallback,
}
if c.DisableCache {
config.CacheStrategy = dns.CacheStrategy_Cache_DISABLE
} }
if c.ClientIP != nil { if c.ClientIP != nil {
@ -145,6 +156,15 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
config.QueryStrategy = dns.QueryStrategy_USE_IP6 config.QueryStrategy = dns.QueryStrategy_USE_IP6
} }
switch strings.ToLower(c.CacheStrategy) {
case "noerror":
config.CacheStrategy = dns.CacheStrategy_Cache_NOERROR
case "all":
config.CacheStrategy = dns.CacheStrategy_Cache_ALL
case "disable", "none":
config.CacheStrategy = dns.CacheStrategy_Cache_DISABLE
}
for _, server := range c.Servers { for _, server := range c.Servers {
ns, err := server.Build() ns, err := server.Build()
if err != nil { if err != nil {

View File

@ -70,6 +70,7 @@ func TestDNSConfigParsing(t *testing.T) {
"address": "8.8.8.8", "address": "8.8.8.8",
"clientIp": "10.0.0.1", "clientIp": "10.0.0.1",
"port": 5353, "port": 5353,
"skipFallback": true,
"domains": ["domain:example.com"] "domains": ["domain:example.com"]
}], }],
"hosts": { "hosts": {
@ -81,7 +82,8 @@ func TestDNSConfigParsing(t *testing.T) {
}, },
"clientIp": "10.0.0.1", "clientIp": "10.0.0.1",
"queryStrategy": "UseIPv4", "queryStrategy": "UseIPv4",
"disableCache": true "disableCache": true,
"disableFallback": true
}`, }`,
Parser: parserCreator(), Parser: parserCreator(),
Output: &dns.Config{ Output: &dns.Config{
@ -97,6 +99,7 @@ func TestDNSConfigParsing(t *testing.T) {
Port: 5353, Port: 5353,
}, },
ClientIp: []byte{10, 0, 0, 1}, ClientIp: []byte{10, 0, 0, 1},
SkipFallback: true,
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*domain.Domain{
{ {
Type: domain.MatchingType_Subdomain, Type: domain.MatchingType_Subdomain,
@ -140,7 +143,8 @@ func TestDNSConfigParsing(t *testing.T) {
}, },
ClientIp: []byte{10, 0, 0, 1}, ClientIp: []byte{10, 0, 0, 1},
QueryStrategy: dns.QueryStrategy_USE_IP4, QueryStrategy: dns.QueryStrategy_USE_IP4,
DisableCache: true, CacheStrategy: dns.CacheStrategy_Cache_DISABLE,
DisableFallback: true,
}, },
}, },
}) })

View File

@ -37,8 +37,6 @@ type ownLinkVerifier interface {
type Handler struct { type Handler struct {
client dns.Client client dns.Client
ipv4Lookup dns.IPv4Lookup
ipv6Lookup dns.IPv6Lookup
ownLinkVerifier ownLinkVerifier ownLinkVerifier ownLinkVerifier
server net.Destination server net.Destination
} }
@ -46,18 +44,6 @@ type Handler struct {
func (h *Handler) Init(config *Config, dnsClient dns.Client) error { func (h *Handler) Init(config *Config, dnsClient dns.Client) error {
h.client = dnsClient h.client = dnsClient
if ipv4lookup, ok := dnsClient.(dns.IPv4Lookup); ok {
h.ipv4Lookup = ipv4lookup
} else {
return newError("dns.Client doesn't implement IPv4Lookup")
}
if ipv6lookup, ok := dnsClient.(dns.IPv6Lookup); ok {
h.ipv6Lookup = ipv6lookup
} else {
return newError("dns.Client doesn't implement IPv6Lookup")
}
if v, ok := dnsClient.(ownLinkVerifier); ok { if v, ok := dnsClient.(ownLinkVerifier); ok {
h.ownLinkVerifier = v h.ownLinkVerifier = v
} }
@ -213,21 +199,16 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
var err error var err error
var ttl uint32 = 600 var ttl uint32 = 600
var opt dns.Option
// Do NOT skip FakeDNS
if c, ok := h.client.(dns.ClientWithIPOption); ok {
c.SetFakeDNSOption(true)
} else {
newError("dns.Client doesn't implement ClientWithIPOption")
}
switch qType { switch qType {
case dnsmessage.TypeA: case dnsmessage.TypeA:
ips, err = h.ipv4Lookup.LookupIPv4(domain) opt = dns.LookupIPv4Only
case dnsmessage.TypeAAAA: case dnsmessage.TypeAAAA:
ips, err = h.ipv6Lookup.LookupIPv6(domain) opt = dns.LookupIPv6Only
} }
ips, err = h.client.LookupOptions(domain, opt, dns.LookupFake)
rcode := dns.RCodeFromError(err) rcode := dns.RCodeFromError(err)
if rcode == 0 && len(ips) == 0 && err != dns.ErrEmptyResponse { if rcode == 0 && len(ips) == 0 && err != dns.ErrEmptyResponse {
newError("ip query").Base(err).WriteToLog() newError("ip query").Base(err).WriteToLog()

View File

@ -59,24 +59,14 @@ func (h *Handler) policy() policy.Session {
} }
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address { func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
if c, ok := h.dns.(dns.ClientWithIPOption); ok { var opt dns.Option
c.SetFakeDNSOption(false) // Skip FakeDNS
} else {
newError("DNS client doesn't implement ClientWithIPOption")
}
var lookupFunc func(string) ([]net.IP, error) = h.dns.LookupIP
if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) { if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) {
if lookupIPv4, ok := h.dns.(dns.IPv4Lookup); ok { opt = dns.LookupIPv4Only
lookupFunc = lookupIPv4.LookupIPv4
}
} else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) { } else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) {
if lookupIPv6, ok := h.dns.(dns.IPv6Lookup); ok { opt = dns.LookupIPv6Only
lookupFunc = lookupIPv6.LookupIPv6
}
} }
ips, err := lookupFunc(domain) ips, err := h.dns.LookupOptions(domain, opt, dns.LookupNoFake)
if err != nil { if err != nil {
newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx)) newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx))
} }

View File

@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT. // Code generated by MockGen. DO NOT EDIT.
// Source: github.com/xray/xray-core/v4/features/dns (interfaces: Client) // Source: github.com/xtls/xray-core/features/dns (interfaces: Client)
// Package mocks is a generated GoMock package. // Package mocks is a generated GoMock package.
package mocks package mocks
@ -9,6 +9,7 @@ import (
reflect "reflect" reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
dns "github.com/xtls/xray-core/features/dns"
) )
// DNSClient is a mock of Client interface. // DNSClient is a mock of Client interface.
@ -63,6 +64,26 @@ func (mr *DNSClientMockRecorder) LookupIP(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0)
} }
// LookupOptions mocks base method.
func (m *DNSClient) LookupOptions(arg0 string, arg1 ...dns.Option) ([]net.IP, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "LookupOptions", varargs...)
ret0, _ := ret[0].([]net.IP)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LookupOptions indicates an expected call of LookupOptions.
func (mr *DNSClientMockRecorder) LookupOptions(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupOptions", reflect.TypeOf((*DNSClient)(nil).LookupOptions), varargs...)
}
// Start mocks base method. // Start mocks base method.
func (m *DNSClient) Start() error { func (m *DNSClient) Start() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -5,34 +5,35 @@
package mocks package mocks
import ( import (
gomock "github.com/golang/mock/gomock"
reflect "reflect" reflect "reflect"
gomock "github.com/golang/mock/gomock"
) )
// Reader is a mock of Reader interface // Reader is a mock of Reader interface.
type Reader struct { type Reader struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *ReaderMockRecorder recorder *ReaderMockRecorder
} }
// ReaderMockRecorder is the mock recorder for Reader // ReaderMockRecorder is the mock recorder for Reader.
type ReaderMockRecorder struct { type ReaderMockRecorder struct {
mock *Reader mock *Reader
} }
// NewReader creates a new mock instance // NewReader creates a new mock instance.
func NewReader(ctrl *gomock.Controller) *Reader { func NewReader(ctrl *gomock.Controller) *Reader {
mock := &Reader{ctrl: ctrl} mock := &Reader{ctrl: ctrl}
mock.recorder = &ReaderMockRecorder{mock} mock.recorder = &ReaderMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *Reader) EXPECT() *ReaderMockRecorder { func (m *Reader) EXPECT() *ReaderMockRecorder {
return m.recorder return m.recorder
} }
// Read mocks base method // Read mocks base method.
func (m *Reader) Read(arg0 []byte) (int, error) { func (m *Reader) Read(arg0 []byte) (int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Read", arg0) ret := m.ctrl.Call(m, "Read", arg0)
@ -41,36 +42,36 @@ func (m *Reader) Read(arg0 []byte) (int, error) {
return ret0, ret1 return ret0, ret1
} }
// Read indicates an expected call of Read // Read indicates an expected call of Read.
func (mr *ReaderMockRecorder) Read(arg0 interface{}) *gomock.Call { func (mr *ReaderMockRecorder) Read(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*Reader)(nil).Read), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*Reader)(nil).Read), arg0)
} }
// Writer is a mock of Writer interface // Writer is a mock of Writer interface.
type Writer struct { type Writer struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *WriterMockRecorder recorder *WriterMockRecorder
} }
// WriterMockRecorder is the mock recorder for Writer // WriterMockRecorder is the mock recorder for Writer.
type WriterMockRecorder struct { type WriterMockRecorder struct {
mock *Writer mock *Writer
} }
// NewWriter creates a new mock instance // NewWriter creates a new mock instance.
func NewWriter(ctrl *gomock.Controller) *Writer { func NewWriter(ctrl *gomock.Controller) *Writer {
mock := &Writer{ctrl: ctrl} mock := &Writer{ctrl: ctrl}
mock.recorder = &WriterMockRecorder{mock} mock.recorder = &WriterMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *Writer) EXPECT() *WriterMockRecorder { func (m *Writer) EXPECT() *WriterMockRecorder {
return m.recorder return m.recorder
} }
// Write mocks base method // Write mocks base method.
func (m *Writer) Write(arg0 []byte) (int, error) { func (m *Writer) Write(arg0 []byte) (int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Write", arg0) ret := m.ctrl.Call(m, "Write", arg0)
@ -79,7 +80,7 @@ func (m *Writer) Write(arg0 []byte) (int, error) {
return ret0, ret1 return ret0, ret1
} }
// Write indicates an expected call of Write // Write indicates an expected call of Write.
func (mr *WriterMockRecorder) Write(arg0 interface{}) *gomock.Call { func (mr *WriterMockRecorder) Write(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*Writer)(nil).Write), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*Writer)(nil).Write), arg0)

View File

@ -5,41 +5,42 @@
package mocks package mocks
import ( import (
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
log "github.com/xtls/xray-core/common/log" log "github.com/xtls/xray-core/common/log"
reflect "reflect"
) )
// LogHandler is a mock of Handler interface // LogHandler is a mock of Handler interface.
type LogHandler struct { type LogHandler struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *LogHandlerMockRecorder recorder *LogHandlerMockRecorder
} }
// LogHandlerMockRecorder is the mock recorder for LogHandler // LogHandlerMockRecorder is the mock recorder for LogHandler.
type LogHandlerMockRecorder struct { type LogHandlerMockRecorder struct {
mock *LogHandler mock *LogHandler
} }
// NewLogHandler creates a new mock instance // NewLogHandler creates a new mock instance.
func NewLogHandler(ctrl *gomock.Controller) *LogHandler { func NewLogHandler(ctrl *gomock.Controller) *LogHandler {
mock := &LogHandler{ctrl: ctrl} mock := &LogHandler{ctrl: ctrl}
mock.recorder = &LogHandlerMockRecorder{mock} mock.recorder = &LogHandlerMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *LogHandler) EXPECT() *LogHandlerMockRecorder { func (m *LogHandler) EXPECT() *LogHandlerMockRecorder {
return m.recorder return m.recorder
} }
// Handle mocks base method // Handle mocks base method.
func (m *LogHandler) Handle(arg0 log.Message) { func (m *LogHandler) Handle(arg0 log.Message) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "Handle", arg0) m.ctrl.Call(m, "Handle", arg0)
} }
// Handle indicates an expected call of Handle // Handle indicates an expected call of Handle.
func (mr *LogHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call { func (mr *LogHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*LogHandler)(nil).Handle), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*LogHandler)(nil).Handle), arg0)

View File

@ -5,35 +5,36 @@
package mocks package mocks
import ( import (
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
mux "github.com/xtls/xray-core/common/mux" mux "github.com/xtls/xray-core/common/mux"
reflect "reflect"
) )
// MuxClientWorkerFactory is a mock of ClientWorkerFactory interface // MuxClientWorkerFactory is a mock of ClientWorkerFactory interface.
type MuxClientWorkerFactory struct { type MuxClientWorkerFactory struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MuxClientWorkerFactoryMockRecorder recorder *MuxClientWorkerFactoryMockRecorder
} }
// MuxClientWorkerFactoryMockRecorder is the mock recorder for MuxClientWorkerFactory // MuxClientWorkerFactoryMockRecorder is the mock recorder for MuxClientWorkerFactory.
type MuxClientWorkerFactoryMockRecorder struct { type MuxClientWorkerFactoryMockRecorder struct {
mock *MuxClientWorkerFactory mock *MuxClientWorkerFactory
} }
// NewMuxClientWorkerFactory creates a new mock instance // NewMuxClientWorkerFactory creates a new mock instance.
func NewMuxClientWorkerFactory(ctrl *gomock.Controller) *MuxClientWorkerFactory { func NewMuxClientWorkerFactory(ctrl *gomock.Controller) *MuxClientWorkerFactory {
mock := &MuxClientWorkerFactory{ctrl: ctrl} mock := &MuxClientWorkerFactory{ctrl: ctrl}
mock.recorder = &MuxClientWorkerFactoryMockRecorder{mock} mock.recorder = &MuxClientWorkerFactoryMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *MuxClientWorkerFactory) EXPECT() *MuxClientWorkerFactoryMockRecorder { func (m *MuxClientWorkerFactory) EXPECT() *MuxClientWorkerFactoryMockRecorder {
return m.recorder return m.recorder
} }
// Create mocks base method // Create mocks base method.
func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) { func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Create") ret := m.ctrl.Call(m, "Create")
@ -42,7 +43,7 @@ func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) {
return ret0, ret1 return ret0, ret1
} }
// Create indicates an expected call of Create // Create indicates an expected call of Create.
func (mr *MuxClientWorkerFactoryMockRecorder) Create() *gomock.Call { func (mr *MuxClientWorkerFactoryMockRecorder) Create() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MuxClientWorkerFactory)(nil).Create)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MuxClientWorkerFactory)(nil).Create))

View File

@ -6,35 +6,36 @@ package mocks
import ( import (
context "context" context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
outbound "github.com/xtls/xray-core/features/outbound" outbound "github.com/xtls/xray-core/features/outbound"
reflect "reflect"
) )
// OutboundManager is a mock of Manager interface // OutboundManager is a mock of Manager interface.
type OutboundManager struct { type OutboundManager struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *OutboundManagerMockRecorder recorder *OutboundManagerMockRecorder
} }
// OutboundManagerMockRecorder is the mock recorder for OutboundManager // OutboundManagerMockRecorder is the mock recorder for OutboundManager.
type OutboundManagerMockRecorder struct { type OutboundManagerMockRecorder struct {
mock *OutboundManager mock *OutboundManager
} }
// NewOutboundManager creates a new mock instance // NewOutboundManager creates a new mock instance.
func NewOutboundManager(ctrl *gomock.Controller) *OutboundManager { func NewOutboundManager(ctrl *gomock.Controller) *OutboundManager {
mock := &OutboundManager{ctrl: ctrl} mock := &OutboundManager{ctrl: ctrl}
mock.recorder = &OutboundManagerMockRecorder{mock} mock.recorder = &OutboundManagerMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *OutboundManager) EXPECT() *OutboundManagerMockRecorder { func (m *OutboundManager) EXPECT() *OutboundManagerMockRecorder {
return m.recorder return m.recorder
} }
// AddHandler mocks base method // AddHandler mocks base method.
func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler) error { func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddHandler", arg0, arg1) ret := m.ctrl.Call(m, "AddHandler", arg0, arg1)
@ -42,13 +43,13 @@ func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler
return ret0 return ret0
} }
// AddHandler indicates an expected call of AddHandler // AddHandler indicates an expected call of AddHandler.
func (mr *OutboundManagerMockRecorder) AddHandler(arg0, arg1 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) AddHandler(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHandler", reflect.TypeOf((*OutboundManager)(nil).AddHandler), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHandler", reflect.TypeOf((*OutboundManager)(nil).AddHandler), arg0, arg1)
} }
// Close mocks base method // Close mocks base method.
func (m *OutboundManager) Close() error { func (m *OutboundManager) Close() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close") ret := m.ctrl.Call(m, "Close")
@ -56,13 +57,13 @@ func (m *OutboundManager) Close() error {
return ret0 return ret0
} }
// Close indicates an expected call of Close // Close indicates an expected call of Close.
func (mr *OutboundManagerMockRecorder) Close() *gomock.Call { func (mr *OutboundManagerMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*OutboundManager)(nil).Close)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*OutboundManager)(nil).Close))
} }
// GetDefaultHandler mocks base method // GetDefaultHandler mocks base method.
func (m *OutboundManager) GetDefaultHandler() outbound.Handler { func (m *OutboundManager) GetDefaultHandler() outbound.Handler {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDefaultHandler") ret := m.ctrl.Call(m, "GetDefaultHandler")
@ -70,13 +71,13 @@ func (m *OutboundManager) GetDefaultHandler() outbound.Handler {
return ret0 return ret0
} }
// GetDefaultHandler indicates an expected call of GetDefaultHandler // GetDefaultHandler indicates an expected call of GetDefaultHandler.
func (mr *OutboundManagerMockRecorder) GetDefaultHandler() *gomock.Call { func (mr *OutboundManagerMockRecorder) GetDefaultHandler() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultHandler", reflect.TypeOf((*OutboundManager)(nil).GetDefaultHandler)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultHandler", reflect.TypeOf((*OutboundManager)(nil).GetDefaultHandler))
} }
// GetHandler mocks base method // GetHandler mocks base method.
func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler { func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetHandler", arg0) ret := m.ctrl.Call(m, "GetHandler", arg0)
@ -84,13 +85,13 @@ func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler {
return ret0 return ret0
} }
// GetHandler indicates an expected call of GetHandler // GetHandler indicates an expected call of GetHandler.
func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0)
} }
// RemoveHandler mocks base method // RemoveHandler mocks base method.
func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error { func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RemoveHandler", arg0, arg1) ret := m.ctrl.Call(m, "RemoveHandler", arg0, arg1)
@ -98,13 +99,13 @@ func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error
return ret0 return ret0
} }
// RemoveHandler indicates an expected call of RemoveHandler // RemoveHandler indicates an expected call of RemoveHandler.
func (mr *OutboundManagerMockRecorder) RemoveHandler(arg0, arg1 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) RemoveHandler(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHandler", reflect.TypeOf((*OutboundManager)(nil).RemoveHandler), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHandler", reflect.TypeOf((*OutboundManager)(nil).RemoveHandler), arg0, arg1)
} }
// Start mocks base method // Start mocks base method.
func (m *OutboundManager) Start() error { func (m *OutboundManager) Start() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Start") ret := m.ctrl.Call(m, "Start")
@ -112,13 +113,13 @@ func (m *OutboundManager) Start() error {
return ret0 return ret0
} }
// Start indicates an expected call of Start // Start indicates an expected call of Start.
func (mr *OutboundManagerMockRecorder) Start() *gomock.Call { func (mr *OutboundManagerMockRecorder) Start() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*OutboundManager)(nil).Start)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*OutboundManager)(nil).Start))
} }
// Type mocks base method // Type mocks base method.
func (m *OutboundManager) Type() interface{} { func (m *OutboundManager) Type() interface{} {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Type") ret := m.ctrl.Call(m, "Type")
@ -126,36 +127,36 @@ func (m *OutboundManager) Type() interface{} {
return ret0 return ret0
} }
// Type indicates an expected call of Type // Type indicates an expected call of Type.
func (mr *OutboundManagerMockRecorder) Type() *gomock.Call { func (mr *OutboundManagerMockRecorder) Type() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*OutboundManager)(nil).Type)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*OutboundManager)(nil).Type))
} }
// OutboundHandlerSelector is a mock of HandlerSelector interface // OutboundHandlerSelector is a mock of HandlerSelector interface.
type OutboundHandlerSelector struct { type OutboundHandlerSelector struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *OutboundHandlerSelectorMockRecorder recorder *OutboundHandlerSelectorMockRecorder
} }
// OutboundHandlerSelectorMockRecorder is the mock recorder for OutboundHandlerSelector // OutboundHandlerSelectorMockRecorder is the mock recorder for OutboundHandlerSelector.
type OutboundHandlerSelectorMockRecorder struct { type OutboundHandlerSelectorMockRecorder struct {
mock *OutboundHandlerSelector mock *OutboundHandlerSelector
} }
// NewOutboundHandlerSelector creates a new mock instance // NewOutboundHandlerSelector creates a new mock instance.
func NewOutboundHandlerSelector(ctrl *gomock.Controller) *OutboundHandlerSelector { func NewOutboundHandlerSelector(ctrl *gomock.Controller) *OutboundHandlerSelector {
mock := &OutboundHandlerSelector{ctrl: ctrl} mock := &OutboundHandlerSelector{ctrl: ctrl}
mock.recorder = &OutboundHandlerSelectorMockRecorder{mock} mock.recorder = &OutboundHandlerSelectorMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *OutboundHandlerSelector) EXPECT() *OutboundHandlerSelectorMockRecorder { func (m *OutboundHandlerSelector) EXPECT() *OutboundHandlerSelectorMockRecorder {
return m.recorder return m.recorder
} }
// Select mocks base method // Select mocks base method.
func (m *OutboundHandlerSelector) Select(arg0 []string) []string { func (m *OutboundHandlerSelector) Select(arg0 []string) []string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Select", arg0) ret := m.ctrl.Call(m, "Select", arg0)
@ -163,7 +164,7 @@ func (m *OutboundHandlerSelector) Select(arg0 []string) []string {
return ret0 return ret0
} }
// Select indicates an expected call of Select // Select indicates an expected call of Select.
func (mr *OutboundHandlerSelectorMockRecorder) Select(arg0 interface{}) *gomock.Call { func (mr *OutboundHandlerSelectorMockRecorder) Select(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*OutboundHandlerSelector)(nil).Select), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*OutboundHandlerSelector)(nil).Select), arg0)

View File

@ -6,38 +6,39 @@ package mocks
import ( import (
context "context" context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
net "github.com/xtls/xray-core/common/net" net "github.com/xtls/xray-core/common/net"
routing "github.com/xtls/xray-core/features/routing" routing "github.com/xtls/xray-core/features/routing"
transport "github.com/xtls/xray-core/transport" transport "github.com/xtls/xray-core/transport"
internet "github.com/xtls/xray-core/transport/internet" internet "github.com/xtls/xray-core/transport/internet"
reflect "reflect"
) )
// ProxyInbound is a mock of Inbound interface // ProxyInbound is a mock of Inbound interface.
type ProxyInbound struct { type ProxyInbound struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *ProxyInboundMockRecorder recorder *ProxyInboundMockRecorder
} }
// ProxyInboundMockRecorder is the mock recorder for ProxyInbound // ProxyInboundMockRecorder is the mock recorder for ProxyInbound.
type ProxyInboundMockRecorder struct { type ProxyInboundMockRecorder struct {
mock *ProxyInbound mock *ProxyInbound
} }
// NewProxyInbound creates a new mock instance // NewProxyInbound creates a new mock instance.
func NewProxyInbound(ctrl *gomock.Controller) *ProxyInbound { func NewProxyInbound(ctrl *gomock.Controller) *ProxyInbound {
mock := &ProxyInbound{ctrl: ctrl} mock := &ProxyInbound{ctrl: ctrl}
mock.recorder = &ProxyInboundMockRecorder{mock} mock.recorder = &ProxyInboundMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *ProxyInbound) EXPECT() *ProxyInboundMockRecorder { func (m *ProxyInbound) EXPECT() *ProxyInboundMockRecorder {
return m.recorder return m.recorder
} }
// Network mocks base method // Network mocks base method.
func (m *ProxyInbound) Network() []net.Network { func (m *ProxyInbound) Network() []net.Network {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Network") ret := m.ctrl.Call(m, "Network")
@ -45,13 +46,13 @@ func (m *ProxyInbound) Network() []net.Network {
return ret0 return ret0
} }
// Network indicates an expected call of Network // Network indicates an expected call of Network.
func (mr *ProxyInboundMockRecorder) Network() *gomock.Call { func (mr *ProxyInboundMockRecorder) Network() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Network", reflect.TypeOf((*ProxyInbound)(nil).Network)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Network", reflect.TypeOf((*ProxyInbound)(nil).Network))
} }
// Process mocks base method // Process mocks base method.
func (m *ProxyInbound) Process(arg0 context.Context, arg1 net.Network, arg2 internet.Connection, arg3 routing.Dispatcher) error { func (m *ProxyInbound) Process(arg0 context.Context, arg1 net.Network, arg2 internet.Connection, arg3 routing.Dispatcher) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Process", arg0, arg1, arg2, arg3) ret := m.ctrl.Call(m, "Process", arg0, arg1, arg2, arg3)
@ -59,36 +60,36 @@ func (m *ProxyInbound) Process(arg0 context.Context, arg1 net.Network, arg2 inte
return ret0 return ret0
} }
// Process indicates an expected call of Process // Process indicates an expected call of Process.
func (mr *ProxyInboundMockRecorder) Process(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { func (mr *ProxyInboundMockRecorder) Process(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Process", reflect.TypeOf((*ProxyInbound)(nil).Process), arg0, arg1, arg2, arg3) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Process", reflect.TypeOf((*ProxyInbound)(nil).Process), arg0, arg1, arg2, arg3)
} }
// ProxyOutbound is a mock of Outbound interface // ProxyOutbound is a mock of Outbound interface.
type ProxyOutbound struct { type ProxyOutbound struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *ProxyOutboundMockRecorder recorder *ProxyOutboundMockRecorder
} }
// ProxyOutboundMockRecorder is the mock recorder for ProxyOutbound // ProxyOutboundMockRecorder is the mock recorder for ProxyOutbound.
type ProxyOutboundMockRecorder struct { type ProxyOutboundMockRecorder struct {
mock *ProxyOutbound mock *ProxyOutbound
} }
// NewProxyOutbound creates a new mock instance // NewProxyOutbound creates a new mock instance.
func NewProxyOutbound(ctrl *gomock.Controller) *ProxyOutbound { func NewProxyOutbound(ctrl *gomock.Controller) *ProxyOutbound {
mock := &ProxyOutbound{ctrl: ctrl} mock := &ProxyOutbound{ctrl: ctrl}
mock.recorder = &ProxyOutboundMockRecorder{mock} mock.recorder = &ProxyOutboundMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use // EXPECT returns an object that allows the caller to indicate expected use.
func (m *ProxyOutbound) EXPECT() *ProxyOutboundMockRecorder { func (m *ProxyOutbound) EXPECT() *ProxyOutboundMockRecorder {
return m.recorder return m.recorder
} }
// Process mocks base method // Process mocks base method.
func (m *ProxyOutbound) Process(arg0 context.Context, arg1 *transport.Link, arg2 internet.Dialer) error { func (m *ProxyOutbound) Process(arg0 context.Context, arg1 *transport.Link, arg2 internet.Dialer) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Process", arg0, arg1, arg2) ret := m.ctrl.Call(m, "Process", arg0, arg1, arg2)
@ -96,7 +97,7 @@ func (m *ProxyOutbound) Process(arg0 context.Context, arg1 *transport.Link, arg2
return ret0 return ret0
} }
// Process indicates an expected call of Process // Process indicates an expected call of Process.
func (mr *ProxyOutboundMockRecorder) Process(arg0, arg1, arg2 interface{}) *gomock.Call { func (mr *ProxyOutboundMockRecorder) Process(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Process", reflect.TypeOf((*ProxyOutbound)(nil).Process), arg0, arg1, arg2) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Process", reflect.TypeOf((*ProxyOutbound)(nil).Process), arg0, arg1, arg2)

View File

@ -63,30 +63,20 @@ func (d *DefaultSystemDialer) lookupIP(domain string, strategy DomainStrategy, l
return nil, nil return nil, nil
} }
if c, ok := d.dns.(dns.ClientWithIPOption); ok { var opt dns.Option
c.SetFakeDNSOption(false) // Skip FakeDNS
} else {
newError("DNS client doesn't implement ClientWithIPOption")
}
var lookupFunc func(string) ([]net.IP, error) = d.dns.LookupIP
switch { switch {
case strategy == DomainStrategy_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()): case strategy == DomainStrategy_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()):
if lookupIPv4, ok := d.dns.(dns.IPv4Lookup); ok { opt = dns.LookupIPv4Only
lookupFunc = lookupIPv4.LookupIPv4
}
case strategy == DomainStrategy_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()): case strategy == DomainStrategy_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()):
if lookupIPv6, ok := d.dns.(dns.IPv6Lookup); ok { opt = dns.LookupIPv6Only
lookupFunc = lookupIPv6.LookupIPv6
}
case strategy == DomainStrategy_AS_IS: case strategy == DomainStrategy_AS_IS:
return nil, nil return nil, nil
} }
return lookupFunc(domain) return d.dns.LookupOptions(domain, opt, dns.LookupNoFake)
} }
func (d *DefaultSystemDialer) doLookupIP(ctx context.Context, dst net.Destination, sockopt *SocketConfig) bool { func (d *DefaultSystemDialer) canLookupIP(ctx context.Context, dst net.Destination, sockopt *SocketConfig) bool {
if sockopt == nil || dst.Address.Family().IsIP() || d.dns == nil { if sockopt == nil || dst.Address.Family().IsIP() || d.dns == nil {
return false return false
} }
@ -121,7 +111,7 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
} }
} }
if d.doLookupIP(ctx, dest, sockopt) { if d.canLookupIP(ctx, dest, sockopt) {
ips, err := d.lookupIP(dest.Address.String(), sockopt.DomainStrategy, src) ips, err := d.lookupIP(dest.Address.String(), sockopt.DomainStrategy, src)
if err == nil && len(ips) > 0 { if err == nil && len(ips) > 0 {
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))]) dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])