diff --git a/app/dns/cache_controller.go b/app/dns/cache_controller.go index 24ae3cb2..a303b264 100644 --- a/app/dns/cache_controller.go +++ b/app/dns/cache_controller.go @@ -194,7 +194,7 @@ func (c *CacheController) migrate() { 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) for domain, recD := range dirtyips { @@ -214,7 +214,7 @@ func (c *CacheController) migrate() { c.dirtyips = nil 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) { diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go index 9cc63986..d7ac3803 100644 --- a/app/dns/config.pb.go +++ b/app/dns/config.pb.go @@ -147,6 +147,7 @@ type NameServer struct { 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"` 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() { @@ -291,6 +292,13 @@ func (x *NameServer) GetActUnprior() bool { return false } +func (x *NameServer) GetPolicyID() uint32 { + if x != nil { + return x.PolicyID + } + return 0 +} + type Config struct { state protoimpl.MessageState 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"` DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,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() { @@ -414,6 +423,13 @@ func (x *Config) GetDisableFallbackIfMatch() bool { return false } +func (x *Config) GetEnableParallelQuery() bool { + if x != nil { + return x.EnableParallelQuery + } + return false +} + type NameServer_PriorityDomain struct { state protoimpl.MessageState 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, 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, - 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, 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, @@ -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, 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, - 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, - 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, - 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, - 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x22, 0xe6, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, - 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, - 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, - 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, - 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, - 0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, - 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, - 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 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, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, - 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, - 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, - 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, - 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, - 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, - 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, - 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, - 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, - 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, - 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, - 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 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, 0x12, 0x0b, - 0x0a, 0x07, 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, + 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x44, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x44, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, + 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x42, + 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, + 0x54, 0x54, 0x4c, 0x22, 0x98, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, + 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, + 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, + 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, + 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, + 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, + 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, + 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x42, 0x0a, 0x0e, 0x71, + 0x75, 0x65, 0x72, 0x79, 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, 0x70, 0x2e, 0x64, + 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, + 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, + 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x12, 0x30, 0x0a, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c, + 0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, + 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, + 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, + 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45, + 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, + 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, + 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, + 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, + 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 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, 0x12, 0x0b, 0x0a, 0x07, + 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 ( diff --git a/app/dns/config.proto b/app/dns/config.proto index a87725a3..f1b47bc0 100644 --- a/app/dns/config.proto +++ b/app/dns/config.proto @@ -37,6 +37,7 @@ message NameServer { bool finalQuery = 12; repeated xray.app.router.GeoIP unexpected_geoip = 13; bool actUnprior = 14; + uint32 policyID = 17; } enum DomainMatchingType { @@ -89,4 +90,6 @@ message Config { bool disableFallback = 10; bool disableFallbackIfMatch = 11; + + bool enableParallelQuery = 14; } diff --git a/app/dns/dns.go b/app/dns/dns.go index 78e91389..9233d905 100644 --- a/app/dns/dns.go +++ b/app/dns/dns.go @@ -25,6 +25,7 @@ type DNS struct { sync.Mutex disableFallback bool disableFallbackIfMatch bool + enableParallelQuery bool ipOption *dns.IPOption hosts *StaticHosts clients []*Client @@ -157,6 +158,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) { matcherInfos: matcherInfos, disableFallback: config.DisableFallback, disableFallbackIfMatch: config.DisableFallbackIfMatch, + enableParallelQuery: config.EnableParallelQuery, checkSystem: checkSystem, }, nil } @@ -235,45 +237,11 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er } // Name servers lookup - 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 { - 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 s.enableParallelQuery { + return s.parallelQuery(domain, option) + } else { + return s.serialQuery(domain, option) } - - 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 { @@ -300,6 +268,9 @@ func (s *DNS) sortClients(domain string) []*Client { clients = append(clients, client) clientNames = append(clientNames, client.Name()) hasMatch = true + if client.finalQuery { + return clients + } } if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) { @@ -311,6 +282,9 @@ func (s *DNS) sortClients(domain string) []*Client { clientUsed[idx] = true clients = append(clients, client) 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 { - clients = append(clients, s.clients[0]) - clientNames = append(clientNames, s.clients[0].Name()) - errors.LogDebug(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames) + if len(s.clients) > 0 { + clients = append(clients, s.clients[0]) + clientNames = append(clientNames, s.clients[0].Name()) + 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 } +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() { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { return New(ctx, config.(*Config)) diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 3f25833e..e606d4b3 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -20,6 +20,9 @@ import ( type Server interface { // Name of the Client. Name() string + + IsDisableCache() bool + // QueryIP sends IP queries to its configured server. QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) } @@ -38,6 +41,7 @@ type Client struct { finalQuery bool ipOption *dns.IPOption checkSystem bool + policyID uint32 } // NewServer creates a name server object according to the network destination url. @@ -199,6 +203,7 @@ func NewClient( client.finalQuery = ns.FinalQuery client.ipOption = &ipOption client.checkSystem = checkSystem + client.policyID = ns.PolicyID return nil }) return client, err @@ -209,10 +214,6 @@ func (c *Client) Name() string { 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. func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) { if c.checkSystem { diff --git a/app/dns/nameserver_cached.go b/app/dns/nameserver_cached.go index e27dda49..cbd2f031 100644 --- a/app/dns/nameserver_cached.go +++ b/app/dns/nameserver_cached.go @@ -28,12 +28,12 @@ func queryIP(ctx context.Context, s CachedNameserver, domain string, option dns. ips, ttl, err := merge(option, rec.A, rec.AAAA) if !go_errors.Is(err, errRecordNotFound) { 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}) return ips, uint32(ttl), err } 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}) go pull(ctx, s, fqdn, option) return ips, 1, err diff --git a/app/dns/nameserver_doh.go b/app/dns/nameserver_doh.go index 88198aed..9557c325 100644 --- a/app/dns/nameserver_doh.go +++ b/app/dns/nameserver_doh.go @@ -116,6 +116,11 @@ func (s *DoHNameServer) Name() string { return s.cacheController.name } +// IsDisableCache implements Server. +func (s *DoHNameServer) IsDisableCache() bool { + return s.cacheController.disableCache +} + func (s *DoHNameServer) newReqID() uint16 { return 0 } @@ -130,7 +135,7 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er errors.LogInfo(ctx, s.Name(), " querying: ", 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 { noResponseErrCh <- errors.New("tries to resolve itself!", s.Name()) } diff --git a/app/dns/nameserver_fakedns.go b/app/dns/nameserver_fakedns.go index 8c598ac8..bed11bd6 100644 --- a/app/dns/nameserver_fakedns.go +++ b/app/dns/nameserver_fakedns.go @@ -20,6 +20,11 @@ func (FakeDNSServer) Name() string { 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) { if f.fakeDNSEngine == nil { return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError() diff --git a/app/dns/nameserver_local.go b/app/dns/nameserver_local.go index 91b003e3..576c259b 100644 --- a/app/dns/nameserver_local.go +++ b/app/dns/nameserver_local.go @@ -35,6 +35,11 @@ func (s *LocalNameServer) Name() string { return "localhost" } +// IsDisableCache implements Server. +func (s *LocalNameServer) IsDisableCache() bool { + return true +} + // NewLocalNameServer creates localdns server object for directly lookup in system DNS. func NewLocalNameServer() *LocalNameServer { errors.LogInfo(context.Background(), "DNS: created localhost client") diff --git a/app/dns/nameserver_quic.go b/app/dns/nameserver_quic.go index 3d271d74..4c7ac032 100644 --- a/app/dns/nameserver_quic.go +++ b/app/dns/nameserver_quic.go @@ -37,8 +37,6 @@ type QUICNameServer struct { // 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) { - errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String()) - var err error port := net.Port(853) if url.Port() != "" { @@ -55,6 +53,7 @@ func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveEx clientIP: clientIP, } + errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String()) return s, nil } @@ -63,6 +62,11 @@ func (s *QUICNameServer) Name() string { return s.cacheController.name } +// IsDisableCache implements Server. +func (s *QUICNameServer) IsDisableCache() bool { + return s.cacheController.disableCache +} + func (s *QUICNameServer) newReqID() uint16 { return 0 } diff --git a/app/dns/nameserver_tcp.go b/app/dns/nameserver_tcp.go index f549a161..283a42a7 100644 --- a/app/dns/nameserver_tcp.go +++ b/app/dns/nameserver_tcp.go @@ -52,6 +52,7 @@ func NewTCPNameServer( ), nil } + errors.LogInfo(context.Background(), "DNS: created TCP client initialized for ", url.String()) return s, nil } @@ -66,6 +67,7 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, serveStale bool, ser return internet.DialSystem(ctx, *s.destination, nil) } + errors.LogInfo(context.Background(), "DNS: created Local TCP client initialized for ", url.String()) return s, nil } @@ -93,6 +95,11 @@ func (s *TCPNameServer) Name() string { return s.cacheController.name } +// IsDisableCache implements Server. +func (s *TCPNameServer) IsDisableCache() bool { + return s.cacheController.disableCache +} + func (s *TCPNameServer) newReqID() uint16 { return uint16(atomic.AddUint32(&s.reqID, 1)) } @@ -104,7 +111,7 @@ func (s *TCPNameServer) getCacheController() *CacheController { // sendQuery implements CachedNameserver. 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)) diff --git a/app/dns/nameserver_udp.go b/app/dns/nameserver_udp.go index 4449ac14..f263a0f8 100644 --- a/app/dns/nameserver_udp.go +++ b/app/dns/nameserver_udp.go @@ -54,6 +54,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher Execute: s.RequestsCleanup, } s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse) + errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr()) return s } @@ -63,6 +64,11 @@ func (s *ClassicNameServer) Name() string { return s.cacheController.name } +// IsDisableCache implements Server. +func (s *ClassicNameServer) IsDisableCache() bool { + return s.cacheController.disableCache +} + // RequestsCleanup clears expired items from cache func (s *ClassicNameServer) RequestsCleanup() error { now := time.Now() @@ -92,7 +98,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot ipRec, err := parseResponse(payload.Bytes()) payload.Release() 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 } @@ -105,7 +111,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot } s.Unlock() if !ok { - errors.LogError(ctx, s.Name(), " cannot find the pending request") + errors.LogErrorInner(ctx, err, s.Name(), " cannot find the pending request") return } @@ -155,7 +161,7 @@ func (s *ClassicNameServer) getCacheController() *CacheController { // sendQuery implements CachedNameserver. 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)) diff --git a/infra/conf/dns.go b/infra/conf/dns.go index 74b892c8..7c94a488 100644 --- a/infra/conf/dns.go +++ b/infra/conf/dns.go @@ -206,6 +206,7 @@ type DNSConfig struct { ServeExpiredTTL uint32 `json:"serveExpiredTTL"` DisableFallback bool `json:"disableFallback"` DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"` + EnableParallelQuery bool `json:"enableParallelQuery"` UseSystemHosts bool `json:"useSystemHosts"` } @@ -405,6 +406,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) { ServeExpiredTTL: c.ServeExpiredTTL, DisableFallback: c.DisableFallback, DisableFallbackIfMatch: c.DisableFallbackIfMatch, + EnableParallelQuery: c.EnableParallelQuery, QueryStrategy: resolveQueryStrategy(c.QueryStrategy), } @@ -415,11 +417,78 @@ func (c *DNSConfig) Build() (*dns.Config, error) { 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 { ns, err := server.Build() if err != nil { return nil, errors.New("failed to build nameserver").Base(err) } + ns.PolicyID = buildPolicyID(server) config.NameServer = append(config.NameServer, ns) } diff --git a/infra/conf/dns_test.go b/infra/conf/dns_test.go index 3329f5a2..af51b734 100644 --- a/infra/conf/dns_test.go +++ b/infra/conf/dns_test.go @@ -74,6 +74,7 @@ func TestDNSConfigParsing(t *testing.T) { }, ServeStale: true, ServeExpiredTTL: &expectedServeExpiredTTL, + PolicyID: 1, // Servers with certain identical fields share this ID, incrementing starting from 1. See: Build PolicyID }, }, StaticHosts: []*dns.Config_HostMapping{