condition_geoip_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. {
  80. Input: "0.1.0.0",
  81. Output: true,
  82. },
  83. {
  84. Input: "1.0.0.1",
  85. Output: false,
  86. },
  87. {
  88. Input: "8.8.8.7",
  89. Output: false,
  90. },
  91. {
  92. Input: "8.8.8.8",
  93. Output: true,
  94. },
  95. {
  96. Input: "2001:cdba::3257:9652",
  97. Output: false,
  98. },
  99. {
  100. Input: "91.108.255.254",
  101. Output: true,
  102. },
  103. }
  104. for _, testCase := range testCases {
  105. ip := net.ParseAddress(testCase.Input).IP()
  106. actual := matcher.Match(ip)
  107. if actual != testCase.Output {
  108. t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
  109. }
  110. }
  111. }
  112. func TestGeoIPReverseMatcher(t *testing.T) {
  113. cidrList := router.CIDRList{
  114. {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
  115. {Ip: []byte{91, 108, 4, 0}, Prefix: 16},
  116. }
  117. matcher := &router.GeoIPMatcher{}
  118. matcher.SetReverseMatch(true) // Reverse match
  119. common.Must(matcher.Init(cidrList))
  120. testCases := []struct {
  121. Input string
  122. Output bool
  123. }{
  124. {
  125. Input: "8.8.8.8",
  126. Output: false,
  127. },
  128. {
  129. Input: "2001:cdba::3257:9652",
  130. Output: true,
  131. },
  132. {
  133. Input: "91.108.255.254",
  134. Output: false,
  135. },
  136. }
  137. for _, testCase := range testCases {
  138. ip := net.ParseAddress(testCase.Input).IP()
  139. actual := matcher.Match(ip)
  140. if actual != testCase.Output {
  141. t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
  142. }
  143. }
  144. }
  145. func TestGeoIPMatcher4CN(t *testing.T) {
  146. ips, err := loadGeoIP("CN")
  147. common.Must(err)
  148. matcher := &router.GeoIPMatcher{}
  149. common.Must(matcher.Init(ips))
  150. if matcher.Match([]byte{8, 8, 8, 8}) {
  151. t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
  152. }
  153. }
  154. func TestGeoIPMatcher6US(t *testing.T) {
  155. ips, err := loadGeoIP("US")
  156. common.Must(err)
  157. matcher := &router.GeoIPMatcher{}
  158. common.Must(matcher.Init(ips))
  159. if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
  160. t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
  161. }
  162. }
  163. func loadGeoIP(country string) ([]*router.CIDR, error) {
  164. geoipBytes, err := filesystem.ReadAsset("geoip.dat")
  165. if err != nil {
  166. return nil, err
  167. }
  168. var geoipList router.GeoIPList
  169. if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
  170. return nil, err
  171. }
  172. for _, geoip := range geoipList.Entry {
  173. if geoip.CountryCode == country {
  174. return geoip.Cidr, nil
  175. }
  176. }
  177. panic("country not found: " + country)
  178. }
  179. func BenchmarkGeoIPMatcher4CN(b *testing.B) {
  180. ips, err := loadGeoIP("CN")
  181. common.Must(err)
  182. matcher := &router.GeoIPMatcher{}
  183. common.Must(matcher.Init(ips))
  184. b.ResetTimer()
  185. for i := 0; i < b.N; i++ {
  186. _ = matcher.Match([]byte{8, 8, 8, 8})
  187. }
  188. }
  189. func BenchmarkGeoIPMatcher6US(b *testing.B) {
  190. ips, err := loadGeoIP("US")
  191. common.Must(err)
  192. matcher := &router.GeoIPMatcher{}
  193. common.Must(matcher.Init(ips))
  194. b.ResetTimer()
  195. for i := 0; i < b.N; i++ {
  196. _ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP())
  197. }
  198. }