mirror of https://github.com/XTLS/Xray-core
feat(dns): add parallel query (#5239)
parent
cd51f57535
commit
f14fd1cbee
|
|
@ -194,7 +194,7 @@ func (c *CacheController) migrate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.LogDebug(context.Background(), c.name, " starting background cache migration for ", len(dirtyips), " items.")
|
errors.LogDebug(context.Background(), c.name, " starting background cache migration for ", len(dirtyips), " items")
|
||||||
|
|
||||||
batch := make([]migrationEntry, 0, migrationBatchSize)
|
batch := make([]migrationEntry, 0, migrationBatchSize)
|
||||||
for domain, recD := range dirtyips {
|
for domain, recD := range dirtyips {
|
||||||
|
|
@ -214,7 +214,7 @@ func (c *CacheController) migrate() {
|
||||||
c.dirtyips = nil
|
c.dirtyips = nil
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
|
||||||
errors.LogDebug(context.Background(), c.name, " cache migration completed.")
|
errors.LogDebug(context.Background(), c.name, " cache migration completed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) flush(batch []migrationEntry) {
|
func (c *CacheController) flush(batch []migrationEntry) {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ type NameServer struct {
|
||||||
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
||||||
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
||||||
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
||||||
|
PolicyID uint32 `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) Reset() {
|
func (x *NameServer) Reset() {
|
||||||
|
|
@ -291,6 +292,13 @@ func (x *NameServer) GetActUnprior() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetPolicyID() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PolicyID
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
|
@ -312,6 +320,7 @@ type Config struct {
|
||||||
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"`
|
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
||||||
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
||||||
|
EnableParallelQuery bool `protobuf:"varint,14,opt,name=enableParallelQuery,proto3" json:"enableParallelQuery,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
|
|
@ -414,6 +423,13 @@ func (x *Config) GetDisableFallbackIfMatch() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetEnableParallelQuery() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.EnableParallelQuery
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type NameServer_PriorityDomain struct {
|
type NameServer_PriorityDomain struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
|
@ -599,7 +615,7 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
||||||
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x07, 0x0a, 0x0a,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb5, 0x07, 0x0a, 0x0a,
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
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, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
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, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
||||||
|
|
@ -646,70 +662,75 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
||||||
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x78,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x78,
|
||||||
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
|
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
|
||||||
0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e, 0x50,
|
0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70,
|
||||||
0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a,
|
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x44, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70,
|
||||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72,
|
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x44, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
||||||
0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f,
|
0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72,
|
0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12,
|
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69,
|
||||||
0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73,
|
0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18,
|
||||||
0x69, 0x7a, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73,
|
||||||
0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x22, 0xe6, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x42,
|
||||||
0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65,
|
0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64,
|
||||||
0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
0x54, 0x54, 0x4c, 0x22, 0x98, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39,
|
||||||
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
|
0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20,
|
||||||
0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a,
|
0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
||||||
0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e,
|
||||||
0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74,
|
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69,
|
||||||
0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
|
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c,
|
||||||
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63,
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69,
|
0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
||||||
0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
|
0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b,
|
||||||
0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68,
|
0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74,
|
||||||
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a,
|
||||||
0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74,
|
0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20,
|
||||||
0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65,
|
0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68,
|
||||||
0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78,
|
0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18,
|
||||||
0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
|
0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c,
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12,
|
0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65,
|
||||||
0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76,
|
||||||
0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x42, 0x0a, 0x0e, 0x71,
|
||||||
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61,
|
0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20,
|
||||||
0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
||||||
0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61,
|
0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69,
|
0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12,
|
||||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a,
|
0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
||||||
0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
||||||
0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64,
|
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73,
|
||||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66,
|
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61,
|
||||||
0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61,
|
0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62,
|
||||||
0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
|
0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63,
|
||||||
0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
0x68, 0x12, 0x30, 0x0a, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c,
|
||||||
0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e,
|
0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13,
|
||||||
0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64,
|
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d,
|
0x65, 0x72, 0x79, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70,
|
||||||
0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52,
|
0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64,
|
0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f,
|
0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54,
|
||||||
0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08,
|
0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d,
|
||||||
0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69,
|
0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00,
|
0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69,
|
||||||
0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12,
|
0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d,
|
||||||
0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05,
|
0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69,
|
||||||
0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79,
|
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f,
|
0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67,
|
||||||
0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10,
|
0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d,
|
||||||
0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0b,
|
0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a,
|
||||||
0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63,
|
0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65,
|
||||||
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50,
|
0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
|
||||||
0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
||||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
|
0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12,
|
||||||
0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e,
|
0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07,
|
||||||
0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 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 (
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ message NameServer {
|
||||||
bool finalQuery = 12;
|
bool finalQuery = 12;
|
||||||
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
||||||
bool actUnprior = 14;
|
bool actUnprior = 14;
|
||||||
|
uint32 policyID = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DomainMatchingType {
|
enum DomainMatchingType {
|
||||||
|
|
@ -89,4 +90,6 @@ message Config {
|
||||||
|
|
||||||
bool disableFallback = 10;
|
bool disableFallback = 10;
|
||||||
bool disableFallbackIfMatch = 11;
|
bool disableFallbackIfMatch = 11;
|
||||||
|
|
||||||
|
bool enableParallelQuery = 14;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
252
app/dns/dns.go
252
app/dns/dns.go
|
|
@ -25,6 +25,7 @@ type DNS struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
disableFallback bool
|
disableFallback bool
|
||||||
disableFallbackIfMatch bool
|
disableFallbackIfMatch bool
|
||||||
|
enableParallelQuery bool
|
||||||
ipOption *dns.IPOption
|
ipOption *dns.IPOption
|
||||||
hosts *StaticHosts
|
hosts *StaticHosts
|
||||||
clients []*Client
|
clients []*Client
|
||||||
|
|
@ -157,6 +158,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
||||||
matcherInfos: matcherInfos,
|
matcherInfos: matcherInfos,
|
||||||
disableFallback: config.DisableFallback,
|
disableFallback: config.DisableFallback,
|
||||||
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
||||||
|
enableParallelQuery: config.EnableParallelQuery,
|
||||||
checkSystem: checkSystem,
|
checkSystem: checkSystem,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
@ -235,45 +237,11 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name servers lookup
|
// Name servers lookup
|
||||||
var errs []error
|
if s.enableParallelQuery {
|
||||||
for _, client := range s.sortClients(domain) {
|
return s.parallelQuery(domain, option)
|
||||||
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
} else {
|
||||||
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
return s.serialQuery(domain, option)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
|
||||||
if ttl == 0 {
|
|
||||||
ttl = 1
|
|
||||||
}
|
|
||||||
return ips, ttl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name())
|
|
||||||
if err == nil {
|
|
||||||
err = dns.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
errs = append(errs, err)
|
|
||||||
|
|
||||||
if client.IsFinalQuery() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) > 0 {
|
|
||||||
allErrs := errors.Combine(errs...)
|
|
||||||
err0 := errs[0]
|
|
||||||
if errors.AllEqual(err0, allErrs) {
|
|
||||||
if go_errors.Is(err0, dns.ErrEmptyResponse) {
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(err0)
|
|
||||||
}
|
|
||||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(allErrs)
|
|
||||||
}
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DNS) sortClients(domain string) []*Client {
|
func (s *DNS) sortClients(domain string) []*Client {
|
||||||
|
|
@ -300,6 +268,9 @@ func (s *DNS) sortClients(domain string) []*Client {
|
||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
clientNames = append(clientNames, client.Name())
|
clientNames = append(clientNames, client.Name())
|
||||||
hasMatch = true
|
hasMatch = true
|
||||||
|
if client.finalQuery {
|
||||||
|
return clients
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) {
|
if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) {
|
||||||
|
|
@ -311,6 +282,9 @@ func (s *DNS) sortClients(domain string) []*Client {
|
||||||
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 client.finalQuery {
|
||||||
|
return clients
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,14 +296,214 @@ func (s *DNS) sortClients(domain string) []*Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) == 0 {
|
if len(clients) == 0 {
|
||||||
|
if len(s.clients) > 0 {
|
||||||
clients = append(clients, s.clients[0])
|
clients = append(clients, s.clients[0])
|
||||||
clientNames = append(clientNames, s.clients[0].Name())
|
clientNames = append(clientNames, s.clients[0].Name())
|
||||||
errors.LogDebug(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
|
errors.LogWarning(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
|
||||||
|
} else {
|
||||||
|
errors.LogError(s.ctx, "no DNS clients available for domain ", domain, " and no default clients configured")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return clients
|
return clients
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeQueryErrors(domain string, errs []error) error {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
var noRNF error
|
||||||
|
for _, err := range errs {
|
||||||
|
if go_errors.Is(err, errRecordNotFound) {
|
||||||
|
continue // server no response, ignore
|
||||||
|
} else if noRNF == nil {
|
||||||
|
noRNF = err
|
||||||
|
} else if !go_errors.Is(err, noRNF) {
|
||||||
|
return errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if go_errors.Is(noRNF, dns.ErrEmptyResponse) {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
if noRNF == nil {
|
||||||
|
noRNF = errRecordNotFound
|
||||||
|
}
|
||||||
|
return errors.New("returning nil for domain ", domain).Base(noRNF)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DNS) serialQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
var errs []error
|
||||||
|
for _, client := range s.sortClients(domain) {
|
||||||
|
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||||
|
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return ips, ttl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name(), " in serial query mode")
|
||||||
|
if err == nil {
|
||||||
|
err = dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return nil, 0, mergeQueryErrors(domain, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DNS) parallelQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
var errs []error
|
||||||
|
clients := s.sortClients(domain)
|
||||||
|
|
||||||
|
resultsChan := asyncQueryAll(domain, option, clients, s.ctx)
|
||||||
|
|
||||||
|
groups, groupOf := makeGroups( /*s.ctx,*/ clients)
|
||||||
|
results := make([]*queryResult, len(clients))
|
||||||
|
pending := make([]int, len(groups))
|
||||||
|
for gi, g := range groups {
|
||||||
|
pending[gi] = g.end - g.start + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
nextGroup := 0
|
||||||
|
for range clients {
|
||||||
|
result := <-resultsChan
|
||||||
|
results[result.index] = &result
|
||||||
|
|
||||||
|
gi := groupOf[result.index]
|
||||||
|
pending[gi]--
|
||||||
|
|
||||||
|
for nextGroup < len(groups) {
|
||||||
|
g := groups[nextGroup]
|
||||||
|
|
||||||
|
// group race, minimum rtt -> return
|
||||||
|
for j := g.start; j <= g.end; j++ {
|
||||||
|
r := results[j]
|
||||||
|
if r != nil && r.err == nil && len(r.ips) > 0 {
|
||||||
|
return r.ips, r.ttl, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// current group is incomplete and no one success -> continue pending
|
||||||
|
if pending[nextGroup] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// all failed -> log and continue next group
|
||||||
|
for j := g.start; j <= g.end; j++ {
|
||||||
|
r := results[j]
|
||||||
|
e := r.err
|
||||||
|
if e == nil {
|
||||||
|
e = dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
errors.LogInfoInner(s.ctx, e, "failed to lookup ip for domain ", domain, " at server ", clients[j].Name(), " in parallel query mode")
|
||||||
|
errs = append(errs, e)
|
||||||
|
}
|
||||||
|
nextGroup++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, 0, mergeQueryErrors(domain, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryResult struct {
|
||||||
|
ips []net.IP
|
||||||
|
ttl uint32
|
||||||
|
err error
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncQueryAll(domain string, option dns.IPOption, clients []*Client, ctx context.Context) chan queryResult {
|
||||||
|
if len(clients) == 0 {
|
||||||
|
ch := make(chan queryResult)
|
||||||
|
close(ch)
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan queryResult, len(clients))
|
||||||
|
for i, client := range clients {
|
||||||
|
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||||
|
errors.LogDebug(ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
||||||
|
ch <- queryResult{err: dns.ErrEmptyResponse, index: i}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go func(i int, c *Client) {
|
||||||
|
qctx := ctx
|
||||||
|
if !c.server.IsDisableCache() {
|
||||||
|
nctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), c.timeoutMs*2)
|
||||||
|
qctx = nctx
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
ips, ttl, err := c.QueryIP(qctx, domain, option)
|
||||||
|
ch <- queryResult{ips: ips, ttl: ttl, err: err, index: i}
|
||||||
|
}(i, client)
|
||||||
|
}
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
type group struct{ start, end int }
|
||||||
|
|
||||||
|
// merge only adjacent and rule-equivalent Client into a single group
|
||||||
|
func makeGroups( /*ctx context.Context,*/ clients []*Client) ([]group, []int) {
|
||||||
|
n := len(clients)
|
||||||
|
if n == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
groups := make([]group, 0, n)
|
||||||
|
groupOf := make([]int, n)
|
||||||
|
|
||||||
|
s, e := 0, 0
|
||||||
|
for i := 1; i < n; i++ {
|
||||||
|
if clients[i-1].policyID == clients[i].policyID {
|
||||||
|
e = i
|
||||||
|
} else {
|
||||||
|
for k := s; k <= e; k++ {
|
||||||
|
groupOf[k] = len(groups)
|
||||||
|
}
|
||||||
|
groups = append(groups, group{start: s, end: e})
|
||||||
|
s, e = i, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k := s; k <= e; k++ {
|
||||||
|
groupOf[k] = len(groups)
|
||||||
|
}
|
||||||
|
groups = append(groups, group{start: s, end: e})
|
||||||
|
|
||||||
|
// var b strings.Builder
|
||||||
|
// b.WriteString("dns grouping: total clients=")
|
||||||
|
// b.WriteString(strconv.Itoa(n))
|
||||||
|
// b.WriteString(", groups=")
|
||||||
|
// b.WriteString(strconv.Itoa(len(groups)))
|
||||||
|
|
||||||
|
// for gi, g := range groups {
|
||||||
|
// b.WriteString("\n [")
|
||||||
|
// b.WriteString(strconv.Itoa(g.start))
|
||||||
|
// b.WriteString("..")
|
||||||
|
// b.WriteString(strconv.Itoa(g.end))
|
||||||
|
// b.WriteString("] gid=")
|
||||||
|
// b.WriteString(strconv.Itoa(gi))
|
||||||
|
// b.WriteString(" pid=")
|
||||||
|
// b.WriteString(strconv.FormatUint(uint64(clients[g.start].policyID), 10))
|
||||||
|
// b.WriteString(" members: ")
|
||||||
|
|
||||||
|
// for i := g.start; i <= g.end; i++ {
|
||||||
|
// if i > g.start {
|
||||||
|
// b.WriteString(", ")
|
||||||
|
// }
|
||||||
|
// b.WriteString(strconv.Itoa(i))
|
||||||
|
// b.WriteByte(':')
|
||||||
|
// b.WriteString(clients[i].Name())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// errors.LogDebug(ctx, b.String())
|
||||||
|
|
||||||
|
return groups, groupOf
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return New(ctx, config.(*Config))
|
return New(ctx, config.(*Config))
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ import (
|
||||||
type Server interface {
|
type Server interface {
|
||||||
// Name of the Client.
|
// Name of the Client.
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
|
IsDisableCache() bool
|
||||||
|
|
||||||
// QueryIP sends IP queries to its configured server.
|
// QueryIP sends IP queries to its configured server.
|
||||||
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
|
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +41,7 @@ type Client struct {
|
||||||
finalQuery bool
|
finalQuery bool
|
||||||
ipOption *dns.IPOption
|
ipOption *dns.IPOption
|
||||||
checkSystem bool
|
checkSystem bool
|
||||||
|
policyID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a name server object according to the network destination url.
|
// NewServer creates a name server object according to the network destination url.
|
||||||
|
|
@ -199,6 +203,7 @@ func NewClient(
|
||||||
client.finalQuery = ns.FinalQuery
|
client.finalQuery = ns.FinalQuery
|
||||||
client.ipOption = &ipOption
|
client.ipOption = &ipOption
|
||||||
client.checkSystem = checkSystem
|
client.checkSystem = checkSystem
|
||||||
|
client.policyID = ns.PolicyID
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return client, err
|
return client, err
|
||||||
|
|
@ -209,10 +214,6 @@ func (c *Client) Name() string {
|
||||||
return c.server.Name()
|
return c.server.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) IsFinalQuery() bool {
|
|
||||||
return c.finalQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryIP sends DNS query to the name server with the client's IP.
|
// QueryIP sends DNS query to the name server with the client's IP.
|
||||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
if c.checkSystem {
|
if c.checkSystem {
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ func queryIP(ctx context.Context, s CachedNameserver, domain string, option dns.
|
||||||
ips, ttl, err := merge(option, rec.A, rec.AAAA)
|
ips, ttl, err := merge(option, rec.A, rec.AAAA)
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
if ttl > 0 {
|
if ttl > 0 {
|
||||||
// errors.LogDebugInner(ctx, err, cache.name, " cache HIT ", fqdn, " -> ", ips)
|
errors.LogDebugInner(ctx, err, cache.name, " cache HIT ", fqdn, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, uint32(ttl), err
|
return ips, uint32(ttl), err
|
||||||
}
|
}
|
||||||
if cache.serveStale && (cache.serveExpiredTTL == 0 || cache.serveExpiredTTL < ttl) {
|
if cache.serveStale && (cache.serveExpiredTTL == 0 || cache.serveExpiredTTL < ttl) {
|
||||||
// errors.LogDebugInner(ctx, err, cache.name, " cache OPTIMISTE ", fqdn, " -> ", ips)
|
errors.LogDebugInner(ctx, err, cache.name, " cache OPTIMISTE ", fqdn, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheOptimiste, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheOptimiste, Elapsed: 0, Error: err})
|
||||||
go pull(ctx, s, fqdn, option)
|
go pull(ctx, s, fqdn, option)
|
||||||
return ips, 1, err
|
return ips, 1, err
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,11 @@ func (s *DoHNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *DoHNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) newReqID() uint16 {
|
func (s *DoHNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +135,7 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
||||||
errors.LogInfo(ctx, s.Name(), " querying: ", fqdn)
|
errors.LogInfo(ctx, s.Name(), " querying: ", fqdn)
|
||||||
|
|
||||||
if s.Name()+"." == "DOH//"+fqdn {
|
if s.Name()+"." == "DOH//"+fqdn {
|
||||||
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead")
|
||||||
if noResponseErrCh != nil {
|
if noResponseErrCh != nil {
|
||||||
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,11 @@ func (FakeDNSServer) Name() string {
|
||||||
return "FakeDNS"
|
return "FakeDNS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *FakeDNSServer) IsDisableCache() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
|
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
if f.fakeDNSEngine == nil {
|
if f.fakeDNSEngine == nil {
|
||||||
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
|
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@ func (s *LocalNameServer) Name() string {
|
||||||
return "localhost"
|
return "localhost"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *LocalNameServer) IsDisableCache() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
||||||
func NewLocalNameServer() *LocalNameServer {
|
func NewLocalNameServer() *LocalNameServer {
|
||||||
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ type QUICNameServer struct {
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
||||||
func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*QUICNameServer, error) {
|
func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*QUICNameServer, error) {
|
||||||
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
port := net.Port(853)
|
port := net.Port(853)
|
||||||
if url.Port() != "" {
|
if url.Port() != "" {
|
||||||
|
|
@ -55,6 +53,7 @@ func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveEx
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,6 +62,11 @@ func (s *QUICNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *QUICNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) newReqID() uint16 {
|
func (s *QUICNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ func NewTCPNameServer(
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created TCP client initialized for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,6 +67,7 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, serveStale bool, ser
|
||||||
return internet.DialSystem(ctx, *s.destination, nil)
|
return internet.DialSystem(ctx, *s.destination, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created Local TCP client initialized for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,6 +95,11 @@ func (s *TCPNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *TCPNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TCPNameServer) newReqID() uint16 {
|
func (s *TCPNameServer) newReqID() uint16 {
|
||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +111,7 @@ func (s *TCPNameServer) getCacheController() *CacheController {
|
||||||
|
|
||||||
// sendQuery implements CachedNameserver.
|
// sendQuery implements CachedNameserver.
|
||||||
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
|
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", fqdn)
|
errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
|
||||||
|
|
||||||
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
||||||
Execute: s.RequestsCleanup,
|
Execute: s.RequestsCleanup,
|
||||||
}
|
}
|
||||||
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
||||||
|
|
||||||
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +64,11 @@ func (s *ClassicNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *ClassicNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
// RequestsCleanup clears expired items from cache
|
// RequestsCleanup clears expired items from cache
|
||||||
func (s *ClassicNameServer) RequestsCleanup() error {
|
func (s *ClassicNameServer) RequestsCleanup() error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
@ -92,7 +98,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
||||||
ipRec, err := parseResponse(payload.Bytes())
|
ipRec, err := parseResponse(payload.Bytes())
|
||||||
payload.Release()
|
payload.Release()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(ctx, s.Name(), " fail to parse responded DNS udp")
|
errors.LogErrorInner(ctx, err, s.Name(), " fail to parse responded DNS udp")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +111,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
||||||
}
|
}
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
errors.LogError(ctx, s.Name(), " cannot find the pending request")
|
errors.LogErrorInner(ctx, err, s.Name(), " cannot find the pending request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +161,7 @@ func (s *ClassicNameServer) getCacheController() *CacheController {
|
||||||
|
|
||||||
// sendQuery implements CachedNameserver.
|
// sendQuery implements CachedNameserver.
|
||||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn string, option dns_feature.IPOption) {
|
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", fqdn)
|
errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
|
||||||
|
|
||||||
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,7 @@ type DNSConfig struct {
|
||||||
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
|
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
|
||||||
DisableFallback bool `json:"disableFallback"`
|
DisableFallback bool `json:"disableFallback"`
|
||||||
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
||||||
|
EnableParallelQuery bool `json:"enableParallelQuery"`
|
||||||
UseSystemHosts bool `json:"useSystemHosts"`
|
UseSystemHosts bool `json:"useSystemHosts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -405,6 +406,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
|
||||||
ServeExpiredTTL: c.ServeExpiredTTL,
|
ServeExpiredTTL: c.ServeExpiredTTL,
|
||||||
DisableFallback: c.DisableFallback,
|
DisableFallback: c.DisableFallback,
|
||||||
DisableFallbackIfMatch: c.DisableFallbackIfMatch,
|
DisableFallbackIfMatch: c.DisableFallbackIfMatch,
|
||||||
|
EnableParallelQuery: c.EnableParallelQuery,
|
||||||
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,11 +417,78 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
|
||||||
config.ClientIp = []byte(c.ClientIP.IP())
|
config.ClientIp = []byte(c.ClientIP.IP())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build PolicyID
|
||||||
|
policyMap := map[string]uint32{}
|
||||||
|
nextPolicyID := uint32(1)
|
||||||
|
buildPolicyID := func(nsc *NameServerConfig) uint32 {
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
// ClientIP
|
||||||
|
if nsc.ClientIP != nil {
|
||||||
|
sb.WriteString("client=")
|
||||||
|
sb.WriteString(nsc.ClientIP.String())
|
||||||
|
sb.WriteByte('|')
|
||||||
|
} else {
|
||||||
|
sb.WriteString("client=none|")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SkipFallback
|
||||||
|
if nsc.SkipFallback {
|
||||||
|
sb.WriteString("skip=1|")
|
||||||
|
} else {
|
||||||
|
sb.WriteString("skip=0|")
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStrategy
|
||||||
|
sb.WriteString("qs=")
|
||||||
|
sb.WriteString(strings.ToLower(strings.TrimSpace(nsc.QueryStrategy)))
|
||||||
|
sb.WriteByte('|')
|
||||||
|
|
||||||
|
// Tag
|
||||||
|
sb.WriteString("tag=")
|
||||||
|
sb.WriteString(strings.ToLower(strings.TrimSpace(nsc.Tag)))
|
||||||
|
sb.WriteByte('|')
|
||||||
|
|
||||||
|
// []string helper
|
||||||
|
writeList := func(tag string, lst []string) {
|
||||||
|
if len(lst) == 0 {
|
||||||
|
sb.WriteString(tag)
|
||||||
|
sb.WriteString("=[]|")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cp := make([]string, len(lst))
|
||||||
|
for i, s := range lst {
|
||||||
|
cp[i] = strings.TrimSpace(strings.ToLower(s))
|
||||||
|
}
|
||||||
|
sort.Strings(cp)
|
||||||
|
sb.WriteString(tag)
|
||||||
|
sb.WriteByte('=')
|
||||||
|
sb.WriteString(strings.Join(cp, ","))
|
||||||
|
sb.WriteByte('|')
|
||||||
|
}
|
||||||
|
|
||||||
|
writeList("domains", nsc.Domains)
|
||||||
|
writeList("expected", nsc.ExpectedIPs)
|
||||||
|
writeList("expect", nsc.ExpectIPs)
|
||||||
|
writeList("unexpected", nsc.UnexpectedIPs)
|
||||||
|
|
||||||
|
key := sb.String()
|
||||||
|
|
||||||
|
if id, ok := policyMap[key]; ok {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
id := nextPolicyID
|
||||||
|
nextPolicyID++
|
||||||
|
policyMap[key] = id
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
for _, server := range c.Servers {
|
for _, server := range c.Servers {
|
||||||
ns, err := server.Build()
|
ns, err := server.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build nameserver").Base(err)
|
return nil, errors.New("failed to build nameserver").Base(err)
|
||||||
}
|
}
|
||||||
|
ns.PolicyID = buildPolicyID(server)
|
||||||
config.NameServer = append(config.NameServer, ns)
|
config.NameServer = append(config.NameServer, ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ func TestDNSConfigParsing(t *testing.T) {
|
||||||
},
|
},
|
||||||
ServeStale: true,
|
ServeStale: true,
|
||||||
ServeExpiredTTL: &expectedServeExpiredTTL,
|
ServeExpiredTTL: &expectedServeExpiredTTL,
|
||||||
|
PolicyID: 1, // Servers with certain identical fields share this ID, incrementing starting from 1. See: Build PolicyID
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StaticHosts: []*dns.Config_HostMapping{
|
StaticHosts: []*dns.Config_HostMapping{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue