diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go
index 67fbd84e..c653d691 100644
--- a/app/dns/config.pb.go
+++ b/app/dns/config.pb.go
@@ -128,16 +128,20 @@ type NameServer struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	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"`
-	SkipFallback       bool                         `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
-	PrioritizedDomain  []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
-	Geoip              []*router.GeoIP              `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
-	OriginalRules      []*NameServer_OriginalRule   `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
-	QueryStrategy      QueryStrategy                `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
-	AllowUnexpectedIPs bool                         `protobuf:"varint,8,opt,name=allowUnexpectedIPs,proto3" json:"allowUnexpectedIPs,omitempty"`
-	Tag                string                       `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
-	TimeoutMs          uint64                       `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,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"`
+	SkipFallback      bool                         `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
+	PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
+	ExpectedGeoip     []*router.GeoIP              `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
+	OriginalRules     []*NameServer_OriginalRule   `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
+	QueryStrategy     QueryStrategy                `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
+	PriorGeoip        []*router.GeoIP              `protobuf:"bytes,8,rep,name=prior_geoip,json=priorGeoip,proto3" json:"prior_geoip,omitempty"`
+	Tag               string                       `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
+	TimeoutMs         uint64                       `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
+	DisableCache      bool                         `protobuf:"varint,11,opt,name=disableCache,proto3" json:"disableCache,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"`
+	UnpriorGeoip      []*router.GeoIP              `protobuf:"bytes,14,rep,name=unprior_geoip,json=unpriorGeoip,proto3" json:"unprior_geoip,omitempty"`
 }
 
 func (x *NameServer) Reset() {
@@ -198,9 +202,9 @@ func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
 	return nil
 }
 
-func (x *NameServer) GetGeoip() []*router.GeoIP {
+func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
 	if x != nil {
-		return x.Geoip
+		return x.ExpectedGeoip
 	}
 	return nil
 }
@@ -219,11 +223,11 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy {
 	return QueryStrategy_USE_IP
 }
 
