github.com/EagleQL/Xray-core@v1.4.3/app/router/condition_geoip_test.go (about)

     1  package router_test
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"github.com/golang/protobuf/proto"
     9  	"github.com/xtls/xray-core/app/router"
    10  	"github.com/xtls/xray-core/common"
    11  	"github.com/xtls/xray-core/common/net"
    12  	"github.com/xtls/xray-core/common/platform"
    13  	"github.com/xtls/xray-core/common/platform/filesystem"
    14  )
    15  
    16  func init() {
    17  	wd, err := os.Getwd()
    18  	common.Must(err)
    19  
    20  	if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
    21  		common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
    22  	}
    23  	if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
    24  		common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
    25  	}
    26  }
    27  
    28  func TestGeoIPMatcherContainer(t *testing.T) {
    29  	container := &router.GeoIPMatcherContainer{}
    30  
    31  	m1, err := container.Add(&router.GeoIP{
    32  		CountryCode: "CN",
    33  	})
    34  	common.Must(err)
    35  
    36  	m2, err := container.Add(&router.GeoIP{
    37  		CountryCode: "US",
    38  	})
    39  	common.Must(err)
    40  
    41  	m3, err := container.Add(&router.GeoIP{
    42  		CountryCode: "CN",
    43  	})
    44  	common.Must(err)
    45  
    46  	if m1 != m3 {
    47  		t.Error("expect same matcher for same geoip, but not")
    48  	}
    49  
    50  	if m1 == m2 {
    51  		t.Error("expect different matcher for different geoip, but actually same")
    52  	}
    53  }
    54  
    55  func TestGeoIPMatcher(t *testing.T) {
    56  	cidrList := router.CIDRList{
    57  		{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
    58  		{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
    59  		{Ip: []byte{100, 64, 0, 0}, Prefix: 10},
    60  		{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
    61  		{Ip: []byte{169, 254, 0, 0}, Prefix: 16},
    62  		{Ip: []byte{172, 16, 0, 0}, Prefix: 12},
    63  		{Ip: []byte{192, 0, 0, 0}, Prefix: 24},
    64  		{Ip: []byte{192, 0, 2, 0}, Prefix: 24},
    65  		{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
    66  		{Ip: []byte{192, 18, 0, 0}, Prefix: 15},
    67  		{Ip: []byte{198, 51, 100, 0}, Prefix: 24},
    68  		{Ip: []byte{203, 0, 113, 0}, Prefix: 24},
    69  		{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
    70  		{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
    71  	}
    72  
    73  	matcher := &router.GeoIPMatcher{}
    74  	common.Must(matcher.Init(cidrList))
    75  
    76  	testCases := []struct {
    77  		Input  string
    78  		Output bool
    79  	}{
    80  		{
    81  			Input:  "192.168.1.1",
    82  			Output: true,
    83  		},
    84  		{
    85  			Input:  "192.0.0.0",
    86  			Output: true,
    87  		},
    88  		{
    89  			Input:  "192.0.1.0",
    90  			Output: false,
    91  		}, {
    92  			Input:  "0.1.0.0",
    93  			Output: true,
    94  		},
    95  		{
    96  			Input:  "1.0.0.1",
    97  			Output: false,
    98  		},
    99  		{
   100  			Input:  "8.8.8.7",
   101  			Output: false,
   102  		},
   103  		{
   104  			Input:  "8.8.8.8",
   105  			Output: true,
   106  		},
   107  		{
   108  			Input:  "2001:cdba::3257:9652",
   109  			Output: false,
   110  		},
   111  		{
   112  			Input:  "91.108.255.254",
   113  			Output: true,
   114  		},
   115  	}
   116  
   117  	for _, testCase := range testCases {
   118  		ip := net.ParseAddress(testCase.Input).IP()
   119  		actual := matcher.Match(ip)
   120  		if actual != testCase.Output {
   121  			t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
   122  		}
   123  	}
   124  }
   125  
   126  func TestGeoIPMatcher4CN(t *testing.T) {
   127  	ips, err := loadGeoIP("CN")
   128  	common.Must(err)
   129  
   130  	matcher := &router.GeoIPMatcher{}
   131  	common.Must(matcher.Init(ips))
   132  
   133  	if matcher.Match([]byte{8, 8, 8, 8}) {
   134  		t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
   135  	}
   136  }
   137  
   138  func TestGeoIPMatcher6US(t *testing.T) {
   139  	ips, err := loadGeoIP("US")
   140  	common.Must(err)
   141  
   142  	matcher := &router.GeoIPMatcher{}
   143  	common.Must(matcher.Init(ips))
   144  
   145  	if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
   146  		t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
   147  	}
   148  }
   149  
   150  func loadGeoIP(country string) ([]*router.CIDR, error) {
   151  	geoipBytes, err := filesystem.ReadAsset("geoip.dat")
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	var geoipList router.GeoIPList
   156  	if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	for _, geoip := range geoipList.Entry {
   161  		if geoip.CountryCode == country {
   162  			return geoip.Cidr, nil
   163  		}
   164  	}
   165  
   166  	panic("country not found: " + country)
   167  }
   168  
   169  func BenchmarkGeoIPMatcher4CN(b *testing.B) {
   170  	ips, err := loadGeoIP("CN")
   171  	common.Must(err)
   172  
   173  	matcher := &router.GeoIPMatcher{}
   174  	common.Must(matcher.Init(ips))
   175  
   176  	b.ResetTimer()
   177  
   178  	for i := 0; i < b.N; i++ {
   179  		_ = matcher.Match([]byte{8, 8, 8, 8})
   180  	}
   181  }
   182  
   183  func BenchmarkGeoIPMatcher6US(b *testing.B) {
   184  	ips, err := loadGeoIP("US")
   185  	common.Must(err)
   186  
   187  	matcher := &router.GeoIPMatcher{}
   188  	common.Must(matcher.Init(ips))
   189  
   190  	b.ResetTimer()
   191  
   192  	for i := 0; i < b.N; i++ {
   193  		_ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP())
   194  	}
   195  }