Meow
2026-04-18 06:13:35 +08:00
committed by GitHub
parent d42c981f9c
commit 31ab22c33d
13 changed files with 277 additions and 173 deletions

View File

@@ -548,15 +548,8 @@ func TestIPMatch(t *testing.T) {
Port: uint32(port), Port: uint32(port),
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
{
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
// inner ip, will not match // inner ip, will not match
Ip: []byte{192, 168, 11, 1}, {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{192, 168, 11, 1}, Prefix: 32}}}},
Prefix: 32,
},
},
},
}, },
}, },
// second dns, match ip // second dns, match ip
@@ -571,22 +564,8 @@ func TestIPMatch(t *testing.T) {
Port: uint32(port), Port: uint32(port),
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32}}}},
Value: &geodata.IPRule_Custom{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 4}, Prefix: 32}}}},
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
},
},
{
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 8, 4},
Prefix: 32,
},
},
},
}, },
}, },
}, },
@@ -676,9 +655,9 @@ func TestLocalDomain(t *testing.T) {
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
// Will match localhost, localhost-a and localhost-b, // Will match localhost, localhost-a and localhost-b,
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDR{Ip: []byte{127, 0, 0, 2}, Prefix: 32}}}, {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 2}, Prefix: 32}}}},
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDR{Ip: []byte{127, 0, 0, 3}, Prefix: 32}}}, {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 3}, Prefix: 32}}}},
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDR{Ip: []byte{127, 0, 0, 4}, Prefix: 32}}}, {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 4}, Prefix: 32}}}},
}, },
}, },
{ {
@@ -901,22 +880,8 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
// Will only match 8.8.8.8 and 8.8.4.4 // Will only match 8.8.8.8 and 8.8.4.4
{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32}}}},
Value: &geodata.IPRule_Custom{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 4, 4}, Prefix: 32}}}},
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
},
},
{
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 4, 4},
Prefix: 32,
},
},
},
}, },
}, },
{ {
@@ -936,14 +901,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
// Will match 8.8.8.8 and 8.8.8.7, etc // Will match 8.8.8.8 and 8.8.8.7, etc
{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 7}, Prefix: 24}}}},
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 8, 7},
Prefix: 24,
},
},
},
}, },
}, },
{ {
@@ -963,14 +921,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
// Will only match 8.8.7.7 (api.google.com) // Will only match 8.8.7.7 (api.google.com)
{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 7, 7}, Prefix: 32}}}},
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 7, 7},
Prefix: 32,
},
},
},
}, },
}, },
{ {
@@ -990,14 +941,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
ExpectedIp: []*geodata.IPRule{ ExpectedIp: []*geodata.IPRule{
// Will only match 8.8.7.8 (v2.api.google.com) // Will only match 8.8.7.8 (v2.api.google.com)
{ {Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 7, 8}, Prefix: 32}}}},
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{
Ip: []byte{8, 8, 7, 8},
Prefix: 32,
},
},
},
}, },
}, },
}, },

View File

@@ -308,7 +308,7 @@ func TestServiceTestRoute(t *testing.T) {
TargetTag: &router.RoutingRule_Tag{Tag: "out"}, TargetTag: &router.RoutingRule_Tag{Tag: "out"},
}, },
{ {
SourceIp: []*geodata.IPRule{{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}}, SourceIp: []*geodata.IPRule{{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}}},
TargetTag: &router.RoutingRule_Tag{Tag: "out"}, TargetTag: &router.RoutingRule_Tag{Tag: "out"},
}, },
{ {

View File

@@ -92,25 +92,22 @@ func TestRoutingRule(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{8, 8, 8, 8}, Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
Prefix: 32,
}, },
}, },
}, },
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{8, 8, 8, 8}, Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
Prefix: 32,
}, },
}, },
}, },
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(), Cidr: &geodata.CIDR{Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(), Prefix: 128},
Prefix: 128,
}, },
}, },
}, },
@@ -140,9 +137,8 @@ func TestRoutingRule(t *testing.T) {
SourceIp: []*geodata.IPRule{ SourceIp: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{192, 168, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
Prefix: 16,
}, },
}, },
}, },

View File

