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