-func (x *NameServer) GetAllowUnexpectedIPs() bool {
+func (x *NameServer) GetPriorGeoip() []*router.GeoIP {
 	if x != nil {
-		return x.AllowUnexpectedIPs
+		return x.PriorGeoip
 	}
-	return false
+	return nil
 }
 
 func (x *NameServer) GetTag() string {
@@ -240,6 +244,34 @@ func (x *NameServer) GetTimeoutMs() uint64 {
 	return 0
 }
 
+func (x *NameServer) GetDisableCache() bool {
+	if x != nil {
+		return x.DisableCache
+	}
+	return false
+}
+
+func (x *NameServer) GetFinalQuery() bool {
+	if x != nil {
+		return x.FinalQuery
+	}
+	return false
+}
+
+func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
+	if x != nil {
+		return x.UnexpectedGeoip
+	}
+	return nil
+}
+
+func (x *NameServer) GetUnpriorGeoip() []*router.GeoIP {
+	if x != nil {
+		return x.UnpriorGeoip
+	}
+	return nil
+}
+
 type Config struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -532,7 +564,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, 0x92, 0x05, 0x0a, 0x0a,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x06, 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,
@@ -546,81 +578,95 @@ var file_app_dns_config_proto_rawDesc = []byte{
 	0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
 	0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
 	0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
-	0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69,
-	0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
-	0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52,
-	0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
-	0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
+	0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
+	0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
+	0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
+	0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
+	0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
+	0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
+	0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
+	0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
+	0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 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, 0x37, 0x0a, 0x0b, 0x70, 0x72, 0x69,
+	0x6f, 0x72, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
+	0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
+	0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x47, 0x65, 0x6f,
+	0x69, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d,
+	0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
+	0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63,
+	0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
+	0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x51,
+	0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x61,
+	0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65, 0x78, 0x70, 0x65,
+	0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 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, 0x3b, 0x0a, 0x0d, 0x75, 0x6e, 0x70,
+	0x72, 0x69, 0x6f, 0x72, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
+	0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0c, 0x75, 0x6e, 0x70, 0x72, 0x69, 0x6f,
+	0x72, 0x47, 0x65, 0x6f, 0x69, 0x70, 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, 0x22, 0x9c,
+	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, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
-	0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52,
-	0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74,
-	0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 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, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f,
-	0x77, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x18, 0x08,
-	0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x6e, 0x65, 0x78, 0x70,
-	0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
-	0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
-	0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 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,
-	0x22, 0x9c, 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, 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,
+	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, 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, 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, 0x35, 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, 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,
+	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, 0x35, 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, 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 (
@@ -651,19 +697,22 @@ var file_app_dns_config_proto_goTypes = []any{
 var file_app_dns_config_proto_depIdxs = []int32{
 	7,  // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
 	4,  // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
-	8,  // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP
+	8,  // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
 	5,  // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
 	1,  // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
-	2,  // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
-	6,  // 6: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
-	1,  // 7: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
-	0,  // 8: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
-	0,  // 9: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
-	10, // [10:10] is the sub-list for method output_type
-	10, // [10:10] is the sub-list for method input_type
-	10, // [10:10] is the sub-list for extension type_name
-	10, // [10:10] is the sub-list for extension extendee
-	0,  // [0:10] is the sub-list for field type_name
+	8,  // 5: xray.app.dns.NameServer.prior_geoip:type_name -> xray.app.router.GeoIP
+	8,  // 6: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
+	8,  // 7: xray.app.dns.NameServer.unprior_geoip:type_name -> xray.app.router.GeoIP
+	2,  // 8: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
+	6,  // 9: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
+	1,  // 10: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
+	0,  // 11: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
+	0,  // 12: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
+	13, // [13:13] is the sub-list for method output_type
+	13, // [13:13] is the sub-list for method input_type
+	13, // [13:13] is the sub-list for extension type_name
+	13, // [13:13] is the sub-list for extension extendee
+	0,  // [0:13] is the sub-list for field type_name
 }
 
 func init() { file_app_dns_config_proto_init() }
diff --git a/app/dns/config.proto b/app/dns/config.proto
index 8935ffa8..82600235 100644
--- a/app/dns/config.proto
+++ b/app/dns/config.proto
@@ -25,12 +25,16 @@ message NameServer {
   }
 
   repeated PriorityDomain prioritized_domain = 2;
-  repeated xray.app.router.GeoIP geoip = 3;
+  repeated xray.app.router.GeoIP expected_geoip = 3;
   repeated OriginalRule original_rules = 4;
   QueryStrategy query_strategy = 7;
-  bool allowUnexpectedIPs = 8;
+  repeated xray.app.router.GeoIP prior_geoip = 8;
   string tag = 9;
   uint64 timeoutMs = 10;
+  bool disableCache = 11;
+  bool finalQuery = 12;
+  repeated xray.app.router.GeoIP unexpected_geoip = 13;
+  repeated xray.app.router.GeoIP unprior_geoip = 14;
 }
 
 enum DomainMatchingType {
diff --git a/app/dns/dns.go b/app/dns/dns.go
index 3b9cfbcb..29960817 100644
--- a/app/dns/dns.go
+++ b/app/dns/dns.go
@@ -108,7 +108,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
 			myClientIP = net.IP(ns.ClientIp)
 		}
 
-		disableCache := config.DisableCache
+		disableCache := config.DisableCache || ns.DisableCache
 
 		var tag = defaultTag
 		if len(ns.Tag) > 0 {
@@ -227,6 +227,9 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er
 		}
 		errs = append(errs, err)
 
+		if client.IsFinalQuery() {
+			break
+		}
 	}
 
 	if len(errs) > 0 {
diff --git a/app/dns/dns_test.go b/app/dns/dns_test.go
index 7ea6fcf8..cb70b0b3 100644
--- a/app/dns/dns_test.go
+++ b/app/dns/dns_test.go
@@ -539,7 +539,7 @@ func TestIPMatch(t *testing.T) {
 							},
 							Port: uint32(port),
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{
 								CountryCode: "local",
 								Cidr: []*router.CIDR{
@@ -563,7 +563,7 @@ func TestIPMatch(t *testing.T) {
 							},
 							Port: uint32(port),
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{
 								CountryCode: "test",
 								Cidr: []*router.CIDR{
@@ -667,7 +667,7 @@ func TestLocalDomain(t *testing.T) {
 							// Equivalent of dotless:localhost
 							{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{ // Will match localhost, localhost-a and localhost-b,
 								CountryCode: "local",
 								Cidr: []*router.CIDR{
@@ -897,7 +897,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
 								Domain: "google.com",
 							},
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{ // Will only match 8.8.8.8 and 8.8.4.4
 								Cidr: []*router.CIDR{
 									{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
@@ -922,7 +922,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
 								Domain: "google.com",
 							},
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{ // Will match 8.8.8.8 and 8.8.8.7, etc
 								Cidr: []*router.CIDR{
 									{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
@@ -946,7 +946,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
 								Domain: "api.google.com",
 							},
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{ // Will only match 8.8.7.7 (api.google.com)
 								Cidr: []*router.CIDR{
 									{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
@@ -970,7 +970,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
 								Domain: "v2.api.google.com",
 							},
 						},
-						Geoip: []*router.GeoIP{
+						ExpectedGeoip: []*router.GeoIP{
 							{ // Will only match 8.8.7.8 (v2.api.google.com)
 								Cidr: []*router.CIDR{
 									{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go
index 31681c4a..2ee875e8 100644
--- a/app/dns/nameserver.go
+++ b/app/dns/nameserver.go
@@ -26,14 +26,17 @@ type Server interface {
 
 // Client is the interface for DNS client.
 type Client struct {
-	server             Server
-	skipFallback       bool
-	domains            []string
-	expectedIPs        []*router.GeoIPMatcher
-	allowUnexpectedIPs bool
-	tag                string
-	timeoutMs          time.Duration
-	ipOption           *dns.IPOption
+	server        Server
+	skipFallback  bool
+	domains       []string
+	expectedIPs   []*router.GeoIPMatcher
+	unexpectedIPs []*router.GeoIPMatcher
+	priorIPs      []*router.GeoIPMatcher
+	unpriorIPs    []*router.GeoIPMatcher
+	tag           string
+	timeoutMs     time.Duration
+	finalQuery    bool
+	ipOption      *dns.IPOption
 }
 
 // NewServer creates a name server object according to the network destination url.
@@ -150,13 +153,43 @@ func NewClient(
 		}
 
 		// Establish expected IPs
-		var matchers []*router.GeoIPMatcher
-		for _, geoip := range ns.Geoip {
+		var expectedMatchers []*router.GeoIPMatcher
+		for _, geoip := range ns.ExpectedGeoip {
 			matcher, err := router.GlobalGeoIPContainer.Add(geoip)
 			if err != nil {
-				return errors.New("failed to create ip matcher").Base(err).AtWarning()
+				return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
 			}
-			matchers = append(matchers, matcher)
+			expectedMatchers = append(expectedMatchers, matcher)
+		}
+
+		// Establish unexpected IPs
+		var unexpectedMatchers []*router.GeoIPMatcher
+		for _, geoip := range ns.UnexpectedGeoip {
+			matcher, err := router.GlobalGeoIPContainer.Add(geoip)
+			if err != nil {
+				return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
+			}
+			unexpectedMatchers = append(unexpectedMatchers, matcher)
+		}
+
+		// Establish prior IPs
+		var priorMatchers []*router.GeoIPMatcher
+		for _, geoip := range ns.PriorGeoip {
+			matcher, err := router.GlobalGeoIPContainer.Add(geoip)
+			if err != nil {
+				return errors.New("failed to create prior ip matcher").Base(err).AtWarning()
+			}
+			priorMatchers = append(priorMatchers, matcher)
+		}
+
+		// Establish unprior IPs
+		var unpriorMatchers []*router.GeoIPMatcher
+		for _, geoip := range ns.UnpriorGeoip {
+			matcher, err := router.GlobalGeoIPContainer.Add(geoip)
+			if err != nil {
+				return errors.New("failed to create unprior ip matcher").Base(err).AtWarning()
+			}
+			unpriorMatchers = append(unpriorMatchers, matcher)
 		}
 
 		if len(clientIP) > 0 {
@@ -176,10 +209,13 @@ func NewClient(
 		client.server = server
 		client.skipFallback = ns.SkipFallback
 		client.domains = rules
-		client.expectedIPs = matchers
-		client.allowUnexpectedIPs = ns.AllowUnexpectedIPs
+		client.expectedIPs = expectedMatchers
+		client.unexpectedIPs = unexpectedMatchers
+		client.priorIPs = priorMatchers
+		client.unpriorIPs = unpriorMatchers
 		client.tag = tag
 		client.timeoutMs = timeoutMs
+		client.finalQuery = ns.FinalQuery
 		client.ipOption = &ipOption
 		return nil
 	})
@@ -191,6 +227,10 @@ 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) {
 	option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable
@@ -213,34 +253,40 @@ func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption
 	}
 
 	if len(c.expectedIPs) > 0 {
-		newIps := c.MatchExpectedIPs(domain, ips)
-		if len(newIps) == 0 {
-			if !c.allowUnexpectedIPs {
-				return nil, 0, dns.ErrEmptyResponse
-			}
-		} else {
-			ips = newIps
+		ips = router.MatchIPs(c.expectedIPs, ips, false)
+		errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", ips, " matched at server ", c.Name())
+		if len(ips) == 0 {
+			return nil, 0, dns.ErrEmptyResponse
+		}
+	}
+
+	if len(c.unexpectedIPs) > 0 {
+		ips = router.MatchIPs(c.unexpectedIPs, ips, true)
+		errors.LogDebug(context.Background(), "domain ", domain, " unexpectedIPs ", ips, " matched at server ", c.Name())
+		if len(ips) == 0 {
+			return nil, 0, dns.ErrEmptyResponse
+		}
+	}
+
+	if len(c.priorIPs) > 0 {
+		ipsNew := router.MatchIPs(c.priorIPs, ips, false)
+		if len(ipsNew) > 0 {
+			ips = ipsNew
+			errors.LogDebug(context.Background(), "domain ", domain, " priorIPs ", ips, " matched at server ", c.Name())
+		}
+	}
+
+	if len(c.unpriorIPs) > 0 {
+		ipsNew := router.MatchIPs(c.unpriorIPs, ips, true)
+		if len(ipsNew) > 0 {
+			ips = ipsNew
+			errors.LogDebug(context.Background(), "domain ", domain, " unpriorIPs ", ips, " matched at server ", c.Name())
 		}
 	}
 
 	return ips, ttl, nil
 }
 
-// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
-func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) []net.IP {
-	var newIps []net.IP
-	for _, ip := range ips {
-		for _, matcher := range c.expectedIPs {
-			if matcher.Match(ip) {
-				newIps = append(newIps, ip)
-				break
-			}
-		}
-	}
-	errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", newIps, " matched at server ", c.Name())
-	return newIps
-}
-
 func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
 	switch queryStrategy {
 	case QueryStrategy_USE_IP:
diff --git a/app/router/condition_geoip.go b/app/router/condition_geoip.go
index 0140cdfb..38f7f0ce 100644
--- a/app/router/condition_geoip.go
+++ b/app/router/condition_geoip.go
@@ -116,3 +116,29 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
 }
 
 var GlobalGeoIPContainer GeoIPMatcherContainer
+
+func MatchIPs(matchers []*GeoIPMatcher, ips []net.IP, reverse bool) []net.IP {
+	if len(matchers) == 0 {
+		panic("GeoIP matchers should not be empty to avoid ambiguity")
+	}
+	newIPs := make([]net.IP, 0, len(ips))
+	var isFound bool
+	for _, ip := range ips {
+		isFound = false
+		for _, matcher := range matchers {
+			if matcher.Match(ip) {
+				isFound = true
+				break
+			}
+		}
+		if isFound && !reverse {
+			newIPs = append(newIPs, ip)
+			continue
+		}
+		if !isFound && reverse {
+			newIPs = append(newIPs, ip)
+			continue
+		}
+	}
+	return newIPs
+}
diff --git a/infra/conf/dns.go b/infra/conf/dns.go
index 7baeda87..930f1a73 100644
--- a/infra/conf/dns.go
+++ b/infra/conf/dns.go
@@ -12,17 +12,21 @@ import (
 )
 
 type NameServerConfig struct {
-	Address            *Address   `json:"address"`
-	ClientIP           *Address   `json:"clientIp"`
-	Port               uint16     `json:"port"`
-	SkipFallback       bool       `json:"skipFallback"`
-	Domains            []string   `json:"domains"`
-	ExpectedIPs        StringList `json:"expectedIPs"`
-	ExpectIPs          StringList `json:"expectIPs"`
-	QueryStrategy      string     `json:"queryStrategy"`
-	AllowUnexpectedIPs bool       `json:"allowUnexpectedIps"`
-	Tag                string     `json:"tag"`
-	TimeoutMs          uint64     `json:"timeoutMs"`
+	Address       *Address   `json:"address"`
+	ClientIP      *Address   `json:"clientIp"`
+	Port          uint16     `json:"port"`
+	SkipFallback  bool       `json:"skipFallback"`
+	Domains       []string   `json:"domains"`
+	ExpectedIPs   StringList `json:"expectedIPs"`
+	ExpectIPs     StringList `json:"expectIPs"`
+	QueryStrategy string     `json:"queryStrategy"`
+	PriorIPs      StringList `json:"priorIPs"`
+	Tag           string     `json:"tag"`
+	TimeoutMs     uint64     `json:"timeoutMs"`
+	DisableCache  bool       `json:"disableCache"`
+	FinalQuery    bool       `json:"finalQuery"`
+	UnexpectedIPs StringList `json:"unexpectedIPs"`
+	UnpriorIPs    StringList `json:"unpriorIPs"`
 }
 
 // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
@@ -34,17 +38,21 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
 	}
 
 	var advanced struct {
-		Address            *Address   `json:"address"`
-		ClientIP           *Address   `json:"clientIp"`
-		Port               uint16     `json:"port"`
-		SkipFallback       bool       `json:"skipFallback"`
-		Domains            []string   `json:"domains"`
-		ExpectedIPs        StringList `json:"expectedIPs"`
-		ExpectIPs          StringList `json:"expectIPs"`
-		QueryStrategy      string     `json:"queryStrategy"`
-		AllowUnexpectedIPs bool       `json:"allowUnexpectedIps"`
-		Tag                string     `json:"tag"`
-		TimeoutMs          uint64     `json:"timeoutMs"`
+		Address       *Address   `json:"address"`
+		ClientIP      *Address   `json:"clientIp"`
+		Port          uint16     `json:"port"`
+		SkipFallback  bool       `json:"skipFallback"`
+		Domains       []string   `json:"domains"`
+		ExpectedIPs   StringList `json:"expectedIPs"`
+		ExpectIPs     StringList `json:"expectIPs"`
+		QueryStrategy string     `json:"queryStrategy"`
+		PriorIPs      StringList `json:"priorIPs"`
+		Tag           string     `json:"tag"`
+		TimeoutMs     uint64     `json:"timeoutMs"`
+		DisableCache  bool       `json:"disableCache"`
+		FinalQuery    bool       `json:"finalQuery"`
+		UnexpectedIPs StringList `json:"unexpectedIPs"`
+		UnpriorIPs    StringList `json:"unpriorIPs"`
 	}
 	if err := json.Unmarshal(data, &advanced); err == nil {
 		c.Address = advanced.Address
@@ -55,9 +63,13 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
 		c.ExpectedIPs = advanced.ExpectedIPs
 		c.ExpectIPs = advanced.ExpectIPs
 		c.QueryStrategy = advanced.QueryStrategy
-		c.AllowUnexpectedIPs = advanced.AllowUnexpectedIPs
+		c.PriorIPs = advanced.PriorIPs
 		c.Tag = advanced.Tag
 		c.TimeoutMs = advanced.TimeoutMs
+		c.DisableCache = advanced.DisableCache
+		c.FinalQuery = advanced.FinalQuery
+		c.UnexpectedIPs = advanced.UnexpectedIPs
+		c.UnpriorIPs = advanced.UnpriorIPs
 		return nil
 	}
 
@@ -109,9 +121,21 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
 	if len(expectedIPs) == 0 {
 		expectedIPs = c.ExpectIPs
 	}
-	geoipList, err := ToCidrList(expectedIPs)
+	expectedGeoipList, err := ToCidrList(expectedIPs)
 	if err != nil {
-		return nil, errors.New("invalid IP rule: ", expectedIPs).Base(err)
+		return nil, errors.New("invalid expected IP rule: ", expectedIPs).Base(err)
+	}
+	priorGeoipList, err := ToCidrList(c.PriorIPs)
+	if err != nil {
+		return nil, errors.New("invalid prior IP rule: ", c.PriorIPs).Base(err)
+	}
+	unexpectedGeoipList, err := ToCidrList(c.UnexpectedIPs)
+	if err != nil {
+		return nil, errors.New("invalid unexpected IP rule: ", c.UnexpectedIPs).Base(err)
+	}
+	unpriorGeoipList, err := ToCidrList(c.UnpriorIPs)
+	if err != nil {
+		return nil, errors.New("invalid unprior IP rule: ", c.UnpriorIPs).Base(err)
 	}
 
 	var myClientIP []byte
@@ -128,15 +152,19 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
 			Address: c.Address.Build(),
 			Port:    uint32(c.Port),
 		},
-		ClientIp:           myClientIP,
-		SkipFallback:       c.SkipFallback,
-		PrioritizedDomain:  domains,
-		Geoip:              geoipList,
-		OriginalRules:      originalRules,
-		QueryStrategy:      resolveQueryStrategy(c.QueryStrategy),
-		AllowUnexpectedIPs: c.AllowUnexpectedIPs,
-		Tag:                c.Tag,
-		TimeoutMs:          c.TimeoutMs,
+		ClientIp:          myClientIP,
+		SkipFallback:      c.SkipFallback,
+		PrioritizedDomain: domains,
+		ExpectedGeoip:     expectedGeoipList,
+		OriginalRules:     originalRules,
+		QueryStrategy:     resolveQueryStrategy(c.QueryStrategy),
+		PriorGeoip:        priorGeoipList,
+		Tag:               c.Tag,
+		TimeoutMs:         c.TimeoutMs,
+		DisableCache:      c.DisableCache,
+		FinalQuery:        c.FinalQuery,
+		UnexpectedGeoip:   unexpectedGeoipList,
+		UnpriorGeoip:      unpriorGeoipList,
 	}, nil
 }