condition_geoip_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package router_test
  2. import (
  3. "os"
  4. "path/filepath"
  5. "testing"
  6. "github.com/xtls/xray-core/app/router"
  7. "github.com/xtls/xray-core/common"
  8. "github.com/xtls/xray-core/common/net"
  9. "github.com/xtls/xray-core/common/platform"
  10. "github.com/xtls/xray-core/common/platform/filesystem"
  11. "google.golang.org/protobuf/proto"
  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.CIDR{
  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 TestGeoIPMatcherRegression(t *testing.T) {
  113. cidrList := []*router.CIDR{
  114. {Ip: []byte{98, 108, 20, 0}, Prefix: 22},
  115. {Ip: []byte{98, 108, 20, 0}, Prefix: 23},
  116. }
  117. matcher := &router.GeoIPMatcher{}
  118. common.Must(matcher.Init(cidrList))
  119. testCases := []struct {
  120. Input string
  121. Output bool
  122. }{
  123. {
  124. Input: "98.108.22.11",
  125. Output: true,
  126. },
  127. {
  128. Input: "98.108.25.0",
  129. Output: false,
  130. },
  131. }
  132. for _, testCase := range testCases {
  133. ip := net.ParseAddress(testCase.Input).IP()
  134. actual := matcher.Match(ip)
  135. if actual != testCase.Output {
  136. t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
  137. }
  138. }
  139. }
  140. func TestGeoIPReverseMatcher(t *testing.T) {
  141. cidrList := []*router.CIDR{
  142. {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
  143. {Ip: []byte{91, 108, 4, 0}, Prefix: 16},
  144. }
  145. matcher := &router.GeoIPMatcher{}
  146. matcher.SetReverseMatch(true) // Reverse match
  147. common.Must(matcher.Init(cidrList))
  148. testCases := []struct {
  149. Input string
  150. Output bool
  151. }{
  152. {
  153. Input: "8.8.8.8",
  154. Output: false,
  155. },
  156. {
  157. Input: "2001:cdba::3257:9652",
  158. Output: true,
  159. },
  160. {
  161. Input: "91.108.255.254",
  162. Output: false,
  163. },
  164. }
  165. for _, testCase := range testCases {
  166. ip := net.ParseAddress(testCase.Input).IP()
  167. actual := matcher.Match(ip)
  168. if actual != testCase.Output {
  169. t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
  170. }
  171. }
  172. }
  173. func TestGeoIPMatcher4CN(t *testing.T) {
  174. ips, err := loadGeoIP("CN")
  175. common.Must(err)
  176. matcher := &router.GeoIPMatcher{}
  177. common.Must(matcher.Init(ips))
  178. if matcher.Match([]byte{8, 8, 8, 8}) {
  179. t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
  180. }
  181. }
  182. func TestGeoIPMatcher6US(t *testing.T) {
  183. ips, err := loadGeoIP("US")
  184. common.Must(err)
  185. matcher := &router.GeoIPMatcher{}
  186. common.Must(matcher.Init(ips))
  187. if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
  188. t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
  189. }
  190. }
  191. func loadGeoIP(country string) ([]*router.CIDR, error) {
  192. geoipBytes, err := filesystem.ReadAsset("geoip.dat")
  193. if err != nil {
  194. return nil, err
  195. }
  196. var geoipList router.GeoIPList
  197. if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
  198. return nil, err
  199. }
  200. for _, geoip := range geoipList.Entry {
  201. if geoip.CountryCode == country {
  202. return geoip.Cidr, nil
  203. }
  204. }
  205. panic("country not found: " + country)
  206. }
  207. func BenchmarkGeoIPMatcher4CN(b *testing.B) {
  208. ips, err := loadGeoIP("CN")
  209. common.Must(err)
  210. matcher := &router.GeoIPMatcher{}
  211. common.Must(matcher.Init(ips))
  212. b.ResetTimer()
  213. for i := 0; i < b.N; i++ {
  214. _ = matcher.Match([]byte{8, 8, 8, 8})
  215. }
  216. }
  217. func BenchmarkGeoIPMatcher6US(b *testing.B) {
  218. ips, err := loadGeoIP("US")
  219. common.Must(err)
  220. matcher := &router.GeoIPMatcher{}
  221. common.Must(matcher.Init(ips))
  222. b.ResetTimer()
  223. for i := 0; i < b.N; i++ {
  224. _ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP())
  225. }
  226. }