Meo597 пре 3 месеци
родитељ
комит
af968ebd37
6 измењених фајлова са 822 додато и 964 уклоњено
  1. 61 256
      app/dns/config.pb.go
  2. 4 24
      app/dns/config.proto
  3. 88 609
      app/router/config.pb.go
  4. 14 75
      app/router/config.proto
  5. 591 0
      common/geodata/geodat.pb.go
  6. 64 0
      common/geodata/geodat.proto

+ 61 - 256
app/dns/config.pb.go

@@ -7,7 +7,6 @@
 package dns
 
 import (
-	router "github.com/xtls/xray-core/app/router"
 	net "github.com/xtls/xray-core/common/net"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -23,58 +22,6 @@ const (
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-type DomainMatchingType int32
-
-const (
-	DomainMatchingType_Full      DomainMatchingType = 0
-	DomainMatchingType_Subdomain DomainMatchingType = 1
-	DomainMatchingType_Keyword   DomainMatchingType = 2
-	DomainMatchingType_Regex     DomainMatchingType = 3
-)
-
-// Enum value maps for DomainMatchingType.
-var (
-	DomainMatchingType_name = map[int32]string{
-		0: "Full",
-		1: "Subdomain",
-		2: "Keyword",
-		3: "Regex",
-	}
-	DomainMatchingType_value = map[string]int32{
-		"Full":      0,
-		"Subdomain": 1,
-		"Keyword":   2,
-		"Regex":     3,
-	}
-)
-
-func (x DomainMatchingType) Enum() *DomainMatchingType {
-	p := new(DomainMatchingType)
-	*p = x
-	return p
-}
-
-func (x DomainMatchingType) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
-	return file_app_dns_config_proto_enumTypes[0].Descriptor()
-}
-
-func (DomainMatchingType) Type() protoreflect.EnumType {
-	return &file_app_dns_config_proto_enumTypes[0]
-}
-
-func (x DomainMatchingType) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use DomainMatchingType.Descriptor instead.
-func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
-	return file_app_dns_config_proto_rawDescGZIP(), []int{0}
-}
-
 type QueryStrategy int32
 
 const (
@@ -111,11 +58,11 @@ func (x QueryStrategy) String() string {
 }
 
 func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
-	return file_app_dns_config_proto_enumTypes[1].Descriptor()
+	return file_app_dns_config_proto_enumTypes[0].Descriptor()
 }
 
 func (QueryStrategy) Type() protoreflect.EnumType {
-	return &file_app_dns_config_proto_enumTypes[1]
+	return &file_app_dns_config_proto_enumTypes[0]
 }
 
 func (x QueryStrategy) Number() protoreflect.EnumNumber {
@@ -124,30 +71,29 @@ func (x QueryStrategy) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use QueryStrategy.Descriptor instead.
 func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
-	return file_app_dns_config_proto_rawDescGZIP(), []int{1}
+	return file_app_dns_config_proto_rawDescGZIP(), []int{0}
 }
 
 type NameServer struct {
-	state             protoimpl.MessageState       `protogen:"open.v1"`
-	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"`
-	ActPrior          bool                         `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,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,oneof" json:"disableCache,omitempty"`
-	ServeStale        *bool                        `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
-	ServeExpiredTTL   *uint32                      `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,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"`
-	ActUnprior        bool                         `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
-	PolicyID          uint32                       `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
-	unknownFields     protoimpl.UnknownFields
-	sizeCache         protoimpl.SizeCache
+	state           protoimpl.MessageState `protogen:"open.v1"`
+	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"`
+	Domain          []string               `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
+	ExpectedIp      []string               `protobuf:"bytes,3,rep,name=expected_ip,json=expectedIp,proto3" json:"expected_ip,omitempty"`
+	QueryStrategy   QueryStrategy          `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
+	ActPrior        bool                   `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,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,oneof" json:"disableCache,omitempty"`
+	ServeStale      *bool                  `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
+	ServeExpiredTTL *uint32                `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,omitempty"`
+	FinalQuery      bool                   `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
+	UnexpectedIp    []string               `protobuf:"bytes,13,rep,name=unexpected_ip,json=unexpectedIp,proto3" json:"unexpected_ip,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"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *NameServer) Reset() {
@@ -201,23 +147,16 @@ func (x *NameServer) GetSkipFallback() bool {
 	return false
 }
 
-func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
-	if x != nil {
-		return x.PrioritizedDomain
-	}
-	return nil
-}
-
-func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
+func (x *NameServer) GetDomain() []string {
 	if x != nil {
-		return x.ExpectedGeoip
+		return x.Domain
 	}
 	return nil
 }
 
-func (x *NameServer) GetOriginalRules() []*NameServer_OriginalRule {
+func (x *NameServer) GetExpectedIp() []string {
 	if x != nil {
-		return x.OriginalRules
+		return x.ExpectedIp
 	}
 	return nil
 }
@@ -278,9 +217,9 @@ func (x *NameServer) GetFinalQuery() bool {
 	return false
 }
 
-func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
+func (x *NameServer) GetUnexpectedIp() []string {
 	if x != nil {
-		return x.UnexpectedGeoip
+		return x.UnexpectedIp
 	}
 	return nil
 }
@@ -429,113 +368,8 @@ func (x *Config) GetEnableParallelQuery() bool {
 	return false
 }
 
-type NameServer_PriorityDomain struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	Type          DomainMatchingType     `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
-	Domain        string                 `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *NameServer_PriorityDomain) Reset() {
-	*x = NameServer_PriorityDomain{}
-	mi := &file_app_dns_config_proto_msgTypes[2]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *NameServer_PriorityDomain) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*NameServer_PriorityDomain) ProtoMessage() {}
-
-func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
-	mi := &file_app_dns_config_proto_msgTypes[2]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use NameServer_PriorityDomain.ProtoReflect.Descriptor instead.
-func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
-	return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
-	if x != nil {
-		return x.Type
-	}
-	return DomainMatchingType_Full
-}
-
-func (x *NameServer_PriorityDomain) GetDomain() string {
-	if x != nil {
-		return x.Domain
-	}
-	return ""
-}
-
-type NameServer_OriginalRule struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	Rule          string                 `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
-	Size          uint32                 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *NameServer_OriginalRule) Reset() {
-	*x = NameServer_OriginalRule{}
-	mi := &file_app_dns_config_proto_msgTypes[3]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *NameServer_OriginalRule) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*NameServer_OriginalRule) ProtoMessage() {}
-
-func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
-	mi := &file_app_dns_config_proto_msgTypes[3]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
-func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
-	return file_app_dns_config_proto_rawDescGZIP(), []int{0, 1}
-}
-
-func (x *NameServer_OriginalRule) GetRule() string {
-	if x != nil {
-		return x.Rule
-	}
-	return ""
-}
-
-func (x *NameServer_OriginalRule) GetSize() uint32 {
-	if x != nil {
-		return x.Size
-	}
-	return 0
-}
-
 type Config_HostMapping struct {
 	state  protoimpl.MessageState `protogen:"open.v1"`
-	Type   DomainMatchingType     `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
 	Domain string                 `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
 	Ip     [][]byte               `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
 	// ProxiedDomain indicates the mapped domain has the same IP address on this