@@ -159,9 +159,8 @@ func TestIPOnDemand(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{192, 168, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
Prefix: 16,
}, },
}, },
}, },
@@ -204,9 +203,8 @@ func TestIPIfNonMatchDomain(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{192, 168, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
Prefix: 16,
}, },
}, },
}, },
@@ -249,9 +247,8 @@ func TestIPIfNonMatchIP(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{127, 0, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
Prefix: 8,
}, },
}, },
}, },

View File

@@ -433,6 +433,58 @@ func (x *CIDR) GetPrefix() uint32 {
return 0 return 0
} }
type CIDRRule struct {
state protoimpl.MessageState `protogen:"open.v1"`
Cidr *CIDR `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"`
ReverseMatch bool `protobuf:"varint,2,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CIDRRule) Reset() {
*x = CIDRRule{}
mi := &file_common_geodata_geodat_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CIDRRule) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CIDRRule) ProtoMessage() {}
func (x *CIDRRule) 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 CIDRRule.ProtoReflect.Descriptor instead.
func (*CIDRRule) Descriptor() ([]byte, []int) {
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{6}
}
func (x *CIDRRule) GetCidr() *CIDR {
if x != nil {
return x.Cidr
}
return nil
}
func (x *CIDRRule) GetReverseMatch() bool {
if x != nil {
return x.ReverseMatch
}
return false
}
type GeoIP struct { type GeoIP struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
@@ -444,7 +496,7 @@ type GeoIP struct {
func (x *GeoIP) Reset() { func (x *GeoIP) Reset() {
*x = GeoIP{} *x = GeoIP{}
mi := &file_common_geodata_geodat_proto_msgTypes[6] mi := &file_common_geodata_geodat_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -456,7 +508,7 @@ func (x *GeoIP) String() string {
func (*GeoIP) ProtoMessage() {} func (*GeoIP) ProtoMessage() {}
func (x *GeoIP) ProtoReflect() protoreflect.Message { func (x *GeoIP) ProtoReflect() protoreflect.Message {
mi := &file_common_geodata_geodat_proto_msgTypes[6] mi := &file_common_geodata_geodat_proto_msgTypes[7]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -469,7 +521,7 @@ func (x *GeoIP) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead. // Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
func (*GeoIP) Descriptor() ([]byte, []int) { func (*GeoIP) Descriptor() ([]byte, []int) {
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{6} return file_common_geodata_geodat_proto_rawDescGZIP(), []int{7}
} }
func (x *GeoIP) GetCode() string { func (x *GeoIP) GetCode() string {
@@ -502,7 +554,7 @@ type GeoIPList struct {
func (x *GeoIPList) Reset() { func (x *GeoIPList) Reset() {
*x = GeoIPList{} *x = GeoIPList{}
mi := &file_common_geodata_geodat_proto_msgTypes[7] mi := &file_common_geodata_geodat_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -514,7 +566,7 @@ func (x *GeoIPList) String() string {
func (*GeoIPList) ProtoMessage() {} func (*GeoIPList) ProtoMessage() {}
func (x *GeoIPList) ProtoReflect() protoreflect.Message { func (x *GeoIPList) ProtoReflect() protoreflect.Message {
mi := &file_common_geodata_geodat_proto_msgTypes[7] mi := &file_common_geodata_geodat_proto_msgTypes[8]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -527,7 +579,7 @@ func (x *GeoIPList) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead. // Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
func (*GeoIPList) Descriptor() ([]byte, []int) { func (*GeoIPList) Descriptor() ([]byte, []int) {
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{7} return file_common_geodata_geodat_proto_rawDescGZIP(), []int{8}
} }
func (x *GeoIPList) GetEntry() []*GeoIP { func (x *GeoIPList) GetEntry() []*GeoIP {
@@ -548,7 +600,7 @@ type GeoIPRule struct {
func (x *GeoIPRule) Reset() { func (x *GeoIPRule) Reset() {
*x = GeoIPRule{} *x = GeoIPRule{}
mi := &file_common_geodata_geodat_proto_msgTypes[8] mi := &file_common_geodata_geodat_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -560,7 +612,7 @@ func (x *GeoIPRule) String() string {
func (*GeoIPRule) ProtoMessage() {} func (*GeoIPRule) ProtoMessage() {}
func (x *GeoIPRule) ProtoReflect() protoreflect.Message { func (x *GeoIPRule) ProtoReflect() protoreflect.Message {
mi := &file_common_geodata_geodat_proto_msgTypes[8] mi := &file_common_geodata_geodat_proto_msgTypes[9]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -573,7 +625,7 @@ func (x *GeoIPRule) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeoIPRule.ProtoReflect.Descriptor instead. // Deprecated: Use GeoIPRule.ProtoReflect.Descriptor instead.
func (*GeoIPRule) Descriptor() ([]byte, []int) { func (*GeoIPRule) Descriptor() ([]byte, []int) {
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{8} return file_common_geodata_geodat_proto_rawDescGZIP(), []int{9}
} }
func (x *GeoIPRule) GetFile() string { func (x *GeoIPRule) GetFile() string {
@@ -610,7 +662,7 @@ type IPRule struct {
func (x *IPRule) Reset() { func (x *IPRule) Reset() {
*x = IPRule{} *x = IPRule{}
mi := &file_common_geodata_geodat_proto_msgTypes[9] mi := &file_common_geodata_geodat_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -622,7 +674,7 @@ func (x *IPRule) String() string {
func (*IPRule) ProtoMessage() {} func (*IPRule) ProtoMessage() {}
func (x *IPRule) ProtoReflect() protoreflect.Message { func (x *IPRule) ProtoReflect() protoreflect.Message {
mi := &file_common_geodata_geodat_proto_msgTypes[9] mi := &file_common_geodata_geodat_proto_msgTypes[10]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -635,7 +687,7 @@ func (x *IPRule) ProtoReflect() protoreflect.Message {
// Deprecated: Use IPRule.ProtoReflect.Descriptor instead. // Deprecated: Use IPRule.ProtoReflect.Descriptor instead.
func (*IPRule) Descriptor() ([]byte, []int) { func (*IPRule) Descriptor() ([]byte, []int) {
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{9} return file_common_geodata_geodat_proto_rawDescGZIP(), []int{10}
} }
func (x *IPRule) GetValue() isIPRule_Value { func (x *IPRule) GetValue() isIPRule_Value {
@@ -654,7 +706,7 @@ func (x *IPRule) GetGeoip() *GeoIPRule {
return nil return nil
} }
func (x *IPRule) GetCustom() *CIDR { func (x *IPRule) GetCustom() *CIDRRule {
if x != nil { if x != nil {
if x, ok := x.Value.(*IPRule_Custom); ok { if x, ok := x.Value.(*IPRule_Custom); ok {
return x.Custom return x.Custom
@@ -672,7 +724,7 @@ type IPRule_Geoip struct {
} }
type IPRule_Custom struct { type IPRule_Custom struct {
Custom *CIDR `protobuf:"bytes,2,opt,name=custom,proto3,oneof"` Custom *CIDRRule `protobuf:"bytes,2,opt,name=custom,proto3,oneof"`
} }
func (*IPRule_Geoip) isIPRule_Value() {} func (*IPRule_Geoip) isIPRule_Value() {}
@@ -693,7 +745,7 @@ type Domain_Attribute struct {
func (x *Domain_Attribute) Reset() { func (x *Domain_Attribute) Reset() {
*x = Domain_Attribute{} *x = Domain_Attribute{}
mi := &file_common_geodata_geodat_proto_msgTypes[10] mi := &file_common_geodata_geodat_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -705,7 +757,7 @@ func (x *Domain_Attribute) String() string {
func (*Domain_Attribute) ProtoMessage() {} func (*Domain_Attribute) ProtoMessage() {}
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message { func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
mi := &file_common_geodata_geodat_proto_msgTypes[10] mi := &file_common_geodata_geodat_proto_msgTypes[11]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -807,7 +859,10 @@ const file_common_geodata_geodat_proto_rawDesc = "" +
"\x05value\".\n" + "\x05value\".\n" +
"\x04CIDR\x12\x0e\n" + "\x04CIDR\x12\x0e\n" +
"\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" + "\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" +
"\x06prefix\x18\x02 \x01(\rR\x06prefix\"o\n" + "\x06prefix\x18\x02 \x01(\rR\x06prefix\"^\n" +
"\bCIDRRule\x12-\n" +
"\x04cidr\x18\x01 \x01(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" +
"\rreverse_match\x18\x02 \x01(\bR\freverseMatch\"o\n" +
"\x05GeoIP\x12\x12\n" + "\x05GeoIP\x12\x12\n" +
"\x04code\x18\x01 \x01(\tR\x04code\x12-\n" + "\x04code\x18\x01 \x01(\tR\x04code\x12-\n" +
"\x04cidr\x18\x02 \x03(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" + "\x04cidr\x18\x02 \x03(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" +
@@ -817,10 +872,10 @@ const file_common_geodata_geodat_proto_rawDesc = "" +
"\tGeoIPRule\x12\x12\n" + "\tGeoIPRule\x12\x12\n" +
"\x04file\x18\x01 \x01(\tR\x04file\x12\x12\n" + "\x04file\x18\x01 \x01(\tR\x04file\x12\x12\n" +
"\x04code\x18\x02 \x01(\tR\x04code\x12#\n" + "\x04code\x18\x02 \x01(\tR\x04code\x12#\n" +
"\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"~\n" + "\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"\x82\x01\n" +
"\x06IPRule\x126\n" + "\x06IPRule\x126\n" +
"\x05geoip\x18\x01 \x01(\v2\x1e.xray.common.geodata.GeoIPRuleH\x00R\x05geoip\x123\n" + "\x05geoip\x18\x01 \x01(\v2\x1e.xray.common.geodata.GeoIPRuleH\x00R\x05geoip\x127\n" +
"\x06custom\x18\x02 \x01(\v2\x19.xray.common.geodata.CIDRH\x00R\x06customB\a\n" + "\x06custom\x18\x02 \x01(\v2\x1d.xray.common.geodata.CIDRRuleH\x00R\x06customB\a\n" +
"\x05valueB[\n" + "\x05valueB[\n" +
"\x17com.xray.common.geodataP\x01Z(github.com/xtls/xray-core/common/geodata\xaa\x02\x13Xray.Common.Geodatab\x06proto3" "\x17com.xray.common.geodataP\x01Z(github.com/xtls/xray-core/common/geodata\xaa\x02\x13Xray.Common.Geodatab\x06proto3"
@@ -837,7 +892,7 @@ func file_common_geodata_geodat_proto_rawDescGZIP() []byte {
} }
var file_common_geodata_geodat_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_common_geodata_geodat_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_common_geodata_geodat_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_common_geodata_geodat_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_common_geodata_geodat_proto_goTypes = []any{ var file_common_geodata_geodat_proto_goTypes = []any{
(Domain_Type)(0), // 0: xray.common.geodata.Domain.Type (Domain_Type)(0), // 0: xray.common.geodata.Domain.Type
(*Domain)(nil), // 1: xray.common.geodata.Domain (*Domain)(nil), // 1: xray.common.geodata.Domain
@@ -846,28 +901,30 @@ var file_common_geodata_geodat_proto_goTypes = []any{
(*GeoSiteRule)(nil), // 4: xray.common.geodata.GeoSiteRule (*GeoSiteRule)(nil), // 4: xray.common.geodata.GeoSiteRule
(*DomainRule)(nil), // 5: xray.common.geodata.DomainRule (*DomainRule)(nil), // 5: xray.common.geodata.DomainRule
(*CIDR)(nil), // 6: xray.common.geodata.CIDR (*CIDR)(nil), // 6: xray.common.geodata.CIDR
(*GeoIP)(nil), // 7: xray.common.geodata.GeoIP (*CIDRRule)(nil), // 7: xray.common.geodata.CIDRRule
(*GeoIPList)(nil), // 8: xray.common.geodata.GeoIPList (*GeoIP)(nil), // 8: xray.common.geodata.GeoIP
(*GeoIPRule)(nil), // 9: xray.common.geodata.GeoIPRule (*GeoIPList)(nil), // 9: xray.common.geodata.GeoIPList
(*IPRule)(nil), // 10: xray.common.geodata.IPRule (*GeoIPRule)(nil), // 10: xray.common.geodata.GeoIPRule
(*Domain_Attribute)(nil), // 11: xray.common.geodata.Domain.Attribute (*IPRule)(nil), // 11: xray.common.geodata.IPRule
(*Domain_Attribute)(nil), // 12: xray.common.geodata.Domain.Attribute
} }
var file_common_geodata_geodat_proto_depIdxs = []int32{ var file_common_geodata_geodat_proto_depIdxs = []int32{
0, // 0: xray.common.geodata.Domain.type:type_name -> xray.common.geodata.Domain.Type 0, // 0: xray.common.geodata.Domain.type:type_name -> xray.common.geodata.Domain.Type
11, // 1: xray.common.geodata.Domain.attribute:type_name -> xray.common.geodata.Domain.Attribute 12, // 1: xray.common.geodata.Domain.attribute:type_name -> xray.common.geodata.Domain.Attribute
1, // 2: xray.common.geodata.GeoSite.domain:type_name -> xray.common.geodata.Domain 1, // 2: xray.common.geodata.GeoSite.domain:type_name -> xray.common.geodata.Domain
2, // 3: xray.common.geodata.GeoSiteList.entry:type_name -> xray.common.geodata.GeoSite 2, // 3: xray.common.geodata.GeoSiteList.entry:type_name -> xray.common.geodata.GeoSite
4, // 4: xray.common.geodata.DomainRule.geosite:type_name -> xray.common.geodata.GeoSiteRule 4, // 4: xray.common.geodata.DomainRule.geosite:type_name -> xray.common.geodata.GeoSiteRule
1, // 5: xray.common.geodata.DomainRule.custom:type_name -> xray.common.geodata.Domain 1, // 5: xray.common.geodata.DomainRule.custom:type_name -> xray.common.geodata.Domain
6, // 6: xray.common.geodata.GeoIP.cidr:type_name -> xray.common.geodata.CIDR 6, // 6: xray.common.geodata.CIDRRule.cidr:type_name -> xray.common.geodata.CIDR
7, // 7: xray.common.geodata.GeoIPList.entry:type_name -> xray.common.geodata.GeoIP 6, // 7: xray.common.geodata.GeoIP.cidr:type_name -> xray.common.geodata.CIDR
9, // 8: xray.common.geodata.IPRule.geoip:type_name -> xray.common.geodata.GeoIPRule 8, // 8: xray.common.geodata.GeoIPList.entry:type_name -> xray.common.geodata.GeoIP
6, // 9: xray.common.geodata.IPRule.custom:type_name -> xray.common.geodata.CIDR 10, // 9: xray.common.geodata.IPRule.geoip:type_name -> xray.common.geodata.GeoIPRule
10, // [10:10] is the sub-list for method output_type 7, // 10: xray.common.geodata.IPRule.custom:type_name -> xray.common.geodata.CIDRRule
10, // [10:10] is the sub-list for method input_type 11, // [11:11] is the sub-list for method output_type
10, // [10:10] is the sub-list for extension type_name 11, // [11:11] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension extendee 11, // [11:11] is the sub-list for extension type_name
0, // [0:10] is the sub-list for field type_name 11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
} }
func init() { file_common_geodata_geodat_proto_init() } func init() { file_common_geodata_geodat_proto_init() }
@@ -879,11 +936,11 @@ func file_common_geodata_geodat_proto_init() {
(*DomainRule_Geosite)(nil), (*DomainRule_Geosite)(nil),
(*DomainRule_Custom)(nil), (*DomainRule_Custom)(nil),
} }
file_common_geodata_geodat_proto_msgTypes[9].OneofWrappers = []any{ file_common_geodata_geodat_proto_msgTypes[10].OneofWrappers = []any{
(*IPRule_Geoip)(nil), (*IPRule_Geoip)(nil),
(*IPRule_Custom)(nil), (*IPRule_Custom)(nil),
} }
file_common_geodata_geodat_proto_msgTypes[10].OneofWrappers = []any{ file_common_geodata_geodat_proto_msgTypes[11].OneofWrappers = []any{
(*Domain_Attribute_BoolValue)(nil), (*Domain_Attribute_BoolValue)(nil),
(*Domain_Attribute_IntValue)(nil), (*Domain_Attribute_IntValue)(nil),
} }
@@ -893,7 +950,7 @@ func file_common_geodata_geodat_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)),
NumEnums: 1, NumEnums: 1,
NumMessages: 11, NumMessages: 12,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@@ -66,6 +66,11 @@ message CIDR {
uint32 prefix = 2; uint32 prefix = 2;
} }
message CIDRRule {
CIDR cidr = 1;
bool reverse_match = 2;
}
message GeoIP { message GeoIP {
string code = 1; string code = 1;
repeated CIDR cidr = 2; repeated CIDR cidr = 2;
@@ -85,6 +90,6 @@ message GeoIPRule {
message IPRule { message IPRule {
oneof value { oneof value {
GeoIPRule geoip = 1; GeoIPRule geoip = 1;
CIDR custom = 2; CIDRRule custom = 2;
} }
} }

View File

@@ -940,45 +940,58 @@ func (f *IPSetFactory) createFrom(yield func(func(*CIDR)) error) (*IPSet, error)
func buildOptimizedIPMatcher(f *IPSetFactory, rules []*IPRule) (IPMatcher, error) { func buildOptimizedIPMatcher(f *IPSetFactory, rules []*IPRule) (IPMatcher, error) {
n := len(rules) n := len(rules)
custom := make([]*CIDR, 0, n) posCustom := make([]*CIDR, 0, n)
pos := make([]*GeoIPRule, 0, n) negCustom := make([]*CIDR, 0, n)
neg := make([]*GeoIPRule, 0, n) posGeoip := make([]*GeoIPRule, 0, n)
negGeoip := make([]*GeoIPRule, 0, n)
for _, r := range rules { for _, r := range rules {
switch v := r.Value.(type) { switch v := r.Value.(type) {
case *IPRule_Custom: case *IPRule_Custom:
custom = append(custom, v.Custom) if !v.Custom.ReverseMatch {
posCustom = append(posCustom, v.Custom.Cidr)
} else {
negCustom = append(negCustom, v.Custom.Cidr)
}
case *IPRule_Geoip: case *IPRule_Geoip:
if !v.Geoip.ReverseMatch { if !v.Geoip.ReverseMatch {
pos = append(pos, v.Geoip) posGeoip = append(posGeoip, v.Geoip)
} else { } else {
neg = append(neg, v.Geoip) negGeoip = append(negGeoip, v.Geoip)
} }
default: default:
panic("unknown ip rule type") panic("unknown ip rule type")
} }
} }
subs := make([]*HeuristicIPMatcher, 0, 3) subs := make([]*HeuristicIPMatcher, 0, 4)
if len(custom) > 0 { if len(posCustom) > 0 {
ipset, err := f.CreateFromCIDRs(custom) ipset, err := f.CreateFromCIDRs(posCustom)
if err != nil { if err != nil {
return nil, err return nil, err
} }
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false}) subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false})
} }
if len(pos) > 0 { if len(negCustom) > 0 {
ipset, err := f.GetOrCreateFromGeoIPRules(pos) ipset, err := f.CreateFromCIDRs(negCustom)
if err != nil {
return nil, err
}
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: true})
}
if len(posGeoip) > 0 {
ipset, err := f.GetOrCreateFromGeoIPRules(posGeoip)
if err != nil { if err != nil {
return nil, err return nil, err
} }
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false}) subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false})
} }
if len(neg) > 0 { if len(negGeoip) > 0 {
ipset, err := f.GetOrCreateFromGeoIPRules(neg) ipset, err := f.GetOrCreateFromGeoIPRules(negGeoip)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -189,6 +189,34 @@ func TestIPReverseMatcher2(t *testing.T) {
} }
} }
func TestIPCustomReverseMatcher(t *testing.T) {
matcher := buildIPMatcher("!8.8.8.8/32")
testCases := []struct {
Input string
Output bool
}{
{
Input: "8.8.8.8",
Output: false,
},
{
Input: "1.1.1.1",
Output: true,
},
{
Input: "2001:cdba::3257:9652",
Output: false,
},
}
for _, test := range testCases {
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
t.Error("unexpected output: ", v, " for test case ", test)
}
}
}
func TestIPMatcherAnyMatchAndMatches(t *testing.T) { func TestIPMatcherAnyMatchAndMatches(t *testing.T) {
matcher := buildIPMatcher( matcher := buildIPMatcher(
"8.8.8.8/32", "8.8.8.8/32",

View File

@@ -17,6 +17,8 @@ func ParseIPRules(rules []string) ([]*IPRule, error) {
var ipRules []*IPRule var ipRules []*IPRule
for i, r := range rules { for i, r := range rules {
r, reverse := cutReversePrefix(r)
if strings.HasPrefix(r, "geoip:") { if strings.HasPrefix(r, "geoip:") {
r = "ext:" + DefaultGeoIPDat + ":" + r[len("geoip:"):] r = "ext:" + DefaultGeoIPDat + ":" + r[len("geoip:"):]
} }
@@ -32,9 +34,9 @@ func ParseIPRules(rules []string) ([]*IPRule, error) {
var rule isIPRule_Value var rule isIPRule_Value
var err error var err error
if prefix > 0 { if prefix > 0 {
rule, err = parseGeoIPRule(r[prefix:]) rule, err = parseGeoIPRule(r[prefix:], reverse)
} else { } else {
rule, err = parseCustomIPRule(r) rule, err = parseCustomIPRule(r, reverse)
} }
if err != nil { if err != nil {
return nil, errors.New("illegal ip rule: ", rules[i]).Base(err) return nil, errors.New("illegal ip rule: ", rules[i]).Base(err)
@@ -45,7 +47,16 @@ func ParseIPRules(rules []string) ([]*IPRule, error) {
return ipRules, nil return ipRules, nil
} }
func parseGeoIPRule(rule string) (*IPRule_Geoip, error) { func cutReversePrefix(s string) (string, bool) {
reverse := false
for strings.HasPrefix(s, "!") {
s = s[1:]
reverse = !reverse
}
return s, reverse
}
func parseGeoIPRule(rule string, reverse bool) (*IPRule_Geoip, error) {
file, code, ok := strings.Cut(rule, ":") file, code, ok := strings.Cut(rule, ":")
if !ok { if !ok {
return nil, errors.New("syntax error") return nil, errors.New("syntax error")
@@ -55,11 +66,8 @@ func parseGeoIPRule(rule string) (*IPRule_Geoip, error) {
return nil, errors.New("empty file") return nil, errors.New("empty file")
} }
reverse := false code, codeReverse := cutReversePrefix(code)
if strings.HasPrefix(code, "!") { reverse = reverse != codeReverse
code = code[1:]
reverse = true
}
if code == "" { if code == "" {
return nil, errors.New("empty code") return nil, errors.New("empty code")
} }
@@ -78,13 +86,16 @@ func parseGeoIPRule(rule string) (*IPRule_Geoip, error) {
}, nil }, nil
} }
func parseCustomIPRule(rule string) (*IPRule_Custom, error) { func parseCustomIPRule(rule string, reverse bool) (*IPRule_Custom, error) {
cidr, err := parseCIDR(rule) cidr, err := parseCIDR(rule)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &IPRule_Custom{ return &IPRule_Custom{
Custom: cidr, Custom: &CIDRRule{
Cidr: cidr,
ReverseMatch: reverse,
},
}, nil }, nil
} }

View File

@@ -13,12 +13,20 @@ func TestParseIPRules(t *testing.T) {
rules := []string{ rules := []string{
"geoip:us", "geoip:us",
"geoip:cn", "geoip:cn",
"!geoip:cn",
"!!geoip:cn",
"geoip:!cn", "geoip:!cn",
"geoip:!!cn",
"!geoip:!cn",
"ext:geoip.dat:!cn", "ext:geoip.dat:!cn",
"ext:geoip.dat:!!cn",
"ext:geoip.dat:ca", "ext:geoip.dat:ca",
"ext-ip:geoip.dat:!cn", "ext-ip:geoip.dat:!cn",
"ext-ip:geoip.dat:!ca", "ext-ip:geoip.dat:!ca",
"192.168.0.0/24", "192.168.0.0/24",
"!192.168.0.0/24",
"!!192.168.0.0/24",
"!!!192.168.0.0/24",
"192.168.0.1", "192.168.0.1",
"fe80::/64", "fe80::/64",
"fe80::", "fe80::",
@@ -30,6 +38,53 @@ func TestParseIPRules(t *testing.T) {
} }
} }
func TestParseIPRuleReverse(t *testing.T) {
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
for _, tt := range []struct {
rule string
reverse bool
}{
{rule: "!192.168.0.0/24", reverse: true},
{rule: "!!192.168.0.0/24", reverse: false},
{rule: "!!!192.168.0.0/24", reverse: true},
{rule: "!!!!192.168.0.0/24", reverse: false},
{rule: "geoip:cn", reverse: false},
{rule: "!geoip:cn", reverse: true},
{rule: "!!geoip:cn", reverse: false},
{rule: "geoip:!cn", reverse: true},
{rule: "geoip:!!cn", reverse: false},
{rule: "!geoip:!cn", reverse: false},
{rule: "!!geoip:!cn", reverse: true},
{rule: "!geoip:!!cn", reverse: true},
{rule: "ext:geoip.dat:!!!cn", reverse: true},
} {
t.Run(tt.rule, func(t *testing.T) {
rules, err := geodata.ParseIPRules([]string{tt.rule})
if err != nil {
t.Fatalf("Failed to parse ip rules, got %s", err)
}
if len(rules) != 1 {
t.Fatalf("Expected 1 rule, got %d", len(rules))
}
switch rule := rules[0]; {
case rule.GetGeoip() != nil:
if rule.GetGeoip().GetReverseMatch() != tt.reverse {
t.Fatalf("Expected geoip reverse match to be %t", tt.reverse)
}
case rule.GetCustom() != nil:
if rule.GetCustom().GetReverseMatch() != tt.reverse {
t.Fatalf("Expected custom reverse match to be %t", tt.reverse)
}
default:
t.Fatal("Expected ip rule")
}
})
}
}
func TestParseDomainRules(t *testing.T) { func TestParseDomainRules(t *testing.T) {
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources")) t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))

View File

@@ -135,17 +135,15 @@ func TestRouterConfig(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{10, 0, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
Prefix: 8,
}, },
}, },
}, },
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, Cidr: &geodata.CIDR{Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, Prefix: 128},
Prefix: 128,
}, },
}, },
}, },
@@ -216,17 +214,15 @@ func TestRouterConfig(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{10, 0, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
Prefix: 8,
}, },
}, },
}, },
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, Cidr: &geodata.CIDR{Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, Prefix: 128},
Prefix: 128,
}, },
}, },
}, },

View File

@@ -99,9 +99,8 @@ func TestXrayConfig(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{10, 0, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
Prefix: 8,
}, },
}, },
}, },
@@ -216,8 +215,12 @@ func TestSniffingConfig_Build(t *testing.T) {
if rule == nil { if rule == nil {
t.Fatalf("SniffingConfig.Build() produced a non-custom ip rule at index %d", i) t.Fatalf("SniffingConfig.Build() produced a non-custom ip rule at index %d", i)
} }
if !reflect.DeepEqual(rule.Ip, tc.ip) || rule.Prefix != tc.prefix { cidr := rule.GetCidr()
t.Fatalf("SniffingConfig.Build() produced wrong ip rule at index %d: got (%v, %d), want (%v, %d)", i, rule.Ip, rule.Prefix, tc.ip, tc.prefix) if cidr == nil {
t.Fatalf("SniffingConfig.Build() produced a custom ip rule without cidr at index %d", i)
}
if !reflect.DeepEqual(cidr.Ip, tc.ip) || cidr.Prefix != tc.prefix {
t.Fatalf("SniffingConfig.Build() produced wrong ip rule at index %d: got (%v, %d), want (%v, %d)", i, cidr.Ip, cidr.Prefix, tc.ip, tc.prefix)
} }
} }
} }

View File

@@ -47,9 +47,8 @@ func TestResolveIP(t *testing.T) {
Ip: []*geodata.IPRule{ Ip: []*geodata.IPRule{
{ {
Value: &geodata.IPRule_Custom{ Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDR{ Custom: &geodata.CIDRRule{
Ip: []byte{127, 0, 0, 0}, Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
Prefix: 8,
}, },
}, },
}, },