1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-18 05:25:23 +00:00

prototype for high performance geoip matcher

This commit is contained in:
Darien Raymond 2018-11-01 09:10:41 +01:00
parent ee74256aac
commit c73e899f54
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
8 changed files with 581 additions and 58 deletions

View File

@ -226,6 +226,57 @@ func (v *IPv4Matcher) Apply(ctx context.Context) bool {
return false
}
type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
onSource bool
}
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher
for _, geoip := range geoips {
matcher, err := globalGeoIPContainer.Add(geoip)
if err != nil {
return nil, err
}
matchers = append(matchers, matcher)
}
return &MultiGeoIPMatcher{
matchers: matchers,
onSource: onSource,
}, nil
}
func (m *MultiGeoIPMatcher) Apply(ctx context.Context) bool {
ips := make([]net.IP, 0, 4)
if resolver, ok := ResolvedIPsFromContext(ctx); ok {
resolvedIPs := resolver.Resolve()
for _, rip := range resolvedIPs {
ips = append(ips, rip.IP())
}
}
var dest net.Destination
if m.onSource {
dest = sourceFromContext(ctx)
} else {
dest = targetFromContent(ctx)
}
if dest.IsValid() && (dest.Address.Family().IsIPv4() || dest.Address.Family().IsIPv6()) {
ips = append(ips, dest.Address.IP())
}
for _, ip := range ips {
for _, matcher := range m.matchers {
if matcher.Match(ip) {
return true
}
}
}
return false
}
type PortMatcher struct {
port net.PortRange
}

View File

@ -0,0 +1,197 @@
package router
import (
"v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
)
type ipv6 struct {
a uint64
b uint64
}
type GeoIPMatcher struct {
countryCode string
ip4 []uint32
prefix4 []uint8
ip6 []ipv6
prefix6 []uint8
}
func normalize4(ip uint32, prefix uint8) uint32 {
return (ip >> (32 - prefix)) << (32 - prefix)
}
func normalize6(ip ipv6, prefix uint8) ipv6 {
if prefix < 64 {
ip.a = (ip.a >> (64 - prefix)) << (64 - prefix)
}
if prefix <= 64 {
ip.b = 0
} else {
ip.b = (ip.b >> (128 - prefix)) << (128 - prefix)
}
return ip
}
func (m *GeoIPMatcher) Init(cidrs []*CIDR) error {
ip4Count := 0
ip6Count := 0
for _, cidr := range cidrs {
ip := cidr.Ip
switch len(ip) {
case 4:
ip4Count++
case 16:
ip6Count++
default:
return newError("unexpect ip length: ", len(ip))
}
}
m.ip4 = make([]uint32, 0, ip4Count)
m.prefix4 = make([]uint8, 0, ip4Count)
m.ip6 = make([]ipv6, 0, ip6Count)
m.prefix6 = make([]uint8, 0, ip6Count)
for _, cidr := range cidrs {
ip := cidr.Ip
prefix := uint8(cidr.Prefix)
switch len(ip) {
case 4:
m.ip4 = append(m.ip4, normalize4(serial.BytesToUint32(ip), prefix))
m.prefix4 = append(m.prefix4, prefix)
case 16:
ip6 := ipv6{
a: serial.BytesToUint64(ip[0:8]),
b: serial.BytesToUint64(ip[8:16]),
}
ip6 = normalize6(ip6, prefix)
m.ip6 = append(m.ip6, ip6)
m.prefix6 = append(m.prefix6, prefix)
}
}
return nil
}
func (m *GeoIPMatcher) match4(ip uint32) bool {
if len(m.ip4) == 0 {
return false
}
if ip < m.ip4[0] {
return false
}
size := uint32(len(m.ip4))
if ip > m.ip4[size-1] {
nip := normalize4(ip, m.prefix4[size-1])
return nip == m.ip4[size-1]
}
l := uint32(0)
r := size - 1
for l < r-1 {
x := (l + r) / 2
if ip < m.ip4[x] {
r = x
continue
}
nip := normalize4(ip, m.prefix4[x])
if nip == m.ip4[x] {
return true
}
l = x
}
return normalize4(ip, m.prefix4[l]) == m.ip4[l]
}
func less6(a ipv6, b ipv6) bool {
return a.a < b.a || (a.a == b.a && a.b < b.b)
}
func (m *GeoIPMatcher) match6(ip ipv6) bool {
if len(m.ip6) == 0 {
return false
}
if less6(ip, m.ip6[0]) {
return false
}
size := uint32(len(m.ip6))
if less6(m.ip6[size-1], ip) {
nip := normalize6(ip, m.prefix6[size-1])
return nip == m.ip6[size-1]
}
l := uint32(0)
r := size - 1
for l < r-1 {
x := (l + r) / 2
if less6(ip, m.ip6[x]) {
r = x
continue
}
nip := normalize6(ip, m.prefix6[x])
if nip == m.ip6[x] {
return true
}
l = x
}
return normalize6(ip, m.prefix6[l]) == m.ip6[l]
}
func (m *GeoIPMatcher) Match(ip net.IP) bool {
switch len(ip) {
case 4:
return m.match4(serial.BytesToUint32(ip))
case 16:
return m.match6(ipv6{
a: serial.BytesToUint64(ip[0:8]),
b: serial.BytesToUint64(ip[8:16]),
})
default:
return false
}
}
type GlobalGeoIPContainer struct {
matchers []*GeoIPMatcher
}
func (c *GlobalGeoIPContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
if len(geoip.CountryCode) > 0 {
for _, m := range c.matchers {
if m.countryCode == geoip.CountryCode {
return m, nil
}
}
}
m := &GeoIPMatcher{
countryCode: geoip.CountryCode,
}
if err := m.Init(geoip.Cidr); err != nil {
return nil, err
}
if len(geoip.CountryCode) > 0 {
c.matchers = append(c.matchers, m)
}
return m, nil
}
var (
globalGeoIPContainer GlobalGeoIPContainer
)