@@ -547,7 +381,7 @@ type Config_HostMapping struct {
 
 func (x *Config_HostMapping) Reset() {
 	*x = Config_HostMapping{}
-	mi := &file_app_dns_config_proto_msgTypes[4]
+	mi := &file_app_dns_config_proto_msgTypes[2]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -559,7 +393,7 @@ func (x *Config_HostMapping) String() string {
 func (*Config_HostMapping) ProtoMessage() {}
 
 func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
-	mi := &file_app_dns_config_proto_msgTypes[4]
+	mi := &file_app_dns_config_proto_msgTypes[2]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -575,13 +409,6 @@ func (*Config_HostMapping) Descriptor() ([]byte, []int) {
 	return file_app_dns_config_proto_rawDescGZIP(), []int{1, 0}
 }
 
-func (x *Config_HostMapping) GetType() DomainMatchingType {
-	if x != nil {
-		return x.Type
-	}
-	return DomainMatchingType_Full
-}
-
 func (x *Config_HostMapping) GetDomain() string {
 	if x != nil {
 		return x.Domain
@@ -607,15 +434,15 @@ var File_app_dns_config_proto protoreflect.FileDescriptor
 
 const file_app_dns_config_proto_rawDesc = "" +
 	"\n" +
-	"\x14app/dns/config.proto\x12\fxray.app.dns\x1a\x1ccommon/net/destination.proto\x1a\x17app/router/config.proto\"\xdf\a\n" +
+	"\x14app/dns/config.proto\x12\fxray.app.dns\x1a\x1ccommon/net/destination.proto\"\x83\x05\n" +
 	"\n" +
 	"NameServer\x123\n" +
 	"\aaddress\x18\x01 \x01(\v2\x19.xray.common.net.EndpointR\aaddress\x12\x1b\n" +
 	"\tclient_ip\x18\x05 \x01(\fR\bclientIp\x12\"\n" +
-	"\fskipFallback\x18\x06 \x01(\bR\fskipFallback\x12V\n" +
-	"\x12prioritized_domain\x18\x02 \x03(\v2'.xray.app.dns.NameServer.PriorityDomainR\x11prioritizedDomain\x12=\n" +
-	"\x0eexpected_geoip\x18\x03 \x03(\v2\x16.xray.app.router.GeoIPR\rexpectedGeoip\x12L\n" +
-	"\x0eoriginal_rules\x18\x04 \x03(\v2%.xray.app.dns.NameServer.OriginalRuleR\roriginalRules\x12B\n" +
+	"\fskipFallback\x18\x06 \x01(\bR\fskipFallback\x12\x16\n" +
+	"\x06domain\x18\x02 \x03(\tR\x06domain\x12\x1f\n" +
+	"\vexpected_ip\x18\x03 \x03(\tR\n" +
+	"expectedIp\x12B\n" +
 	"\x0equery_strategy\x18\a \x01(\x0e2\x1b.xray.app.dns.QueryStrategyR\rqueryStrategy\x12\x1a\n" +
 	"\bactPrior\x18\b \x01(\bR\bactPrior\x12\x10\n" +
 	"\x03tag\x18\t \x01(\tR\x03tag\x12\x1c\n" +
@@ -628,21 +455,15 @@ const file_app_dns_config_proto_rawDesc = "" +
 	"\x0fserveExpiredTTL\x18\x10 \x01(\rH\x02R\x0fserveExpiredTTL\x88\x01\x01\x12\x1e\n" +
 	"\n" +
 	"finalQuery\x18\f \x01(\bR\n" +
-	"finalQuery\x12A\n" +
-	"\x10unexpected_geoip\x18\r \x03(\v2\x16.xray.app.router.GeoIPR\x0funexpectedGeoip\x12\x1e\n" +
+	"finalQuery\x12#\n" +
+	"\runexpected_ip\x18\r \x03(\tR\funexpectedIp\x12\x1e\n" +
 	"\n" +
 	"actUnprior\x18\x0e \x01(\bR\n" +
 	"actUnprior\x12\x1a\n" +
-	"\bpolicyID\x18\x11 \x01(\rR\bpolicyID\x1a^\n" +
-	"\x0ePriorityDomain\x124\n" +
-	"\x04type\x18\x01 \x01(\x0e2 .xray.app.dns.DomainMatchingTypeR\x04type\x12\x16\n" +
-	"\x06domain\x18\x02 \x01(\tR\x06domain\x1a6\n" +
-	"\fOriginalRule\x12\x12\n" +
-	"\x04rule\x18\x01 \x01(\tR\x04rule\x12\x12\n" +
-	"\x04size\x18\x02 \x01(\rR\x04sizeB\x0f\n" +
+	"\bpolicyID\x18\x11 \x01(\rR\bpolicyIDB\x0f\n" +
 	"\r_disableCacheB\r\n" +
 	"\v_serveStaleB\x12\n" +
-	"\x10_serveExpiredTTL\"\x98\x05\n" +
+	"\x10_serveExpiredTTLJ\x04\b\x04\x10\x05\"\xe1\x04\n" +
 	"\x06Config\x129\n" +
 	"\vname_server\x18\x05 \x03(\v2\x18.xray.app.dns.NameServerR\n" +
 	"nameServer\x12\x1b\n" +
@@ -658,17 +479,11 @@ const file_app_dns_config_proto_rawDesc = "" +
 	"\x0fdisableFallback\x18\n" +
 	" \x01(\bR\x0fdisableFallback\x126\n" +
 	"\x16disableFallbackIfMatch\x18\v \x01(\bR\x16disableFallbackIfMatch\x120\n" +
-	"\x13enableParallelQuery\x18\x0e \x01(\bR\x13enableParallelQuery\x1a\x92\x01\n" +
-	"\vHostMapping\x124\n" +
-	"\x04type\x18\x01 \x01(\x0e2 .xray.app.dns.DomainMatchingTypeR\x04type\x12\x16\n" +
+	"\x13enableParallelQuery\x18\x0e \x01(\bR\x13enableParallelQuery\x1a\\\n" +
+	"\vHostMapping\x12\x16\n" +
 	"\x06domain\x18\x02 \x01(\tR\x06domain\x12\x0e\n" +
 	"\x02ip\x18\x03 \x03(\fR\x02ip\x12%\n" +
-	"\x0eproxied_domain\x18\x04 \x01(\tR\rproxiedDomainJ\x04\b\a\x10\b*E\n" +
-	"\x12DomainMatchingType\x12\b\n" +
-	"\x04Full\x10\x00\x12\r\n" +
-	"\tSubdomain\x10\x01\x12\v\n" +
-	"\aKeyword\x10\x02\x12\t\n" +
-	"\x05Regex\x10\x03*B\n" +
+	"\x0eproxied_domain\x18\x04 \x01(\tR\rproxiedDomainJ\x04\b\a\x10\b*B\n" +
 	"\rQueryStrategy\x12\n" +
 	"\n" +
 	"\x06USE_IP\x10\x00\x12\v\n" +
@@ -689,36 +504,26 @@ func file_app_dns_config_proto_rawDescGZIP() []byte {
 	return file_app_dns_config_proto_rawDescData
 }
 
-var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
-var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
 var file_app_dns_config_proto_goTypes = []any{
-	(DomainMatchingType)(0),           // 0: xray.app.dns.DomainMatchingType
-	(QueryStrategy)(0),                // 1: xray.app.dns.QueryStrategy
-	(*NameServer)(nil),                // 2: xray.app.dns.NameServer
-	(*Config)(nil),                    // 3: xray.app.dns.Config
-	(*NameServer_PriorityDomain)(nil), // 4: xray.app.dns.NameServer.PriorityDomain
-	(*NameServer_OriginalRule)(nil),   // 5: xray.app.dns.NameServer.OriginalRule
-	(*Config_HostMapping)(nil),        // 6: xray.app.dns.Config.HostMapping
-	(*net.Endpoint)(nil),              // 7: xray.common.net.Endpoint
-	(*router.GeoIP)(nil),              // 8: xray.app.router.GeoIP
+	(QueryStrategy)(0),         // 0: xray.app.dns.QueryStrategy
+	(*NameServer)(nil),         // 1: xray.app.dns.NameServer
+	(*Config)(nil),             // 2: xray.app.dns.Config
+	(*Config_HostMapping)(nil), // 3: xray.app.dns.Config.HostMapping
+	(*net.Endpoint)(nil),       // 4: xray.common.net.Endpoint
 }
 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.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
-	8,  // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
-	2,  // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
-	6,  // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
-	1,  // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
-	0,  // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
-	0,  // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
-	11, // [11:11] is the sub-list for method output_type
-	11, // [11:11] is the sub-list for method input_type
-	11, // [11:11] is the sub-list for extension type_name
-	11, // [11:11] is the sub-list for extension extendee
-	0,  // [0:11] is the sub-list for field type_name
+	4, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
+	0, // 1: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
+	1, // 2: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
+	3, // 3: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
+	0, // 4: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
+	5, // [5:5] is the sub-list for method output_type
+	5, // [5:5] is the sub-list for method input_type
+	5, // [5:5] is the sub-list for extension type_name
+	5, // [5:5] is the sub-list for extension extendee
+	0, // [0:5] is the sub-list for field type_name
 }
 
 func init() { file_app_dns_config_proto_init() }
@@ -732,8 +537,8 @@ func file_app_dns_config_proto_init() {
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dns_config_proto_rawDesc), len(file_app_dns_config_proto_rawDesc)),
-			NumEnums:      2,
-			NumMessages:   5,
+			NumEnums:      1,
+			NumMessages:   3,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

+ 4 - 24
app/dns/config.proto

@@ -7,26 +7,14 @@ option java_package = "com.xray.app.dns";
 option java_multiple_files = true;
 
 import "common/net/destination.proto";
-import "app/router/config.proto";
 
 message NameServer {
   xray.common.net.Endpoint address = 1;
   bytes client_ip = 5;
   bool skipFallback = 6;
-
-  message PriorityDomain {
-    DomainMatchingType type = 1;
-    string domain = 2;
-  }
-
-  message OriginalRule {
-    string rule = 1;
-    uint32 size = 2;
-  }
-
-  repeated PriorityDomain prioritized_domain = 2;
-  repeated xray.app.router.GeoIP expected_geoip = 3;
-  repeated OriginalRule original_rules = 4;
+  repeated string domain = 2;
+  repeated string expected_ip = 3;
+  reserved 4;
   QueryStrategy query_strategy = 7;
   bool actPrior = 8;
   string tag = 9;
@@ -35,18 +23,11 @@ message NameServer {
   optional bool serveStale = 15;
   optional uint32 serveExpiredTTL = 16;
   bool finalQuery = 12;
-  repeated xray.app.router.GeoIP unexpected_geoip = 13;
+  repeated string unexpected_ip = 13;
   bool actUnprior = 14;
   uint32 policyID = 17;
 }
 
-enum DomainMatchingType {
-  Full = 0;
-  Subdomain = 1;
-  Keyword = 2;
-  Regex = 3;
-}
-
 enum QueryStrategy {
   USE_IP = 0;
   USE_IP4 = 1;
@@ -64,7 +45,6 @@ message Config {
   bytes client_ip = 3;
 
   message HostMapping {
-    DomainMatchingType type = 1;
     string domain = 2;
 
     repeated bytes ip = 3;

+ 88 - 609
app/router/config.pb.go

@@ -23,63 +23,6 @@ const (
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-// Type of domain value.
-type Domain_Type int32
-
-const (
-	// The value is used as is.
-	Domain_Plain Domain_Type = 0
-	// The value is used as a regular expression.
-	Domain_Regex Domain_Type = 1
-	// The value is a root domain.
-	Domain_Domain Domain_Type = 2
-	// The value is a domain.
-	Domain_Full Domain_Type = 3
-)
-
-// Enum value maps for Domain_Type.
-var (
-	Domain_Type_name = map[int32]string{
-		0: "Plain",
-		1: "Regex",
-		2: "Domain",
-		3: "Full",
-	}
-	Domain_Type_value = map[string]int32{
-		"Plain":  0,
-		"Regex":  1,
-		"Domain": 2,
-		"Full":   3,
-	}
-)
-
-func (x Domain_Type) Enum() *Domain_Type {
-	p := new(Domain_Type)
-	*p = x
-	return p
-}
-
-func (x Domain_Type) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
-	return file_app_router_config_proto_enumTypes[0].Descriptor()
-}
-
-func (Domain_Type) Type() protoreflect.EnumType {
-	return &file_app_router_config_proto_enumTypes[0]
-}
-
-func (x Domain_Type) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use Domain_Type.Descriptor instead.
-func (Domain_Type) EnumDescriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{0, 0}
-}
-
 type Config_DomainStrategy int32
 
 const (
@@ -116,11 +59,11 @@ func (x Config_DomainStrategy) String() string {
 }
 
 func (Config_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
-	return file_app_router_config_proto_enumTypes[1].Descriptor()
+	return file_app_router_config_proto_enumTypes[0].Descriptor()
 }
 
 func (Config_DomainStrategy) Type() protoreflect.EnumType {
-	return &file_app_router_config_proto_enumTypes[1]
+	return &file_app_router_config_proto_enumTypes[0]
 }
 
 func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
@@ -129,326 +72,7 @@ func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Config_DomainStrategy.Descriptor instead.
 func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{11, 0}
-}
-
-// Domain for routing decision.
-type Domain struct {
-	state protoimpl.MessageState `protogen:"open.v1"`
-	// Domain matching type.
-	Type Domain_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.router.Domain_Type" json:"type,omitempty"`
-	// Domain value.
-	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
-	// Attributes of this domain. May be used for filtering.
-	Attribute     []*Domain_Attribute `protobuf:"bytes,3,rep,name=attribute,proto3" json:"attribute,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *Domain) Reset() {
-	*x = Domain{}
-	mi := &file_app_router_config_proto_msgTypes[0]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *Domain) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Domain) ProtoMessage() {}
-
-func (x *Domain) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[0]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
-func (*Domain) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Domain) GetType() Domain_Type {
-	if x != nil {
-		return x.Type
-	}
-	return Domain_Plain
-}
-
-func (x *Domain) GetValue() string {
-	if x != nil {
-		return x.Value
-	}
-	return ""
-}
-
-func (x *Domain) GetAttribute() []*Domain_Attribute {
-	if x != nil {
-		return x.Attribute
-	}
-	return nil
-}
-
-// IP for routing decision, in CIDR form.
-type CIDR struct {
-	state protoimpl.MessageState `protogen:"open.v1"`
-	// IP address, should be either 4 or 16 bytes.
-	Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
-	// Number of leading ones in the network mask.
-	Prefix        uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *CIDR) Reset() {
-	*x = CIDR{}
-	mi := &file_app_router_config_proto_msgTypes[1]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *CIDR) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CIDR) ProtoMessage() {}
-
-func (x *CIDR) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[1]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CIDR.ProtoReflect.Descriptor instead.
-func (*CIDR) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *CIDR) GetIp() []byte {
-	if x != nil {
-		return x.Ip
-	}
-	return nil
-}
-
-func (x *CIDR) GetPrefix() uint32 {
-	if x != nil {
-		return x.Prefix
-	}
-	return 0
-}
-
-type GeoIP struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	CountryCode   string                 `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
-	Cidr          []*CIDR                `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
-	ReverseMatch  bool                   `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *GeoIP) Reset() {
-	*x = GeoIP{}
-	mi := &file_app_router_config_proto_msgTypes[2]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *GeoIP) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GeoIP) ProtoMessage() {}
-
-func (x *GeoIP) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[2]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
-func (*GeoIP) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *GeoIP) GetCountryCode() string {
-	if x != nil {
-		return x.CountryCode
-	}
-	return ""
-}
-
-func (x *GeoIP) GetCidr() []*CIDR {
-	if x != nil {
-		return x.Cidr
-	}
-	return nil
-}
-
-func (x *GeoIP) GetReverseMatch() bool {
-	if x != nil {
-		return x.ReverseMatch
-	}
-	return false
-}
-
-type GeoIPList struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	Entry         []*GeoIP               `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *GeoIPList) Reset() {
-	*x = GeoIPList{}
-	mi := &file_app_router_config_proto_msgTypes[3]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *GeoIPList) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GeoIPList) ProtoMessage() {}
-
-func (x *GeoIPList) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[3]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
-func (*GeoIPList) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *GeoIPList) GetEntry() []*GeoIP {
-	if x != nil {
-		return x.Entry
-	}
-	return nil
-}
-
-type GeoSite struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	CountryCode   string                 `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
-	Domain        []*Domain              `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *GeoSite) Reset() {
-	*x = GeoSite{}
-	mi := &file_app_router_config_proto_msgTypes[4]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *GeoSite) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GeoSite) ProtoMessage() {}
-
-func (x *GeoSite) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[4]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GeoSite.ProtoReflect.Descriptor instead.
-func (*GeoSite) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *GeoSite) GetCountryCode() string {
-	if x != nil {
-		return x.CountryCode
-	}
-	return ""
-}
-
-func (x *GeoSite) GetDomain() []*Domain {
-	if x != nil {
-		return x.Domain
-	}
-	return nil
-}
-
-type GeoSiteList struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	Entry         []*GeoSite             `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *GeoSiteList) Reset() {
-	*x = GeoSiteList{}
-	mi := &file_app_router_config_proto_msgTypes[5]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *GeoSiteList) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GeoSiteList) ProtoMessage() {}
-
-func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[5]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GeoSiteList.ProtoReflect.Descriptor instead.
-func (*GeoSiteList) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{5}
-}
-
-func (x *GeoSiteList) GetEntry() []*GeoSite {
-	if x != nil {
-		return x.Entry
-	}
-	return nil
+	return file_app_router_config_proto_rawDescGZIP(), []int{5, 0}
 }
 
 type RoutingRule struct {
@@ -460,37 +84,35 @@ type RoutingRule struct {
 	TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
 	RuleTag   string                  `protobuf:"bytes,19,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
 	// List of domains for target domain matching.
-	Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
-	// List of GeoIPs for target IP address matching. If this entry exists, the
-	// cidr above will have no effect. GeoIP fields with the same country code are
-	// supposed to contain exactly same content. They will be merged during
-	// runtime. For customized GeoIPs, please leave country code empty.
-	Geoip []*GeoIP `protobuf:"bytes,10,rep,name=geoip,proto3" json:"geoip,omitempty"`
-	// List of ports.
+	Domain []string `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
+	// List of IPs for target IP address matching.
+	Ip []string `protobuf:"bytes,10,rep,name=ip,proto3" json:"ip,omitempty"`
+	// List of ports for target port matching.
 	PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
 	// List of networks for matching.
 	Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
-	// List of GeoIPs for source IP address matching. If this entry exists, the
-	// source_cidr above will have no effect.
-	SourceGeoip []*GeoIP `protobuf:"bytes,11,rep,name=source_geoip,json=sourceGeoip,proto3" json:"source_geoip,omitempty"`
+	// List of IPs for source IP address matching.
+	SourceIp []string `protobuf:"bytes,11,rep,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"`
 	// List of ports for source port matching.
 	SourcePortList *net.PortList     `protobuf:"bytes,16,opt,name=source_port_list,json=sourcePortList,proto3" json:"source_port_list,omitempty"`
 	UserEmail      []string          `protobuf:"bytes,7,rep,name=user_email,json=userEmail,proto3" json:"user_email,omitempty"`
 	InboundTag     []string          `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag,proto3" json:"inbound_tag,omitempty"`
 	Protocol       []string          `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
 	Attributes     map[string]string `protobuf:"bytes,15,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
-	LocalGeoip     []*GeoIP          `protobuf:"bytes,17,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
-	LocalPortList  *net.PortList     `protobuf:"bytes,18,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
-	VlessRouteList *net.PortList     `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
-	Process        []string          `protobuf:"bytes,21,rep,name=process,proto3" json:"process,omitempty"`
-	Webhook        *WebhookConfig    `protobuf:"bytes,22,opt,name=webhook,proto3" json:"webhook,omitempty"`
+	// List of IPs for local IP address matching.
+	LocalIp []string `protobuf:"bytes,17,rep,name=local_ip,json=localIp,proto3" json:"local_ip,omitempty"`
+	// List of ports for local port matching.
+	LocalPortList  *net.PortList  `protobuf:"bytes,18,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
+	VlessRouteList *net.PortList  `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
+	Process        []string       `protobuf:"bytes,21,rep,name=process,proto3" json:"process,omitempty"`
+	Webhook        *WebhookConfig `protobuf:"bytes,22,opt,name=webhook,proto3" json:"webhook,omitempty"`
 	unknownFields  protoimpl.UnknownFields
 	sizeCache      protoimpl.SizeCache
 }
 
 func (x *RoutingRule) Reset() {
 	*x = RoutingRule{}
-	mi := &file_app_router_config_proto_msgTypes[6]
+	mi := &file_app_router_config_proto_msgTypes[0]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -502,7 +124,7 @@ func (x *RoutingRule) String() string {
 func (*RoutingRule) ProtoMessage() {}
 
 func (x *RoutingRule) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[6]
+	mi := &file_app_router_config_proto_msgTypes[0]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -515,7 +137,7 @@ func (x *RoutingRule) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RoutingRule.ProtoReflect.Descriptor instead.
 func (*RoutingRule) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{6}
+	return file_app_router_config_proto_rawDescGZIP(), []int{0}
 }
 
 func (x *RoutingRule) GetTargetTag() isRoutingRule_TargetTag {
@@ -550,16 +172,16 @@ func (x *RoutingRule) GetRuleTag() string {
 	return ""
 }
 
-func (x *RoutingRule) GetDomain() []*Domain {
+func (x *RoutingRule) GetDomain() []string {
 	if x != nil {
 		return x.Domain
 	}
 	return nil
 }
 
-func (x *RoutingRule) GetGeoip() []*GeoIP {
+func (x *RoutingRule) GetIp() []string {
 	if x != nil {
-		return x.Geoip
+		return x.Ip
 	}
 	return nil
 }
@@ -578,9 +200,9 @@ func (x *RoutingRule) GetNetworks() []net.Network {
 	return nil
 }
 
-func (x *RoutingRule) GetSourceGeoip() []*GeoIP {
+func (x *RoutingRule) GetSourceIp() []string {
 	if x != nil {
-		return x.SourceGeoip
+		return x.SourceIp
 	}
 	return nil
 }
@@ -620,9 +242,9 @@ func (x *RoutingRule) GetAttributes() map[string]string {
 	return nil
 }
 
-func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
+func (x *RoutingRule) GetLocalIp() []string {
 	if x != nil {
-		return x.LocalGeoip
+		return x.LocalIp
 	}
 	return nil
 }
@@ -684,7 +306,7 @@ type WebhookConfig struct {
 
 func (x *WebhookConfig) Reset() {
 	*x = WebhookConfig{}
-	mi := &file_app_router_config_proto_msgTypes[7]
+	mi := &file_app_router_config_proto_msgTypes[1]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -696,7 +318,7 @@ func (x *WebhookConfig) String() string {
 func (*WebhookConfig) ProtoMessage() {}
 
 func (x *WebhookConfig) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[7]
+	mi := &file_app_router_config_proto_msgTypes[1]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -709,7 +331,7 @@ func (x *WebhookConfig) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use WebhookConfig.ProtoReflect.Descriptor instead.
 func (*WebhookConfig) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{7}
+	return file_app_router_config_proto_rawDescGZIP(), []int{1}
 }
 
 func (x *WebhookConfig) GetUrl() string {
@@ -746,7 +368,7 @@ type BalancingRule struct {
 
 func (x *BalancingRule) Reset() {
 	*x = BalancingRule{}
-	mi := &file_app_router_config_proto_msgTypes[8]
+	mi := &file_app_router_config_proto_msgTypes[2]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -758,7 +380,7 @@ func (x *BalancingRule) String() string {
 func (*BalancingRule) ProtoMessage() {}
 
 func (x *BalancingRule) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[8]
+	mi := &file_app_router_config_proto_msgTypes[2]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -771,7 +393,7 @@ func (x *BalancingRule) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BalancingRule.ProtoReflect.Descriptor instead.
 func (*BalancingRule) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{8}
+	return file_app_router_config_proto_rawDescGZIP(), []int{2}
 }
 
 func (x *BalancingRule) GetTag() string {
@@ -820,7 +442,7 @@ type StrategyWeight struct {
 
 func (x *StrategyWeight) Reset() {
 	*x = StrategyWeight{}
-	mi := &file_app_router_config_proto_msgTypes[9]
+	mi := &file_app_router_config_proto_msgTypes[3]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -832,7 +454,7 @@ func (x *StrategyWeight) String() string {
 func (*StrategyWeight) ProtoMessage() {}
 
 func (x *StrategyWeight) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[9]
+	mi := &file_app_router_config_proto_msgTypes[3]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -845,7 +467,7 @@ func (x *StrategyWeight) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use StrategyWeight.ProtoReflect.Descriptor instead.
 func (*StrategyWeight) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{9}
+	return file_app_router_config_proto_rawDescGZIP(), []int{3}
 }
 
 func (x *StrategyWeight) GetRegexp() bool {
@@ -887,7 +509,7 @@ type StrategyLeastLoadConfig struct {
 
 func (x *StrategyLeastLoadConfig) Reset() {
 	*x = StrategyLeastLoadConfig{}
-	mi := &file_app_router_config_proto_msgTypes[10]
+	mi := &file_app_router_config_proto_msgTypes[4]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -899,7 +521,7 @@ func (x *StrategyLeastLoadConfig) String() string {
 func (*StrategyLeastLoadConfig) ProtoMessage() {}
 
 func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[10]
+	mi := &file_app_router_config_proto_msgTypes[4]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -912,7 +534,7 @@ func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use StrategyLeastLoadConfig.ProtoReflect.Descriptor instead.
 func (*StrategyLeastLoadConfig) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{10}
+	return file_app_router_config_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *StrategyLeastLoadConfig) GetCosts() []*StrategyWeight {
@@ -961,7 +583,7 @@ type Config struct {
 
 func (x *Config) Reset() {
 	*x = Config{}
-	mi := &file_app_router_config_proto_msgTypes[11]
+	mi := &file_app_router_config_proto_msgTypes[5]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -973,7 +595,7 @@ func (x *Config) String() string {
 func (*Config) ProtoMessage() {}
 
 func (x *Config) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[11]
+	mi := &file_app_router_config_proto_msgTypes[5]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -986,7 +608,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Config.ProtoReflect.Descriptor instead.
 func (*Config) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{11}
+	return file_app_router_config_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *Config) GetDomainStrategy() Config_DomainStrategy {
@@ -1010,141 +632,21 @@ func (x *Config) GetBalancingRule() []*BalancingRule {
 	return nil
 }
 
-type Domain_Attribute struct {
-	state protoimpl.MessageState `protogen:"open.v1"`
-	Key   string                 `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
-	// Types that are valid to be assigned to TypedValue:
-	//
-	//	*Domain_Attribute_BoolValue
-	//	*Domain_Attribute_IntValue
-	TypedValue    isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
-}
-
-func (x *Domain_Attribute) Reset() {
-	*x = Domain_Attribute{}
-	mi := &file_app_router_config_proto_msgTypes[12]
-	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-	ms.StoreMessageInfo(mi)
-}
-
-func (x *Domain_Attribute) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Domain_Attribute) ProtoMessage() {}
-
-func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
-	mi := &file_app_router_config_proto_msgTypes[12]
-	if x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Domain_Attribute.ProtoReflect.Descriptor instead.
-func (*Domain_Attribute) Descriptor() ([]byte, []int) {
-	return file_app_router_config_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *Domain_Attribute) GetKey() string {
-	if x != nil {
-		return x.Key
-	}
-	return ""
-}
-
-func (x *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedValue {
-	if x != nil {
-		return x.TypedValue
-	}
-	return nil
-}
-
-func (x *Domain_Attribute) GetBoolValue() bool {
-	if x != nil {
-		if x, ok := x.TypedValue.(*Domain_Attribute_BoolValue); ok {
-			return x.BoolValue
-		}
-	}
-	return false
-}
-
-func (x *Domain_Attribute) GetIntValue() int64 {
-	if x != nil {
-		if x, ok := x.TypedValue.(*Domain_Attribute_IntValue); ok {
-			return x.IntValue
-		}
-	}
-	return 0
-}
-
-type isDomain_Attribute_TypedValue interface {
-	isDomain_Attribute_TypedValue()
-}
-
-type Domain_Attribute_BoolValue struct {
-	BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"`
-}
-
-type Domain_Attribute_IntValue struct {
-	IntValue int64 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
-}
-
-func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
-
-func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
-
 var File_app_router_config_proto protoreflect.FileDescriptor
 
 const file_app_router_config_proto_rawDesc = "" +
 	"\n" +
-	"\x17app/router/config.proto\x12\x0fxray.app.router\x1a!common/serial/typed_message.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\"\xb3\x02\n" +
-	"\x06Domain\x120\n" +
-	"\x04type\x18\x01 \x01(\x0e2\x1c.xray.app.router.Domain.TypeR\x04type\x12\x14\n" +
-	"\x05value\x18\x02 \x01(\tR\x05value\x12?\n" +
-	"\tattribute\x18\x03 \x03(\v2!.xray.app.router.Domain.AttributeR\tattribute\x1al\n" +
-	"\tAttribute\x12\x10\n" +
-	"\x03key\x18\x01 \x01(\tR\x03key\x12\x1f\n" +
-	"\n" +
-	"bool_value\x18\x02 \x01(\bH\x00R\tboolValue\x12\x1d\n" +
-	"\tint_value\x18\x03 \x01(\x03H\x00R\bintValueB\r\n" +
-	"\vtyped_value\"2\n" +
-	"\x04Type\x12\t\n" +
-	"\x05Plain\x10\x00\x12\t\n" +
-	"\x05Regex\x10\x01\x12\n" +
-	"\n" +
-	"\x06Domain\x10\x02\x12\b\n" +
-	"\x04Full\x10\x03\".\n" +
-	"\x04CIDR\x12\x0e\n" +
-	"\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" +
-	"\x06prefix\x18\x02 \x01(\rR\x06prefix\"z\n" +
-	"\x05GeoIP\x12!\n" +
-	"\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12)\n" +
-	"\x04cidr\x18\x02 \x03(\v2\x15.xray.app.router.CIDRR\x04cidr\x12#\n" +
-	"\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"9\n" +
-	"\tGeoIPList\x12,\n" +
-	"\x05entry\x18\x01 \x03(\v2\x16.xray.app.router.GeoIPR\x05entry\"]\n" +
-	"\aGeoSite\x12!\n" +
-	"\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12/\n" +
-	"\x06domain\x18\x02 \x03(\v2\x17.xray.app.router.DomainR\x06domain\"=\n" +
-	"\vGeoSiteList\x12.\n" +
-	"\x05entry\x18\x01 \x03(\v2\x18.xray.app.router.GeoSiteR\x05entry\"\xbc\a\n" +
+	"\x17app/router/config.proto\x12\x0fxray.app.router\x1a!common/serial/typed_message.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\"\xc9\x06\n" +
 	"\vRoutingRule\x12\x12\n" +
 	"\x03tag\x18\x01 \x01(\tH\x00R\x03tag\x12%\n" +
 	"\rbalancing_tag\x18\f \x01(\tH\x00R\fbalancingTag\x12\x19\n" +
-	"\brule_tag\x18\x13 \x01(\tR\aruleTag\x12/\n" +
-	"\x06domain\x18\x02 \x03(\v2\x17.xray.app.router.DomainR\x06domain\x12,\n" +
-	"\x05geoip\x18\n" +
-	" \x03(\v2\x16.xray.app.router.GeoIPR\x05geoip\x126\n" +
+	"\brule_tag\x18\x13 \x01(\tR\aruleTag\x12\x16\n" +
+	"\x06domain\x18\x02 \x03(\tR\x06domain\x12\x0e\n" +
+	"\x02ip\x18\n" +
+	" \x03(\tR\x02ip\x126\n" +
 	"\tport_list\x18\x0e \x01(\v2\x19.xray.common.net.PortListR\bportList\x124\n" +
-	"\bnetworks\x18\r \x03(\x0e2\x18.xray.common.net.NetworkR\bnetworks\x129\n" +
-	"\fsource_geoip\x18\v \x03(\v2\x16.xray.app.router.GeoIPR\vsourceGeoip\x12C\n" +
+	"\bnetworks\x18\r \x03(\x0e2\x18.xray.common.net.NetworkR\bnetworks\x12\x1b\n" +
+	"\tsource_ip\x18\v \x03(\tR\bsourceIp\x12C\n" +
 	"\x10source_port_list\x18\x10 \x01(\v2\x19.xray.common.net.PortListR\x0esourcePortList\x12\x1d\n" +
 	"\n" +
 	"user_email\x18\a \x03(\tR\tuserEmail\x12\x1f\n" +
@@ -1153,9 +655,8 @@ const file_app_router_config_proto_rawDesc = "" +
 	"\bprotocol\x18\t \x03(\tR\bprotocol\x12L\n" +
 	"\n" +
 	"attributes\x18\x0f \x03(\v2,.xray.app.router.RoutingRule.AttributesEntryR\n" +
-	"attributes\x127\n" +
-	"\vlocal_geoip\x18\x11 \x03(\v2\x16.xray.app.router.GeoIPR\n" +
-	"localGeoip\x12A\n" +
+	"attributes\x12\x19\n" +
+	"\blocal_ip\x18\x11 \x03(\tR\alocalIp\x12A\n" +
 	"\x0flocal_port_list\x18\x12 \x01(\v2\x19.xray.common.net.PortListR\rlocalPortList\x12C\n" +
 	"\x10vless_route_list\x18\x14 \x01(\v2\x19.xray.common.net.PortListR\x0evlessRouteList\x12\x18\n" +
 	"\aprocess\x18\x15 \x03(\tR\aprocess\x128\n" +
@@ -1187,16 +688,16 @@ const file_app_router_config_proto_rawDesc = "" +
 	"\tbaselines\x18\x03 \x03(\x03R\tbaselines\x12\x1a\n" +
 	"\bexpected\x18\x04 \x01(\x05R\bexpected\x12\x16\n" +
 	"\x06maxRTT\x18\x05 \x01(\x03R\x06maxRTT\x12\x1c\n" +
-	"\ttolerance\x18\x06 \x01(\x02R\ttolerance\"\x90\x02\n" +
+	"\ttolerance\x18\x06 \x01(\x02R\ttolerance\"\x96\x02\n" +
 	"\x06Config\x12O\n" +
 	"\x0fdomain_strategy\x18\x01 \x01(\x0e2&.xray.app.router.Config.DomainStrategyR\x0edomainStrategy\x120\n" +
 	"\x04rule\x18\x02 \x03(\v2\x1c.xray.app.router.RoutingRuleR\x04rule\x12E\n" +
-	"\x0ebalancing_rule\x18\x03 \x03(\v2\x1e.xray.app.router.BalancingRuleR\rbalancingRule\"<\n" +
+	"\x0ebalancing_rule\x18\x03 \x03(\v2\x1e.xray.app.router.BalancingRuleR\rbalancingRule\"B\n" +
 	"\x0eDomainStrategy\x12\b\n" +
 	"\x04AsIs\x10\x00\x12\x10\n" +
 	"\fIpIfNonMatch\x10\x02\x12\x0e\n" +
 	"\n" +
-	"IpOnDemand\x10\x03BO\n" +
+	"IpOnDemand\x10\x03\"\x04\b\x01\x10\x01BO\n" +
 	"\x13com.xray.app.routerP\x01Z$github.com/xtls/xray-core/app/router\xaa\x02\x0fXray.App.Routerb\x06proto3"
 
 var (
@@ -1211,59 +712,41 @@ func file_app_router_config_proto_rawDescGZIP() []byte {
 	return file_app_router_config_proto_rawDescData
 }
 
-var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
-var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
+var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
 var file_app_router_config_proto_goTypes = []any{
-	(Domain_Type)(0),                // 0: xray.app.router.Domain.Type
-	(Config_DomainStrategy)(0),      // 1: xray.app.router.Config.DomainStrategy
-	(*Domain)(nil),                  // 2: xray.app.router.Domain
-	(*CIDR)(nil),                    // 3: xray.app.router.CIDR
-	(*GeoIP)(nil),                   // 4: xray.app.router.GeoIP
-	(*GeoIPList)(nil),               // 5: xray.app.router.GeoIPList
-	(*GeoSite)(nil),                 // 6: xray.app.router.GeoSite
-	(*GeoSiteList)(nil),             // 7: xray.app.router.GeoSiteList
-	(*RoutingRule)(nil),             // 8: xray.app.router.RoutingRule
-	(*WebhookConfig)(nil),           // 9: xray.app.router.WebhookConfig
-	(*BalancingRule)(nil),           // 10: xray.app.router.BalancingRule
-	(*StrategyWeight)(nil),          // 11: xray.app.router.StrategyWeight
-	(*StrategyLeastLoadConfig)(nil), // 12: xray.app.router.StrategyLeastLoadConfig
-	(*Config)(nil),                  // 13: xray.app.router.Config
-	(*Domain_Attribute)(nil),        // 14: xray.app.router.Domain.Attribute
-	nil,                             // 15: xray.app.router.RoutingRule.AttributesEntry
-	nil,                             // 16: xray.app.router.WebhookConfig.HeadersEntry
-	(*net.PortList)(nil),            // 17: xray.common.net.PortList
-	(net.Network)(0),                // 18: xray.common.net.Network
-	(*serial.TypedMessage)(nil),     // 19: xray.common.serial.TypedMessage
+	(Config_DomainStrategy)(0),      // 0: xray.app.router.Config.DomainStrategy
+	(*RoutingRule)(nil),             // 1: xray.app.router.RoutingRule
+	(*WebhookConfig)(nil),           // 2: xray.app.router.WebhookConfig
+	(*BalancingRule)(nil),           // 3: xray.app.router.BalancingRule
+	(*StrategyWeight)(nil),          // 4: xray.app.router.StrategyWeight
+	(*StrategyLeastLoadConfig)(nil), // 5: xray.app.router.StrategyLeastLoadConfig
+	(*Config)(nil),                  // 6: xray.app.router.Config
+	nil,                             // 7: xray.app.router.RoutingRule.AttributesEntry
+	nil,                             // 8: xray.app.router.WebhookConfig.HeadersEntry
+	(*net.PortList)(nil),            // 9: xray.common.net.PortList
+	(net.Network)(0),                // 10: xray.common.net.Network
+	(*serial.TypedMessage)(nil),     // 11: xray.common.serial.TypedMessage
 }
 var file_app_router_config_proto_depIdxs = []int32{
-	0,  // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type
-	14, // 1: xray.app.router.Domain.attribute:type_name -> xray.app.router.Domain.Attribute
-	3,  // 2: xray.app.router.GeoIP.cidr:type_name -> xray.app.router.CIDR
-	4,  // 3: xray.app.router.GeoIPList.entry:type_name -> xray.app.router.GeoIP
-	2,  // 4: xray.app.router.GeoSite.domain:type_name -> xray.app.router.Domain
-	6,  // 5: xray.app.router.GeoSiteList.entry:type_name -> xray.app.router.GeoSite
-	2,  // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain
-	4,  // 7: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP
-	17, // 8: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
-	18, // 9: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
-	4,  // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
-	17, // 11: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
-	15, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
-	4,  // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
-	17, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
-	17, // 15: xray.app.router.RoutingRule.vless_route_list:type_name -> xray.common.net.PortList
-	9,  // 16: xray.app.router.RoutingRule.webhook:type_name -> xray.app.router.WebhookConfig
-	16, // 17: xray.app.router.WebhookConfig.headers:type_name -> xray.app.router.WebhookConfig.HeadersEntry
-	19, // 18: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
-	11, // 19: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
-	1,  // 20: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
-	8,  // 21: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
-	10, // 22: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
-	23, // [23:23] is the sub-list for method output_type
-	23, // [23:23] is the sub-list for method input_type
-	23, // [23:23] is the sub-list for extension type_name
-	23, // [23:23] is the sub-list for extension extendee
-	0,  // [0:23] is the sub-list for field type_name
+	9,  // 0: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
+	10, // 1: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
+	9,  // 2: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
+	7,  // 3: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
+	9,  // 4: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
+	9,  // 5: xray.app.router.RoutingRule.vless_route_list:type_name -> xray.common.net.PortList
+	2,  // 6: xray.app.router.RoutingRule.webhook:type_name -> xray.app.router.WebhookConfig
+	8,  // 7: xray.app.router.WebhookConfig.headers:type_name -> xray.app.router.WebhookConfig.HeadersEntry
+	11, // 8: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
+	4,  // 9: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
+	0,  // 10: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
+	1,  // 11: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
+	3,  // 12: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
+	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_router_config_proto_init() }
@@ -1271,21 +754,17 @@ func file_app_router_config_proto_init() {
 	if File_app_router_config_proto != nil {
 		return
 	}
-	file_app_router_config_proto_msgTypes[6].OneofWrappers = []any{
+	file_app_router_config_proto_msgTypes[0].OneofWrappers = []any{
 		(*RoutingRule_Tag)(nil),
 		(*RoutingRule_BalancingTag)(nil),
 	}
-	file_app_router_config_proto_msgTypes[12].OneofWrappers = []any{
-		(*Domain_Attribute_BoolValue)(nil),
-		(*Domain_Attribute_IntValue)(nil),
-	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_router_config_proto_rawDesc), len(file_app_router_config_proto_rawDesc)),
-			NumEnums:      2,
-			NumMessages:   15,
+			NumEnums:      1,
+			NumMessages:   8,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

+ 14 - 75
app/router/config.proto

@@ -10,67 +10,6 @@ import "common/serial/typed_message.proto";
 import "common/net/port.proto";
 import "common/net/network.proto";
 
-// Domain for routing decision.
-message Domain {
-  // Type of domain value.
-  enum Type {
-    // The value is used as is.
-    Plain = 0;
-    // The value is used as a regular expression.
-    Regex = 1;
-    // The value is a root domain.
-    Domain = 2;
-    // The value is a domain.
-    Full = 3;
-  }
-
-  // Domain matching type.
-  Type type = 1;
-
-  // Domain value.
-  string value = 2;
-
-  message Attribute {
-    string key = 1;
-
-    oneof typed_value {
-      bool bool_value = 2;
-      int64 int_value = 3;
-    }
-  }
-
-  // Attributes of this domain. May be used for filtering.
-  repeated Attribute attribute = 3;
-}
-
-// IP for routing decision, in CIDR form.
-message CIDR {
-  // IP address, should be either 4 or 16 bytes.
-  bytes ip = 1;
-
-  // Number of leading ones in the network mask.
-  uint32 prefix = 2;
-}
-
-message GeoIP {
-  string country_code = 1;
-  repeated CIDR cidr = 2;
-  bool reverse_match = 3;
-}
-
-message GeoIPList {
-  repeated GeoIP entry = 1;
-}
-
-message GeoSite {
-  string country_code = 1;
-  repeated Domain domain = 2;
-}
-
-message GeoSiteList {
-  repeated GeoSite entry = 1;
-}
-
 message RoutingRule {
   oneof target_tag {
     // Tag of outbound that this rule is pointing to.
@@ -79,26 +18,23 @@ message RoutingRule {
     // Tag of routing balancer.
     string balancing_tag = 12;
   }
-    string rule_tag = 19;
+
+  string rule_tag = 19;
 
   // List of domains for target domain matching.
-  repeated Domain domain = 2;
+  repeated string domain = 2;
 
-  // List of GeoIPs for target IP address matching. If this entry exists, the
-  // cidr above will have no effect. GeoIP fields with the same country code are
-  // supposed to contain exactly same content. They will be merged during
-  // runtime. For customized GeoIPs, please leave country code empty.
-  repeated GeoIP geoip = 10;
+  // List of IPs for target IP address matching.
+  repeated string ip = 10;
 
-  // List of ports.
+  // List of ports for target port matching.
   xray.common.net.PortList port_list = 14;
 
   // List of networks for matching.
   repeated xray.common.net.Network networks = 13;
 
-  // List of GeoIPs for source IP address matching. If this entry exists, the
-  // source_cidr above will have no effect.
-  repeated GeoIP source_geoip = 11;
+  // List of IPs for source IP address matching.
+  repeated string source_ip = 11;
 
   // List of ports for source port matching.
   xray.common.net.PortList source_port_list = 16;
@@ -109,10 +45,14 @@ message RoutingRule {
 
   map<string, string> attributes = 15;
 
-  repeated GeoIP local_geoip = 17;
+  // List of IPs for local IP address matching.
+  repeated string local_ip = 17;
+
+  // List of ports for local port matching.
   xray.common.net.PortList local_port_list = 18;
 
   xray.common.net.PortList vless_route_list = 20;
+
   repeated string process = 21;
   WebhookConfig webhook = 22;
 }
@@ -155,8 +95,7 @@ message Config {
     // Use domain as is.
     AsIs = 0;
 
-    // [Deprecated] Always resolve IP for domains.
-    // UseIp = 1;
+    reserved 1;
 
     // Resolve to IP if the domain doesn't match any rules.
     IpIfNonMatch = 2;

+ 591 - 0
common/geodata/geodat.pb.go

@@ -0,0 +1,591 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.36.11
+// 	protoc        v6.33.5
+// source: common/geodata/geodat.proto
+
+package geodata
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+	unsafe "unsafe"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// Type of domain value.
+type Domain_Type int32
+
+const (
+	// The value is used as a sub string.
+	Domain_Substr Domain_Type = 0
+	// The value is used as a regular expression.
+	Domain_Regex Domain_Type = 1
+	// The value is a domain.
+	Domain_Domain Domain_Type = 2
+	// The value is a full domain.
+	Domain_Full Domain_Type = 3
+)
+
+// Enum value maps for Domain_Type.
+var (
+	Domain_Type_name = map[int32]string{
+		0: "Substr",
+		1: "Regex",
+		2: "Domain",
+		3: "Full",
+	}
+	Domain_Type_value = map[string]int32{
+		"Substr": 0,
+		"Regex":  1,
+		"Domain": 2,
+		"Full":   3,
+	}
+)
+
+func (x Domain_Type) Enum() *Domain_Type {
+	p := new(Domain_Type)
+	*p = x
+	return p
+}
+
+func (x Domain_Type) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
+	return file_common_geodata_geodat_proto_enumTypes[0].Descriptor()
+}
+
+func (Domain_Type) Type() protoreflect.EnumType {
+	return &file_common_geodata_geodat_proto_enumTypes[0]
+}
+
+func (x Domain_Type) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use Domain_Type.Descriptor instead.
+func (Domain_Type) EnumDescriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0, 0}
+}
+
+type Domain struct {
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Domain matching type.
+	Type Domain_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.geodata.Domain_Type" json:"type,omitempty"`
+	// Domain value.
+	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+	// Attributes of this domain. May be used for filtering.
+	Attribute     []*Domain_Attribute `protobuf:"bytes,3,rep,name=attribute,proto3" json:"attribute,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *Domain) Reset() {
+	*x = Domain{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[0]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *Domain) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Domain) ProtoMessage() {}
+
+func (x *Domain) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[0]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
+func (*Domain) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Domain) GetType() Domain_Type {
+	if x != nil {
+		return x.Type
+	}
+	return Domain_Substr
+}
+
+func (x *Domain) GetValue() string {
+	if x != nil {
+		return x.Value
+	}
+	return ""
+}
+
+func (x *Domain) GetAttribute() []*Domain_Attribute {
+	if x != nil {
+		return x.Attribute
+	}
+	return nil
+}
+
+type CIDR struct {
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// IP address, should be either 4 or 16 bytes.
+	Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
+	// Number of leading ones in the network mask.
+	Prefix        uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *CIDR) Reset() {
+	*x = CIDR{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[1]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *CIDR) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CIDR) ProtoMessage() {}
+
+func (x *CIDR) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[1]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use CIDR.ProtoReflect.Descriptor instead.
+func (*CIDR) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CIDR) GetIp() []byte {
+	if x != nil {
+		return x.Ip
+	}
+	return nil
+}
+
+func (x *CIDR) GetPrefix() uint32 {
+	if x != nil {
+		return x.Prefix
+	}
+	return 0
+}
+
+type GeoIP struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Code          string                 `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
+	Cidr          []*CIDR                `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
+	ReverseMatch  bool                   `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GeoIP) Reset() {
+	*x = GeoIP{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[2]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GeoIP) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GeoIP) ProtoMessage() {}
+
+func (x *GeoIP) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[2]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
+func (*GeoIP) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *GeoIP) GetCode() string {
+	if x != nil {
+		return x.Code
+	}
+	return ""
+}
+
+func (x *GeoIP) GetCidr() []*CIDR {
+	if x != nil {
+		return x.Cidr
+	}
+	return nil
+}
+
+func (x *GeoIP) GetReverseMatch() bool {
+	if x != nil {
+		return x.ReverseMatch
+	}
+	return false
+}
+
+type GeoIPList struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Entry         []*GeoIP               `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GeoIPList) Reset() {
+	*x = GeoIPList{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[3]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GeoIPList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GeoIPList) ProtoMessage() {}
+
+func (x *GeoIPList) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[3]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
+func (*GeoIPList) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *GeoIPList) GetEntry() []*GeoIP {
+	if x != nil {
+		return x.Entry
+	}
+	return nil
+}
+
+type GeoSite struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Code          string                 `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
+	Domain        []*Domain              `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GeoSite) Reset() {
+	*x = GeoSite{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[4]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GeoSite) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GeoSite) ProtoMessage() {}
+
+func (x *GeoSite) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[4]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GeoSite.ProtoReflect.Descriptor instead.
+func (*GeoSite) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *GeoSite) GetCode() string {
+	if x != nil {
+		return x.Code
+	}
+	return ""
+}
+
+func (x *GeoSite) GetDomain() []*Domain {
+	if x != nil {
+		return x.Domain
+	}
+	return nil
+}
+
+type GeoSiteList struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Entry         []*GeoSite             `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GeoSiteList) Reset() {
+	*x = GeoSiteList{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[5]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GeoSiteList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GeoSiteList) ProtoMessage() {}
+
+func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[5]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GeoSiteList.ProtoReflect.Descriptor instead.
+func (*GeoSiteList) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *GeoSiteList) GetEntry() []*GeoSite {
+	if x != nil {
+		return x.Entry
+	}
+	return nil
+}
+
+type Domain_Attribute struct {
+	state protoimpl.MessageState `protogen:"open.v1"`
+	Key   string                 `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+	// Types that are valid to be assigned to TypedValue:
+	//
+	//	*Domain_Attribute_BoolValue
+	//	*Domain_Attribute_IntValue
+	TypedValue    isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *Domain_Attribute) Reset() {
+	*x = Domain_Attribute{}
+	mi := &file_common_geodata_geodat_proto_msgTypes[6]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *Domain_Attribute) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Domain_Attribute) ProtoMessage() {}
+
+func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
+	mi := &file_common_geodata_geodat_proto_msgTypes[6]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Domain_Attribute.ProtoReflect.Descriptor instead.
+func (*Domain_Attribute) Descriptor() ([]byte, []int) {
+	return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *Domain_Attribute) GetKey() string {
+	if x != nil {
+		return x.Key
+	}
+	return ""
+}
+
+func (x *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedValue {
+	if x != nil {
+		return x.TypedValue
+	}
+	return nil
+}
+
+func (x *Domain_Attribute) GetBoolValue() bool {
+	if x != nil {
+		if x, ok := x.TypedValue.(*Domain_Attribute_BoolValue); ok {
+			return x.BoolValue
+		}
+	}
+	return false
+}
+
+func (x *Domain_Attribute) GetIntValue() int64 {
+	if x != nil {
+		if x, ok := x.TypedValue.(*Domain_Attribute_IntValue); ok {
+			return x.IntValue
+		}
+	}
+	return 0
+}
+
+type isDomain_Attribute_TypedValue interface {
+	isDomain_Attribute_TypedValue()
+}
+
+type Domain_Attribute_BoolValue struct {
+	BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"`
+}
+
+type Domain_Attribute_IntValue struct {
+	IntValue int64 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
+}
+
+func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
+
+func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
+
+var File_common_geodata_geodat_proto protoreflect.FileDescriptor
+
+const file_common_geodata_geodat_proto_rawDesc = "" +
+	"\n" +
+	"\x1bcommon/geodata/geodat.proto\x12\x13xray.common.geodata\"\xbc\x02\n" +
+	"\x06Domain\x124\n" +
+	"\x04type\x18\x01 \x01(\x0e2 .xray.common.geodata.Domain.TypeR\x04type\x12\x14\n" +
+	"\x05value\x18\x02 \x01(\tR\x05value\x12C\n" +
+	"\tattribute\x18\x03 \x03(\v2%.xray.common.geodata.Domain.AttributeR\tattribute\x1al\n" +
+	"\tAttribute\x12\x10\n" +
+	"\x03key\x18\x01 \x01(\tR\x03key\x12\x1f\n" +
+	"\n" +
+	"bool_value\x18\x02 \x01(\bH\x00R\tboolValue\x12\x1d\n" +
+	"\tint_value\x18\x03 \x01(\x03H\x00R\bintValueB\r\n" +
+	"\vtyped_value\"3\n" +
+	"\x04Type\x12\n" +
+	"\n" +
+	"\x06Substr\x10\x00\x12\t\n" +
+	"\x05Regex\x10\x01\x12\n" +
+	"\n" +
+	"\x06Domain\x10\x02\x12\b\n" +
+	"\x04Full\x10\x03\".\n" +
+	"\x04CIDR\x12\x0e\n" +
+	"\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" +
+	"\x06prefix\x18\x02 \x01(\rR\x06prefix\"o\n" +
+	"\x05GeoIP\x12\x12\n" +
+	"\x04code\x18\x01 \x01(\tR\x04code\x12-\n" +
+	"\x04cidr\x18\x02 \x03(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" +
+	"\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"=\n" +
+	"\tGeoIPList\x120\n" +
+	"\x05entry\x18\x01 \x03(\v2\x1a.xray.common.geodata.GeoIPR\x05entry\"R\n" +
+	"\aGeoSite\x12\x12\n" +
+	"\x04code\x18\x01 \x01(\tR\x04code\x123\n" +
+	"\x06domain\x18\x02 \x03(\v2\x1b.xray.common.geodata.DomainR\x06domain\"A\n" +
+	"\vGeoSiteList\x122\n" +
+	"\x05entry\x18\x01 \x03(\v2\x1c.xray.common.geodata.GeoSiteR\x05entryB[\n" +
+	"\x17com.xray.common.geodataP\x01Z(github.com/xtls/xray-core/common/geodata\xaa\x02\x13Xray.Common.Geodatab\x06proto3"
+
+var (
+	file_common_geodata_geodat_proto_rawDescOnce sync.Once
+	file_common_geodata_geodat_proto_rawDescData []byte
+)
+
+func file_common_geodata_geodat_proto_rawDescGZIP() []byte {
+	file_common_geodata_geodat_proto_rawDescOnce.Do(func() {
+		file_common_geodata_geodat_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)))
+	})
+	return file_common_geodata_geodat_proto_rawDescData
+}
+
+var file_common_geodata_geodat_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_common_geodata_geodat_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_common_geodata_geodat_proto_goTypes = []any{
+	(Domain_Type)(0),         // 0: xray.common.geodata.Domain.Type
+	(*Domain)(nil),           // 1: xray.common.geodata.Domain
+	(*CIDR)(nil),             // 2: xray.common.geodata.CIDR
+	(*GeoIP)(nil),            // 3: xray.common.geodata.GeoIP
+	(*GeoIPList)(nil),        // 4: xray.common.geodata.GeoIPList
+	(*GeoSite)(nil),          // 5: xray.common.geodata.GeoSite
+	(*GeoSiteList)(nil),      // 6: xray.common.geodata.GeoSiteList
+	(*Domain_Attribute)(nil), // 7: xray.common.geodata.Domain.Attribute
+}
+var file_common_geodata_geodat_proto_depIdxs = []int32{
+	0, // 0: xray.common.geodata.Domain.type:type_name -> xray.common.geodata.Domain.Type
+	7, // 1: xray.common.geodata.Domain.attribute:type_name -> xray.common.geodata.Domain.Attribute
+	2, // 2: xray.common.geodata.GeoIP.cidr:type_name -> xray.common.geodata.CIDR
+	3, // 3: xray.common.geodata.GeoIPList.entry:type_name -> xray.common.geodata.GeoIP
+	1, // 4: xray.common.geodata.GeoSite.domain:type_name -> xray.common.geodata.Domain
+	5, // 5: xray.common.geodata.GeoSiteList.entry:type_name -> xray.common.geodata.GeoSite
+	6, // [6:6] is the sub-list for method output_type
+	6, // [6:6] is the sub-list for method input_type
+	6, // [6:6] is the sub-list for extension type_name
+	6, // [6:6] is the sub-list for extension extendee
+	0, // [0:6] is the sub-list for field type_name
+}
+
+func init() { file_common_geodata_geodat_proto_init() }
+func file_common_geodata_geodat_proto_init() {
+	if File_common_geodata_geodat_proto != nil {
+		return
+	}
+	file_common_geodata_geodat_proto_msgTypes[6].OneofWrappers = []any{
+		(*Domain_Attribute_BoolValue)(nil),
+		(*Domain_Attribute_IntValue)(nil),
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)),
+			NumEnums:      1,
+			NumMessages:   7,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_common_geodata_geodat_proto_goTypes,
+		DependencyIndexes: file_common_geodata_geodat_proto_depIdxs,
+		EnumInfos:         file_common_geodata_geodat_proto_enumTypes,
+		MessageInfos:      file_common_geodata_geodat_proto_msgTypes,
+	}.Build()
+	File_common_geodata_geodat_proto = out.File
+	file_common_geodata_geodat_proto_goTypes = nil
+	file_common_geodata_geodat_proto_depIdxs = nil
+}

