router_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package conf_test
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. _ "unsafe"
  10. "github.com/xtls/xray-core/app/router"
  11. "github.com/xtls/xray-core/common"
  12. "github.com/xtls/xray-core/common/net"
  13. "github.com/xtls/xray-core/common/platform"
  14. "github.com/xtls/xray-core/common/platform/filesystem"
  15. "github.com/xtls/xray-core/common/serial"
  16. . "github.com/xtls/xray-core/infra/conf"
  17. "google.golang.org/protobuf/proto"
  18. )
  19. func getAssetPath(file string) (string, error) {
  20. path := platform.GetAssetLocation(file)
  21. _, err := os.Stat(path)
  22. if os.IsNotExist(err) {
  23. path := filepath.Join("..", "..", "resources", file)
  24. _, err := os.Stat(path)
  25. if os.IsNotExist(err) {
  26. return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
  27. }
  28. if err != nil {
  29. return "", fmt.Errorf("can't stat %s: %v", path, err)
  30. }
  31. return path, nil
  32. }
  33. if err != nil {
  34. return "", fmt.Errorf("can't stat %s: %v", path, err)
  35. }
  36. return path, nil
  37. }
  38. func TestToCidrList(t *testing.T) {
  39. tempDir, err := os.MkdirTemp("", "test-")
  40. if err != nil {
  41. t.Fatalf("can't create temp dir: %v", err)
  42. }
  43. defer os.RemoveAll(tempDir)
  44. geoipPath, err := getAssetPath("geoip.dat")
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. common.Must(filesystem.CopyFile(filepath.Join(tempDir, "geoip.dat"), geoipPath))
  49. common.Must(filesystem.CopyFile(filepath.Join(tempDir, "geoiptestrouter.dat"), geoipPath))
  50. os.Setenv("xray.location.asset", tempDir)
  51. defer os.Unsetenv("xray.location.asset")
  52. ips := StringList([]string{
  53. "geoip:us",
  54. "geoip:cn",
  55. "geoip:!cn",
  56. "ext:geoiptestrouter.dat:!cn",
  57. "ext:geoiptestrouter.dat:ca",
  58. "ext-ip:geoiptestrouter.dat:!cn",
  59. "ext-ip:geoiptestrouter.dat:!ca",
  60. })
  61. _, err = ToCidrList(ips)
  62. if err != nil {
  63. t.Fatalf("Failed to parse geoip list, got %s", err)
  64. }
  65. }
  66. func TestRouterConfig(t *testing.T) {
  67. createParser := func() func(string) (proto.Message, error) {
  68. return func(s string) (proto.Message, error) {
  69. config := new(RouterConfig)
  70. if err := json.Unmarshal([]byte(s), config); err != nil {
  71. return nil, err
  72. }
  73. return config.Build()
  74. }
  75. }
  76. runMultiTestCase(t, []TestCase{
  77. {
  78. Input: `{
  79. "domainStrategy": "AsIs",
  80. "rules": [
  81. {
  82. "domain": [
  83. "baidu.com",
  84. "qq.com"
  85. ],
  86. "outboundTag": "direct"
  87. },
  88. {
  89. "ip": [
  90. "10.0.0.0/8",
  91. "::1/128"
  92. ],
  93. "outboundTag": "test"
  94. },{
  95. "port": "53, 443, 1000-2000",
  96. "outboundTag": "test"
  97. },{
  98. "port": 123,
  99. "outboundTag": "test"
  100. }
  101. ],
  102. "balancers": [
  103. {
  104. "tag": "b1",
  105. "selector": ["test"],
  106. "fallbackTag": "fall"
  107. },
  108. {
  109. "tag": "b2",
  110. "selector": ["test"],
  111. "strategy": {
  112. "type": "leastload",
  113. "settings": {
  114. "healthCheck": {
  115. "interval": "5m0s",
  116. "sampling": 2,
  117. "timeout": "5s",
  118. "destination": "dest",
  119. "connectivity": "conn"
  120. },
  121. "costs": [
  122. {
  123. "regexp": true,
  124. "match": "\\d+(\\.\\d+)",
  125. "value": 5
  126. }
  127. ],
  128. "baselines": ["400ms", "600ms"],
  129. "expected": 6,
  130. "maxRTT": "1000ms",
  131. "tolerance": 0.5
  132. }
  133. },
  134. "fallbackTag": "fall"
  135. }
  136. ]
  137. }`,
  138. Parser: createParser(),
  139. Output: &router.Config{
  140. DomainStrategy: router.Config_AsIs,
  141. BalancingRule: []*router.BalancingRule{
  142. {
  143. Tag: "b1",
  144. OutboundSelector: []string{"test"},
  145. Strategy: "random",
  146. FallbackTag: "fall",
  147. },
  148. {
  149. Tag: "b2",
  150. OutboundSelector: []string{"test"},
  151. Strategy: "leastload",
  152. StrategySettings: serial.ToTypedMessage(&router.StrategyLeastLoadConfig{
  153. Costs: []*router.StrategyWeight{
  154. {
  155. Regexp: true,
  156. Match: "\\d+(\\.\\d+)",
  157. Value: 5,
  158. },
  159. },
  160. Baselines: []int64{
  161. int64(time.Duration(400) * time.Millisecond),
  162. int64(time.Duration(600) * time.Millisecond),
  163. },
  164. Expected: 6,
  165. MaxRTT: int64(time.Duration(1000) * time.Millisecond),
  166. Tolerance: 0.5,
  167. }),
  168. FallbackTag: "fall",
  169. },
  170. },
  171. Rule: []*router.RoutingRule{
  172. {
  173. Domain: []*router.Domain{
  174. {
  175. Type: router.Domain_Plain,
  176. Value: "baidu.com",
  177. },
  178. {
  179. Type: router.Domain_Plain,
  180. Value: "qq.com",
  181. },
  182. },
  183. TargetTag: &router.RoutingRule_Tag{
  184. Tag: "direct",
  185. },
  186. },
  187. {
  188. Geoip: []*router.GeoIP{
  189. {
  190. Cidr: []*router.CIDR{
  191. {
  192. Ip: []byte{10, 0, 0, 0},
  193. Prefix: 8,
  194. },
  195. {
  196. Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
  197. Prefix: 128,
  198. },
  199. },
  200. },
  201. },
  202. TargetTag: &router.RoutingRule_Tag{
  203. Tag: "test",
  204. },
  205. },
  206. {
  207. PortList: &net.PortList{
  208. Range: []*net.PortRange{
  209. {From: 53, To: 53},
  210. {From: 443, To: 443},
  211. {From: 1000, To: 2000},
  212. },
  213. },
  214. TargetTag: &router.RoutingRule_Tag{
  215. Tag: "test",
  216. },
  217. },
  218. {
  219. PortList: &net.PortList{
  220. Range: []*net.PortRange{
  221. {From: 123, To: 123},
  222. },
  223. },
  224. TargetTag: &router.RoutingRule_Tag{
  225. Tag: "test",
  226. },
  227. },
  228. },
  229. },
  230. },
  231. {
  232. Input: `{
  233. "domainStrategy": "IPIfNonMatch",
  234. "rules": [
  235. {
  236. "domain": [
  237. "baidu.com",
  238. "qq.com"
  239. ],
  240. "outboundTag": "direct"
  241. },
  242. {
  243. "ip": [
  244. "10.0.0.0/8",
  245. "::1/128"
  246. ],
  247. "outboundTag": "test"
  248. }
  249. ]
  250. }`,
  251. Parser: createParser(),
  252. Output: &router.Config{
  253. DomainStrategy: router.Config_IpIfNonMatch,
  254. Rule: []*router.RoutingRule{
  255. {
  256. Domain: []*router.Domain{
  257. {
  258. Type: router.Domain_Plain,
  259. Value: "baidu.com",
  260. },
  261. {
  262. Type: router.Domain_Plain,
  263. Value: "qq.com",
  264. },
  265. },
  266. TargetTag: &router.RoutingRule_Tag{
  267. Tag: "direct",
  268. },
  269. },
  270. {
  271. Geoip: []*router.GeoIP{
  272. {
  273. Cidr: []*router.CIDR{
  274. {
  275. Ip: []byte{10, 0, 0, 0},
  276. Prefix: 8,
  277. },
  278. {
  279. Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
  280. Prefix: 128,
  281. },
  282. },
  283. },
  284. },
  285. TargetTag: &router.RoutingRule_Tag{
  286. Tag: "test",
  287. },
  288. },
  289. },
  290. },
  291. },
  292. })
  293. }