View File

@ -0,0 +1,167 @@
package router_test
import (
"os"
"path/filepath"
"sort"
"testing"
proto "github.com/golang/protobuf/proto"
"v2ray.com/core/app/router"
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/platform"
"v2ray.com/ext/sysio"
)
func TestGeoIPMatcher(t *testing.T) {
cidrList := router.CIDRList{
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
{Ip: []byte{100, 64, 0, 0}, Prefix: 10},
{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
{Ip: []byte{169, 254, 0, 0}, Prefix: 16},
{Ip: []byte{172, 16, 0, 0}, Prefix: 12},
{Ip: []byte{192, 0, 0, 0}, Prefix: 24},
{Ip: []byte{192, 0, 2, 0}, Prefix: 24},
{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
{Ip: []byte{192, 18, 0, 0}, Prefix: 15},
{Ip: []byte{198, 51, 100, 0}, Prefix: 24},
{Ip: []byte{203, 0, 113, 0}, Prefix: 24},
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
}
sort.Sort(&cidrList)
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(cidrList))
testCases := []struct {
Input string
Output bool
}{
{
Input: "192.168.1.1",
Output: true,
},
{
Input: "192.0.0.0",
Output: true,
},
{
Input: "192.0.1.0",
Output: false,
}, {
Input: "0.1.0.0",
Output: true,
},
{
Input: "1.0.0.1",
Output: false,
},
{
Input: "8.8.8.7",
Output: false,
},
{
Input: "8.8.8.8",
Output: true,
},
{
Input: "2001:cdba::3257:9652",
Output: false,
},
{
Input: "91.108.255.254",
Output: true,
},
}
for _, testCase := range testCases {
ip := net.ParseAddress(testCase.Input).IP()
actual := matcher.Match(ip)
if actual != testCase.Output {
t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
}
}
}
func TestGeoIPMatcher4CN(t *testing.T) {
common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "release", "config", "geoip.dat")))
ips, err := loadGeoIP("CN")
common.Must(err)
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips))
if matcher.Match([]byte{8, 8, 8, 8}) {
t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
}
}
func TestGeoIPMatcher6US(t *testing.T) {
common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "release", "config", "geoip.dat")))
ips, err := loadGeoIP("US")
common.Must(err)
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips))
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
}
}
func loadGeoIP(country string) ([]*router.CIDR, error) {
geoipBytes, err := sysio.ReadAsset("geoip.dat")
if err != nil {
return nil, err
}
var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err
}
for _, geoip := range geoipList.Entry {
if geoip.CountryCode == country {
return geoip.Cidr, nil
}
}
panic("country not found: " + country)
}
func BenchmarkGeoIPMatcher4CN(b *testing.B) {
common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "release", "config", "geoip.dat")))
ips, err := loadGeoIP("CN")
common.Must(err)
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = matcher.Match([]byte{8, 8, 8, 8})
}
}
func BenchmarkGeoIPMatcher6US(b *testing.B) {
common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "release", "config", "geoip.dat")))
ips, err := loadGeoIP("US")
common.Must(err)
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP())
}
}

