condition_geoip_test.go 4.3 KB

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