+ 64 - 0
common/geodata/geodat.proto

@@ -0,0 +1,64 @@
+syntax = "proto3";
+
+package xray.common.geodata;
+option csharp_namespace = "Xray.Common.Geodata";
+option go_package = "github.com/xtls/xray-core/common/geodata";
+option java_package = "com.xray.common.geodata";
+option java_multiple_files = true;
+
+message Domain {
+  // Type of domain value.
+  enum Type {
+    // The value is used as a sub string.
+    Substr = 0;
+    // The value is used as a regular expression.
+    Regex = 1;
+    // The value is a domain.
+    Domain = 2;
+    // The value is a full domain.
+    Full = 3;
+  }
+  // Domain matching type.
+  Type type = 1;
+
+  // Domain value.
+  string value = 2;
+
+  message Attribute {
+    string key = 1;
+
+    oneof typed_value {
+      bool bool_value = 2;
+      int64 int_value = 3;
+    }
+  }
+  // Attributes of this domain. May be used for filtering.
+  repeated Attribute attribute = 3;
+}
+
+message CIDR {
+  // IP address, should be either 4 or 16 bytes.
+  bytes ip = 1;
+
+  // Number of leading ones in the network mask.
+  uint32 prefix = 2;
+}
+
+message GeoIP {
+  string code = 1;
+  repeated CIDR cidr = 2;
+  bool reverse_match = 3;
+}
+
+message GeoIPList {
+  repeated GeoIP entry = 1;
+}
+
+message GeoSite {
+  string code = 1;
+  repeated Domain domain = 2;
+}
+
+message GeoSiteList {
+  repeated GeoSite entry = 1;
+}