View File

@ -124,6 +124,46 @@ func TestRoutingRule(t *testing.T) {
},
},
},
{
rule: &RoutingRule{
Geoip: []*GeoIP{
{
Cidr: []*CIDR{
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
{
Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(),
Prefix: 128,
},
},
},
},
},
test: []ruleTest{
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)}),
output: true,
},
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.4.4"), 80)}),
output: false,
},
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 80)}),
output: true,
},
{
input: context.Background(),
output: false,
},
},
},
{
rule: &RoutingRule{
SourceCidr: []*CIDR{

View File

@ -111,7 +111,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
conds.Add(NewNetworkMatcher(rr.NetworkList))
}
if len(rr.Cidr) > 0 {
if len(rr.Geoip) > 0 {
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
if err != nil {
return nil, err
}
conds.Add(cond)
} else if len(rr.Cidr) > 0 {
cond, err := cidrToCondition(rr.Cidr, false)
if err != nil {
return nil, err
@ -119,7 +125,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
conds.Add(cond)
}
if len(rr.SourceCidr) > 0 {
if len(rr.SourceGeoip) > 0 {
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
if err != nil {
return nil, err
}
conds.Add(cond)
} else if len(rr.SourceCidr) > 0 {
cond, err := cidrToCondition(rr.SourceCidr, true)
if err != nil {
return nil, err

View File

@ -362,18 +362,24 @@ func (m *GeoSiteList) GetEntry() []*GeoSite {
}
type RoutingRule struct {
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"`
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,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"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
// List of CIDRs for target IP address matching.
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"` // Deprecated: Do not use.
// List of GeoIPs for target IP address matching. If this entry exists, the cidr above will have no effect.
Geoip []*GeoIP `protobuf:"bytes,10,rep,name=geoip,proto3" json:"geoip,omitempty"`
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
// List of CIDRs for source IP address matching.
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,omitempty"` // Deprecated: Do not use.
// 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"`
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"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RoutingRule) Reset() { *m = RoutingRule{} }
@ -415,6 +421,7 @@ func (m *RoutingRule) GetDomain() []*Domain {
return nil
}
// Deprecated: Do not use.
func (m *RoutingRule) GetCidr() []*CIDR {
if m != nil {
return m.Cidr
@ -422,6 +429,13 @@ func (m *RoutingRule) GetCidr() []*CIDR {
return nil
}
func (m *RoutingRule) GetGeoip() []*GeoIP {
if m != nil {
return m.Geoip
}
return nil
}
func (m *RoutingRule) GetPortRange() *net.PortRange {
if m != nil {
return m.PortRange
@ -436,6 +450,7 @@ func (m *RoutingRule) GetNetworkList() *net.NetworkList {
return nil
}
// Deprecated: Do not use.
func (m *RoutingRule) GetSourceCidr() []*CIDR {
if m != nil {
return m.SourceCidr
@ -443,6 +458,13 @@ func (m *RoutingRule) GetSourceCidr() []*CIDR {
return nil
}
func (m *RoutingRule) GetSourceGeoip() []*GeoIP {
if m != nil {
return m.SourceGeoip
}
return nil
}
func (m *RoutingRule) GetUserEmail() []string {
if m != nil {
return m.UserEmail
@ -529,46 +551,49 @@ func init() {
}
var fileDescriptor_6b1608360690c5fc = []byte{
// 656 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xd3, 0x30,
0x14, 0x26, 0xfd, 0xdb, 0x72, 0x52, 0x4a, 0x64, 0x31, 0x14, 0x06, 0x83, 0x12, 0x21, 0xe8, 0x05,
0x4a, 0xa5, 0xf2, 0x73, 0x05, 0x9a, 0x46, 0x37, 0xa6, 0x4a, 0x30, 0x2a, 0x6f, 0xe3, 0x02, 0x2e,
0x2a, 0x2f, 0xf5, 0x42, 0x44, 0x62, 0x5b, 0x8e, 0x33, 0xd6, 0x57, 0xe0, 0x4d, 0xe0, 0xa9, 0x78,
0x14, 0x64, 0x3b, 0x1d, 0x1b, 0x5a, 0x60, 0xe2, 0xce, 0xc7, 0xf9, 0xbe, 0x73, 0x3e, 0x7f, 0x39,
0xe7, 0xc0, 0xa3, 0x93, 0x91, 0x24, 0x8b, 0x28, 0xe6, 0xf9, 0x30, 0xe6, 0x92, 0x0e, 0x89, 0x10,
0x43, 0xc9, 0x4b, 0x45, 0xe5, 0x30, 0xe6, 0xec, 0x38, 0x4d, 0x22, 0x21, 0xb9, 0xe2, 0x68, 0x6d,
0x89, 0x93, 0x34, 0x22, 0x42, 0x44, 0x16, 0xb3, 0xfe, 0xf0, 0x0f, 0x7a, 0xcc, 0xf3, 0x9c, 0xb3,
0x21, 0xa3, 0x6a, 0x28, 0xb8, 0x54, 0x96, 0xbc, 0xfe, 0xb8, 0x1e, 0xc5, 0xa8, 0xfa, 0xca, 0xe5,
0x17, 0x0b, 0x0c, 0xbf, 0x39, 0xd0, 0xd9, 0xe6, 0x39, 0x49, 0x19, 0x7a, 0x01, 0x2d, 0xb5, 0x10,
0x34, 0x70, 0xfa, 0xce, 0xa0, 0x37, 0x0a, 0xa3, 0x4b, 0xeb, 0x47, 0x16, 0x1c, 0x1d, 0x2c, 0x04,
0xc5, 0x06, 0x8f, 0x6e, 0x42, 0xfb, 0x84, 0x64, 0x25, 0x0d, 0x1a, 0x7d, 0x67, 0xe0, 0x62, 0x1b,
0x84, 0x23, 0x68, 0x69, 0x0c, 0x72, 0xa1, 0x3d, 0xcd, 0x48, 0xca, 0xfc, 0x6b, 0xfa, 0x88, 0x69,
0x42, 0x4f, 0x7d, 0x07, 0xc1, 0xb2, 0xaa, 0xdf, 0x40, 0xab, 0xd0, 0x7a, 0x53, 0x66, 0x99, 0xdf,
0x0c, 0x23, 0x68, 0x8d, 0x27, 0xdb, 0x18, 0xf5, 0xa0, 0x91, 0x0a, 0xa3, 0xa3, 0x8b, 0x1b, 0xa9,
0x40, 0xb7, 0xa0, 0x23, 0x24, 0x3d, 0x4e, 0x4f, 0x4d, 0x89, 0xeb, 0xb8, 0x8a, 0xc2, 0x4f, 0xd0,
0xde, 0xa5, 0x7c, 0x32, 0x45, 0x0f, 0xa0, 0x1b, 0xf3, 0x92, 0x29, 0xb9, 0x98, 0xc5, 0x7c, 0x6e,
0x9f, 0xe0, 0x62, 0xaf, 0xba, 0x1b, 0xf3, 0x39, 0x45, 0x43, 0x68, 0xc5, 0xe9, 0x5c, 0x06, 0x8d,
0x7e, 0x73, 0xe0, 0x8d, 0xee, 0xd4, 0xbc, 0x4e, 0x97, 0xc7, 0x06, 0x18, 0x6e, 0x82, 0x6b, 0x92,
0xbf, 0x4d, 0x0b, 0x85, 0x46, 0xd0, 0xa6, 0x3a, 0x55, 0xe0, 0x18, 0xfa, 0xdd, 0x1a, 0xba, 0x21,
0x60, 0x0b, 0x0d, 0x63, 0x58, 0xd9, 0xa5, 0x7c, 0x3f, 0x55, 0xf4, 0x2a, 0xfa, 0x9e, 0x43, 0x67,
0x6e, 0x1c, 0xa9, 0x14, 0x6e, 0xfc, 0xd5, 0x7f, 0x5c, 0x81, 0xc3, 0x31, 0x78, 0x55, 0x11, 0xa3,
0xf3, 0xd9, 0x45, 0x9d, 0xf7, 0xea, 0x75, 0x6a, 0xca, 0x52, 0xe9, 0xf7, 0x26, 0x78, 0x98, 0x97,
0x2a, 0x65, 0x09, 0x2e, 0x33, 0x8a, 0x7c, 0x68, 0x2a, 0x92, 0x54, 0x2a, 0xf5, 0xf1, 0x3f, 0xd5,
0x9d, 0x99, 0xde, 0xbc, 0xa2, 0xe9, 0x68, 0x13, 0x40, 0x77, 0xf1, 0x4c, 0x12, 0x96, 0xd0, 0xa0,
0xd5, 0x77, 0x06, 0xde, 0xa8, 0x7f, 0x9e, 0x66, 0x1b, 0x39, 0x62, 0x54, 0x45, 0x53, 0x2e, 0x15,
0xd6, 0x38, 0xec, 0x8a, 0xe5, 0x11, 0xed, 0x40, 0xb7, 0x6a, 0xf0, 0x59, 0x96, 0x16, 0x2a, 0x68,
0x9b, 0x14, 0x61, 0x4d, 0x8a, 0x3d, 0x0b, 0xd5, 0xd6, 0x61, 0x8f, 0xfd, 0x0e, 0xd0, 0x4b, 0xf0,
0x0a, 0x5e, 0xca, 0x98, 0xce, 0x8c, 0xfe, 0xce, 0xbf, 0xf5, 0x83, 0xc5, 0x8f, 0xf5, 0x2b, 0x36,
0x00, 0xca, 0x82, 0xca, 0x19, 0xcd, 0x49, 0x9a, 0x05, 0x2b, 0xfd, 0xe6, 0xc0, 0xc5, 0xae, 0xbe,
0xd9, 0xd1, 0x17, 0xe8, 0x3e, 0x78, 0x29, 0x3b, 0xe2, 0x25, 0x9b, 0xcf, 0xb4, 0xcd, 0xab, 0xe6,
0x3b, 0x54, 0x57, 0x07, 0x24, 0x41, 0xeb, 0xb0, 0x6a, 0xa6, 0x33, 0xe6, 0x59, 0xe0, 0x9a, 0xaf,
0x67, 0x71, 0xf8, 0xd3, 0x81, 0xce, 0xd8, 0xec, 0x09, 0x74, 0x08, 0x37, 0xac, 0xcf, 0xb3, 0x42,
0x49, 0xa2, 0x68, 0xb2, 0xa8, 0x66, 0xf7, 0x49, 0x9d, 0x50, 0xbb, 0x5f, 0xec, 0x4f, 0xda, 0xaf,
0x38, 0xb8, 0x37, 0xbf, 0x10, 0xeb, 0x3d, 0x20, 0xcb, 0x8c, 0x56, 0x7f, 0xba, 0x6e, 0x0f, 0x9c,
0xeb, 0x17, 0x6c, 0xf0, 0xe1, 0x2e, 0xf4, 0x2e, 0x66, 0xd6, 0x93, 0xbd, 0x55, 0x4c, 0x0a, 0x3b,
0xfa, 0x87, 0x05, 0x9d, 0x08, 0xdf, 0x41, 0x3e, 0x74, 0x27, 0x62, 0x72, 0xbc, 0xc7, 0xd9, 0x3b,
0xa2, 0xe2, 0xcf, 0x7e, 0x03, 0xf5, 0x00, 0x26, 0xe2, 0x3d, 0xdb, 0xa6, 0x39, 0x61, 0x73, 0xbf,
0xf9, 0xfa, 0x15, 0xdc, 0x8e, 0x79, 0x7e, 0x79, 0xdd, 0xa9, 0xf3, 0xb1, 0x63, 0x4f, 0x3f, 0x1a,
0x6b, 0x1f, 0x46, 0x98, 0x2c, 0xa2, 0xb1, 0x46, 0x6c, 0x09, 0x61, 0x24, 0x51, 0x79, 0xd4, 0x31,
0x5e, 0x3d, 0xfd, 0x15, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x7c, 0x4c, 0x99, 0x69, 0x05, 0x00, 0x00,
// 691 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xd3, 0x4c,
0x10, 0xfd, 0xec, 0xfc, 0xb4, 0x1e, 0xe7, 0x0b, 0xd6, 0x8a, 0x22, 0x53, 0x28, 0x04, 0x0b, 0x41,
0x2e, 0x90, 0x23, 0xa5, 0xc0, 0x1d, 0x2a, 0x6d, 0x5a, 0xa2, 0x48, 0x50, 0xa2, 0x6d, 0xcb, 0x05,
0x5c, 0x44, 0xae, 0xb3, 0x35, 0x16, 0xce, 0xee, 0x6a, 0xbd, 0x2e, 0xcd, 0x2b, 0xf0, 0x20, 0x5c,
0xf0, 0x54, 0x3c, 0x0a, 0xda, 0x9f, 0x40, 0x8b, 0x1a, 0x88, 0xb8, 0xdb, 0x59, 0x9f, 0x33, 0x73,
0xe6, 0x78, 0x76, 0xe0, 0xd1, 0x79, 0x5f, 0x24, 0xf3, 0x38, 0x65, 0xb3, 0x5e, 0xca, 0x04, 0xe9,
0x25, 0x9c, 0xf7, 0x04, 0xab, 0x24, 0x11, 0xbd, 0x94, 0xd1, 0xb3, 0x3c, 0x8b, 0xb9, 0x60, 0x92,
0xa1, 0x8d, 0x05, 0x4e, 0x90, 0x38, 0xe1, 0x3c, 0x36, 0x98, 0xcd, 0x87, 0xbf, 0xd1, 0x53, 0x36,
0x9b, 0x31, 0xda, 0xa3, 0x44, 0xf6, 0x38, 0x13, 0xd2, 0x90, 0x37, 0x1f, 0x2f, 0x47, 0x51, 0x22,
0x3f, 0x33, 0xf1, 0xc9, 0x00, 0xa3, 0x2f, 0x0e, 0x34, 0xf7, 0xd9, 0x2c, 0xc9, 0x29, 0x7a, 0x0e,
0x75, 0x39, 0xe7, 0x24, 0x74, 0x3a, 0x4e, 0xb7, 0xdd, 0x8f, 0xe2, 0x6b, 0xeb, 0xc7, 0x06, 0x1c,
0x1f, 0xcf, 0x39, 0xc1, 0x1a, 0x8f, 0x6e, 0x42, 0xe3, 0x3c, 0x29, 0x2a, 0x12, 0xba, 0x1d, 0xa7,
0xeb, 0x61, 0x13, 0x44, 0x7d, 0xa8, 0x2b, 0x0c, 0xf2, 0xa0, 0x31, 0x2e, 0x92, 0x9c, 0x06, 0xff,
0xa9, 0x23, 0x26, 0x19, 0xb9, 0x08, 0x1c, 0x04, 0x8b, 0xaa, 0x81, 0x8b, 0xd6, 0xa1, 0xfe, 0xaa,
0x2a, 0x8a, 0xa0, 0x16, 0xc5, 0x50, 0x1f, 0x8c, 0xf6, 0x31, 0x6a, 0x83, 0x9b, 0x73, 0xad, 0xa3,
0x85, 0xdd, 0x9c, 0xa3, 0x5b, 0xd0, 0xe4, 0x82, 0x9c, 0xe5, 0x17, 0xba, 0xc4, 0xff, 0xd8, 0x46,
0xd1, 0x07, 0x68, 0x0c, 0x09, 0x1b, 0x8d, 0xd1, 0x03, 0x68, 0xa5, 0xac, 0xa2, 0x52, 0xcc, 0x27,
0x29, 0x9b, 0x9a, 0x16, 0x3c, 0xec, 0xdb, 0xbb, 0x01, 0x9b, 0x12, 0xd4, 0x83, 0x7a, 0x9a, 0x4f,
0x45, 0xe8, 0x76, 0x6a, 0x5d, 0xbf, 0x7f, 0x67, 0x49, 0x77, 0xaa, 0x3c, 0xd6, 0xc0, 0x68, 0x07,
0x3c, 0x9d, 0xfc, 0x75, 0x5e, 0x4a, 0xd4, 0x87, 0x06, 0x51, 0xa9, 0x42, 0x47, 0xd3, 0xef, 0x2e,
0xa1, 0x6b, 0x02, 0x36, 0xd0, 0x28, 0x85, 0xb5, 0x21, 0x61, 0x47, 0xb9, 0x24, 0xab, 0xe8, 0x7b,
0x06, 0xcd, 0xa9, 0x76, 0xc4, 0x2a, 0xdc, 0xfa, 0xa3, 0xff, 0xd8, 0x82, 0xa3, 0x01, 0xf8, 0xb6,
0x88, 0xd6, 0xf9, 0xf4, 0xaa, 0xce, 0x7b, 0xcb, 0x75, 0x2a, 0xca, 0x42, 0xe9, 0xd7, 0x3a, 0xf8,
0x98, 0x55, 0x32, 0xa7, 0x19, 0xae, 0x0a, 0x82, 0x02, 0xa8, 0xc9, 0x24, 0xb3, 0x2a, 0xd5, 0xf1,
0x1f, 0xd5, 0xa1, 0x6d, 0x6b, 0x7a, 0xed, 0xaf, 0xa6, 0xef, 0xb9, 0xa1, 0x63, 0x8c, 0x57, 0x5e,
0x67, 0x84, 0xe5, 0x3c, 0x84, 0x55, 0xbc, 0xd6, 0x50, 0xb4, 0x03, 0xa0, 0xa6, 0x7f, 0x22, 0x12,
0x9a, 0x91, 0xb0, 0xde, 0x71, 0xba, 0x7e, 0xbf, 0x73, 0x99, 0x68, 0x1e, 0x40, 0x4c, 0x89, 0x8c,
0xc7, 0x4c, 0x48, 0xac, 0x70, 0xd8, 0xe3, 0x8b, 0x23, 0x3a, 0x80, 0x96, 0x7d, 0x18, 0x93, 0x22,
0x2f, 0x65, 0xd8, 0xd0, 0x29, 0xa2, 0x25, 0x29, 0x0e, 0x0d, 0x54, 0x59, 0x8e, 0x7d, 0xfa, 0x2b,
0x40, 0x2f, 0xc1, 0x2f, 0x59, 0x25, 0x52, 0x32, 0xd1, 0x7d, 0x37, 0x57, 0xeb, 0x1b, 0x0c, 0x67,
0xa0, 0xba, 0xdf, 0x81, 0x96, 0xcd, 0x60, 0x4c, 0xf0, 0x57, 0x30, 0xc1, 0xd6, 0x1c, 0x6a, 0x2b,
0xb6, 0x00, 0xaa, 0x92, 0x88, 0x09, 0x99, 0x25, 0x79, 0x11, 0xae, 0x75, 0x6a, 0x5d, 0x0f, 0x7b,
0xea, 0xe6, 0x40, 0x5d, 0xa0, 0xfb, 0xe0, 0xe7, 0xf4, 0x94, 0x55, 0x74, 0x3a, 0x51, 0xff, 0x78,
0x5d, 0x7f, 0x07, 0x7b, 0x75, 0x9c, 0x64, 0x68, 0x13, 0xd6, 0xf5, 0x6a, 0x48, 0x59, 0x11, 0x7a,
0xfa, 0xeb, 0xcf, 0x38, 0xfa, 0xee, 0x40, 0x73, 0xa0, 0x97, 0x14, 0x3a, 0x81, 0x1b, 0xe6, 0x27,
0x4f, 0x4a, 0x29, 0x12, 0x49, 0xb2, 0xb9, 0x5d, 0x1c, 0x4f, 0x96, 0x75, 0x6b, 0x96, 0x9b, 0x99,
0x90, 0x23, 0xcb, 0xc1, 0xed, 0xe9, 0x95, 0x58, 0x2d, 0x21, 0x51, 0x15, 0xc4, 0x8e, 0xd9, 0xb2,
0x25, 0x74, 0x69, 0x58, 0xb1, 0xc6, 0x47, 0x43, 0x68, 0x5f, 0xcd, 0xac, 0xd6, 0xca, 0x6e, 0x39,
0x2a, 0xcd, 0xde, 0x39, 0x29, 0xc9, 0x88, 0x07, 0x0e, 0x0a, 0xa0, 0x35, 0xe2, 0xa3, 0xb3, 0x43,
0x46, 0xdf, 0x24, 0x32, 0xfd, 0x18, 0xb8, 0xa8, 0x0d, 0x30, 0xe2, 0x6f, 0xe9, 0x3e, 0x99, 0x25,
0x74, 0x1a, 0xd4, 0xf6, 0x5e, 0xc0, 0xed, 0x94, 0xcd, 0xae, 0xaf, 0x3b, 0x76, 0xde, 0x37, 0xcd,
0xe9, 0x9b, 0xbb, 0xf1, 0xae, 0x8f, 0x93, 0x79, 0x3c, 0x50, 0x88, 0x5d, 0xce, 0xb5, 0x24, 0x22,
0x4e, 0x9b, 0xda, 0xab, 0xed, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x42, 0x5b, 0xf4, 0x78, 0xe6,
0x05, 0x00, 0x00,
}

View File

@ -58,12 +58,31 @@ message GeoSiteList{
}
message RoutingRule {
// Tag of outbound that this rule is pointing to.
string tag = 1;
repeated Domain domain = 2;
repeated CIDR cidr = 3;
// List of CIDRs for target IP address matching.
// The list must be sorted beforehand.
repeated CIDR cidr = 3 [deprecated = true];
// 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.
// The CIDR list in the GeoIP must be sorted beforehand.
repeated GeoIP geoip = 10;
v2ray.core.common.net.PortRange port_range = 4;
v2ray.core.common.net.NetworkList network_list = 5;
repeated CIDR source_cidr = 6;
// List of CIDRs for source IP address matching.
// The list must be sorted beforehand.
repeated CIDR source_cidr = 6 [deprecated = true];
// List of GeoIPs for source IP address matching. If this entry exists, the source_cidr above will have no effect.
// The CIDR list in the GeoIP must be sorted beforehand.
repeated GeoIP source_geoip = 11;
repeated string user_email = 7;
repeated string inbound_tag = 8;
repeated string protocol = 9;

View File

@ -44,6 +44,18 @@ func BytesToInt64(value []byte) int64 {
int64(value[7])
}
func BytesToUint64(value []byte) uint64 {
_ = value[7]
return uint64(value[0])<<56 |
uint64(value[1])<<48 |
uint64(value[2])<<40 |
uint64(value[3])<<32 |
uint64(value[4])<<24 |
uint64(value[5])<<16 |
uint64(value[6])<<8 |
uint64(value[7])
}
// BytesToHexString converts a byte array into hex string.
func BytesToHexString(value []byte) string {
m := hex.EncodedLen(len(value))