dns_test.go 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. package dns_test
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/google/go-cmp/cmp"
  6. "github.com/miekg/dns"
  7. "github.com/xtls/xray-core/app/dispatcher"
  8. . "github.com/xtls/xray-core/app/dns"
  9. "github.com/xtls/xray-core/app/policy"
  10. "github.com/xtls/xray-core/app/proxyman"
  11. _ "github.com/xtls/xray-core/app/proxyman/outbound"
  12. "github.com/xtls/xray-core/app/router"
  13. "github.com/xtls/xray-core/common"
  14. "github.com/xtls/xray-core/common/errors"
  15. "github.com/xtls/xray-core/common/net"
  16. "github.com/xtls/xray-core/common/serial"
  17. "github.com/xtls/xray-core/core"
  18. feature_dns "github.com/xtls/xray-core/features/dns"
  19. "github.com/xtls/xray-core/proxy/freedom"
  20. "github.com/xtls/xray-core/testing/servers/udp"
  21. )
  22. type staticHandler struct{}
  23. func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
  24. ans := new(dns.Msg)
  25. ans.Id = r.Id
  26. var clientIP net.IP
  27. opt := r.IsEdns0()
  28. if opt != nil {
  29. for _, o := range opt.Option {
  30. if o.Option() == dns.EDNS0SUBNET {
  31. subnet := o.(*dns.EDNS0_SUBNET)
  32. clientIP = subnet.Address
  33. }
  34. }
  35. }
  36. for _, q := range r.Question {
  37. switch {
  38. case q.Name == "google.com." && q.Qtype == dns.TypeA:
  39. if clientIP == nil {
  40. rr, _ := dns.NewRR("google.com. IN A 8.8.8.8")
  41. ans.Answer = append(ans.Answer, rr)
  42. } else {
  43. rr, _ := dns.NewRR("google.com. IN A 8.8.4.4")
  44. ans.Answer = append(ans.Answer, rr)
  45. }
  46. case q.Name == "api.google.com." && q.Qtype == dns.TypeA:
  47. rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7")
  48. ans.Answer = append(ans.Answer, rr)
  49. case q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA:
  50. rr, _ := dns.NewRR("v2.api.google.com. IN A 8.8.7.8")
  51. ans.Answer = append(ans.Answer, rr)
  52. case q.Name == "facebook.com." && q.Qtype == dns.TypeA:
  53. rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
  54. ans.Answer = append(ans.Answer, rr)
  55. case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA:
  56. rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
  57. common.Must(err)
  58. ans.Answer = append(ans.Answer, rr)
  59. case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA:
  60. rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
  61. common.Must(err)
  62. ans.Answer = append(ans.Answer, rr)
  63. case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
  64. ans.MsgHdr.Rcode = dns.RcodeNameError
  65. case q.Name == "hostname." && q.Qtype == dns.TypeA:
  66. rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
  67. ans.Answer = append(ans.Answer, rr)
  68. case q.Name == "hostname.local." && q.Qtype == dns.TypeA:
  69. rr, _ := dns.NewRR("hostname.local. IN A 127.0.0.1")
  70. ans.Answer = append(ans.Answer, rr)
  71. case q.Name == "hostname.localdomain." && q.Qtype == dns.TypeA:
  72. rr, _ := dns.NewRR("hostname.localdomain. IN A 127.0.0.1")
  73. ans.Answer = append(ans.Answer, rr)
  74. case q.Name == "localhost." && q.Qtype == dns.TypeA:
  75. rr, _ := dns.NewRR("localhost. IN A 127.0.0.2")
  76. ans.Answer = append(ans.Answer, rr)
  77. case q.Name == "localhost-a." && q.Qtype == dns.TypeA:
  78. rr, _ := dns.NewRR("localhost-a. IN A 127.0.0.3")
  79. ans.Answer = append(ans.Answer, rr)
  80. case q.Name == "localhost-b." && q.Qtype == dns.TypeA:
  81. rr, _ := dns.NewRR("localhost-b. IN A 127.0.0.4")
  82. ans.Answer = append(ans.Answer, rr)
  83. case q.Name == "Mijia\\ Cloud." && q.Qtype == dns.TypeA:
  84. rr, _ := dns.NewRR("Mijia\\ Cloud. IN A 127.0.0.1")
  85. ans.Answer = append(ans.Answer, rr)
  86. }
  87. }
  88. w.WriteMsg(ans)
  89. }
  90. func TestUDPServerSubnet(t *testing.T) {
  91. port := udp.PickPort()
  92. dnsServer := dns.Server{
  93. Addr: "127.0.0.1:" + port.String(),
  94. Net: "udp",
  95. Handler: &staticHandler{},
  96. UDPSize: 1200,
  97. }
  98. go dnsServer.ListenAndServe()
  99. time.Sleep(time.Second)
  100. config := &core.Config{
  101. App: []*serial.TypedMessage{
  102. serial.ToTypedMessage(&Config{
  103. NameServer: []*NameServer{
  104. {
  105. Address: &net.Endpoint{
  106. Network: net.Network_UDP,
  107. Address: &net.IPOrDomain{
  108. Address: &net.IPOrDomain_Ip{
  109. Ip: []byte{127, 0, 0, 1},
  110. },
  111. },
  112. Port: uint32(port),
  113. },
  114. },
  115. },
  116. ClientIp: []byte{7, 8, 9, 10},
  117. }),
  118. serial.ToTypedMessage(&dispatcher.Config{}),
  119. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  120. serial.ToTypedMessage(&policy.Config{}),
  121. },
  122. Outbound: []*core.OutboundHandlerConfig{
  123. {
  124. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  125. },
  126. },
  127. }
  128. v, err := core.New(config)
  129. common.Must(err)
  130. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  131. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  132. IPv4Enable: true,
  133. IPv6Enable: true,
  134. FakeEnable: false,
  135. })
  136. if err != nil {
  137. t.Fatal("unexpected error: ", err)
  138. }
  139. if r := cmp.Diff(ips, []net.IP{{8, 8, 4, 4}}); r != "" {
  140. t.Fatal(r)
  141. }
  142. }
  143. func TestUDPServer(t *testing.T) {
  144. port := udp.PickPort()
  145. dnsServer := dns.Server{
  146. Addr: "127.0.0.1:" + port.String(),
  147. Net: "udp",
  148. Handler: &staticHandler{},
  149. UDPSize: 1200,
  150. }
  151. go dnsServer.ListenAndServe()
  152. time.Sleep(time.Second)
  153. config := &core.Config{
  154. App: []*serial.TypedMessage{
  155. serial.ToTypedMessage(&Config{
  156. NameServer: []*NameServer{
  157. {
  158. Address: &net.Endpoint{
  159. Network: net.Network_UDP,
  160. Address: &net.IPOrDomain{
  161. Address: &net.IPOrDomain_Ip{
  162. Ip: []byte{127, 0, 0, 1},
  163. },
  164. },
  165. Port: uint32(port),
  166. },
  167. },
  168. },
  169. }),
  170. serial.ToTypedMessage(&dispatcher.Config{}),
  171. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  172. serial.ToTypedMessage(&policy.Config{}),
  173. },
  174. Outbound: []*core.OutboundHandlerConfig{
  175. {
  176. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  177. },
  178. },
  179. }
  180. v, err := core.New(config)
  181. common.Must(err)
  182. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  183. {
  184. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  185. IPv4Enable: true,
  186. IPv6Enable: true,
  187. FakeEnable: false,
  188. })
  189. if err != nil {
  190. t.Fatal("unexpected error: ", err)
  191. }
  192. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  193. t.Fatal(r)
  194. }
  195. }
  196. {
  197. ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{
  198. IPv4Enable: true,
  199. IPv6Enable: true,
  200. FakeEnable: false,
  201. })
  202. if err != nil {
  203. t.Fatal("unexpected error: ", err)
  204. }
  205. if r := cmp.Diff(ips, []net.IP{{9, 9, 9, 9}}); r != "" {
  206. t.Fatal(r)
  207. }
  208. }
  209. {
  210. _, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
  211. IPv4Enable: true,
  212. IPv6Enable: true,
  213. FakeEnable: false,
  214. })
  215. if err == nil {
  216. t.Fatal("nil error")
  217. }
  218. if r := feature_dns.RCodeFromError(err); r != uint16(dns.RcodeNameError) {
  219. t.Fatal("expected NameError, but got ", r)
  220. }
  221. }
  222. {
  223. ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
  224. IPv4Enable: false,
  225. IPv6Enable: true,
  226. FakeEnable: false,
  227. })
  228. if !errors.AllEqual(feature_dns.ErrEmptyResponse, errors.Cause(err)) {
  229. t.Fatal("error: ", err)
  230. }
  231. if len(ips) != 0 {
  232. t.Fatal("ips: ", ips)
  233. }
  234. }
  235. dnsServer.Shutdown()
  236. {
  237. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  238. IPv4Enable: true,
  239. IPv6Enable: true,
  240. FakeEnable: false,
  241. })
  242. if err != nil {
  243. t.Fatal("unexpected error: ", err)
  244. }
  245. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  246. t.Fatal(r)
  247. }
  248. }
  249. }
  250. func TestPrioritizedDomain(t *testing.T) {
  251. port := udp.PickPort()
  252. dnsServer := dns.Server{
  253. Addr: "127.0.0.1:" + port.String(),
  254. Net: "udp",
  255. Handler: &staticHandler{},
  256. UDPSize: 1200,
  257. }
  258. go dnsServer.ListenAndServe()
  259. time.Sleep(time.Second)
  260. config := &core.Config{
  261. App: []*serial.TypedMessage{
  262. serial.ToTypedMessage(&Config{
  263. NameServer: []*NameServer{
  264. {
  265. Address: &net.Endpoint{
  266. Network: net.Network_UDP,
  267. Address: &net.IPOrDomain{
  268. Address: &net.IPOrDomain_Ip{
  269. Ip: []byte{127, 0, 0, 1},
  270. },
  271. },
  272. Port: 9999, /* unreachable */
  273. },
  274. },
  275. {
  276. Address: &net.Endpoint{
  277. Network: net.Network_UDP,
  278. Address: &net.IPOrDomain{
  279. Address: &net.IPOrDomain_Ip{
  280. Ip: []byte{127, 0, 0, 1},
  281. },
  282. },
  283. Port: uint32(port),
  284. },
  285. PrioritizedDomain: []*NameServer_PriorityDomain{
  286. {
  287. Type: DomainMatchingType_Full,
  288. Domain: "google.com",
  289. },
  290. },
  291. },
  292. },
  293. }),
  294. serial.ToTypedMessage(&dispatcher.Config{}),
  295. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  296. serial.ToTypedMessage(&policy.Config{}),
  297. },
  298. Outbound: []*core.OutboundHandlerConfig{
  299. {
  300. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  301. },
  302. },
  303. }
  304. v, err := core.New(config)
  305. common.Must(err)
  306. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  307. startTime := time.Now()
  308. {
  309. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  310. IPv4Enable: true,
  311. IPv6Enable: true,
  312. FakeEnable: false,
  313. })
  314. if err != nil {
  315. t.Fatal("unexpected error: ", err)
  316. }
  317. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  318. t.Fatal(r)
  319. }
  320. }
  321. endTime := time.Now()
  322. if startTime.After(endTime.Add(time.Second * 2)) {
  323. t.Error("DNS query doesn't finish in 2 seconds.")
  324. }
  325. }
  326. func TestUDPServerIPv6(t *testing.T) {
  327. port := udp.PickPort()
  328. dnsServer := dns.Server{
  329. Addr: "127.0.0.1:" + port.String(),
  330. Net: "udp",
  331. Handler: &staticHandler{},
  332. UDPSize: 1200,
  333. }
  334. go dnsServer.ListenAndServe()
  335. time.Sleep(time.Second)
  336. config := &core.Config{
  337. App: []*serial.TypedMessage{
  338. serial.ToTypedMessage(&Config{
  339. NameServer: []*NameServer{
  340. {
  341. Address: &net.Endpoint{
  342. Network: net.Network_UDP,
  343. Address: &net.IPOrDomain{
  344. Address: &net.IPOrDomain_Ip{
  345. Ip: []byte{127, 0, 0, 1},
  346. },
  347. },
  348. Port: uint32(port),
  349. },
  350. },
  351. },
  352. }),
  353. serial.ToTypedMessage(&dispatcher.Config{}),
  354. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  355. serial.ToTypedMessage(&policy.Config{}),
  356. },
  357. Outbound: []*core.OutboundHandlerConfig{
  358. {
  359. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  360. },
  361. },
  362. }
  363. v, err := core.New(config)
  364. common.Must(err)
  365. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  366. {
  367. ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
  368. IPv4Enable: false,
  369. IPv6Enable: true,
  370. FakeEnable: false,
  371. })
  372. if err != nil {
  373. t.Fatal("unexpected error: ", err)
  374. }
  375. if r := cmp.Diff(ips, []net.IP{{32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136}}); r != "" {
  376. t.Fatal(r)
  377. }
  378. }
  379. }
  380. func TestStaticHostDomain(t *testing.T) {
  381. port := udp.PickPort()
  382. dnsServer := dns.Server{
  383. Addr: "127.0.0.1:" + port.String(),
  384. Net: "udp",
  385. Handler: &staticHandler{},
  386. UDPSize: 1200,
  387. }
  388. go dnsServer.ListenAndServe()
  389. time.Sleep(time.Second)
  390. config := &core.Config{
  391. App: []*serial.TypedMessage{
  392. serial.ToTypedMessage(&Config{
  393. NameServer: []*NameServer{
  394. {
  395. Address: &net.Endpoint{
  396. Network: net.Network_UDP,
  397. Address: &net.IPOrDomain{
  398. Address: &net.IPOrDomain_Ip{
  399. Ip: []byte{127, 0, 0, 1},
  400. },
  401. },
  402. Port: uint32(port),
  403. },
  404. },
  405. },
  406. StaticHosts: []*Config_HostMapping{
  407. {
  408. Type: DomainMatchingType_Full,
  409. Domain: "example.com",
  410. ProxiedDomain: "google.com",
  411. },
  412. },
  413. }),
  414. serial.ToTypedMessage(&dispatcher.Config{}),
  415. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  416. serial.ToTypedMessage(&policy.Config{}),
  417. },
  418. Outbound: []*core.OutboundHandlerConfig{
  419. {
  420. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  421. },
  422. },
  423. }
  424. v, err := core.New(config)
  425. common.Must(err)
  426. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  427. {
  428. ips, err := client.LookupIP("example.com", feature_dns.IPOption{
  429. IPv4Enable: true,
  430. IPv6Enable: true,
  431. FakeEnable: false,
  432. })
  433. if err != nil {
  434. t.Fatal("unexpected error: ", err)
  435. }
  436. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  437. t.Fatal(r)
  438. }
  439. }
  440. dnsServer.Shutdown()
  441. }
  442. func TestIPMatch(t *testing.T) {
  443. port := udp.PickPort()
  444. dnsServer := dns.Server{
  445. Addr: "127.0.0.1:" + port.String(),
  446. Net: "udp",
  447. Handler: &staticHandler{},
  448. UDPSize: 1200,
  449. }
  450. go dnsServer.ListenAndServe()
  451. time.Sleep(time.Second)
  452. config := &core.Config{
  453. App: []*serial.TypedMessage{
  454. serial.ToTypedMessage(&Config{
  455. NameServer: []*NameServer{
  456. // private dns, not match
  457. {
  458. Address: &net.Endpoint{
  459. Network: net.Network_UDP,
  460. Address: &net.IPOrDomain{
  461. Address: &net.IPOrDomain_Ip{
  462. Ip: []byte{127, 0, 0, 1},
  463. },
  464. },
  465. Port: uint32(port),
  466. },
  467. Geoip: []*router.GeoIP{
  468. {
  469. CountryCode: "local",
  470. Cidr: []*router.CIDR{
  471. {
  472. // inner ip, will not match
  473. Ip: []byte{192, 168, 11, 1},
  474. Prefix: 32,
  475. },
  476. },
  477. },
  478. },
  479. },
  480. // second dns, match ip
  481. {
  482. Address: &net.Endpoint{
  483. Network: net.Network_UDP,
  484. Address: &net.IPOrDomain{
  485. Address: &net.IPOrDomain_Ip{
  486. Ip: []byte{127, 0, 0, 1},
  487. },
  488. },
  489. Port: uint32(port),
  490. },
  491. Geoip: []*router.GeoIP{
  492. {
  493. CountryCode: "test",
  494. Cidr: []*router.CIDR{
  495. {
  496. Ip: []byte{8, 8, 8, 8},
  497. Prefix: 32,
  498. },
  499. },
  500. },
  501. {
  502. CountryCode: "test",
  503. Cidr: []*router.CIDR{
  504. {
  505. Ip: []byte{8, 8, 8, 4},
  506. Prefix: 32,
  507. },
  508. },
  509. },
  510. },
  511. },
  512. },
  513. }),
  514. serial.ToTypedMessage(&dispatcher.Config{}),
  515. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  516. serial.ToTypedMessage(&policy.Config{}),
  517. },
  518. Outbound: []*core.OutboundHandlerConfig{
  519. {
  520. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  521. },
  522. },
  523. }
  524. v, err := core.New(config)
  525. common.Must(err)
  526. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  527. startTime := time.Now()
  528. {
  529. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  530. IPv4Enable: true,
  531. IPv6Enable: true,
  532. FakeEnable: false,
  533. })
  534. if err != nil {
  535. t.Fatal("unexpected error: ", err)
  536. }
  537. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  538. t.Fatal(r)
  539. }
  540. }
  541. endTime := time.Now()
  542. if startTime.After(endTime.Add(time.Second * 2)) {
  543. t.Error("DNS query doesn't finish in 2 seconds.")
  544. }
  545. }
  546. func TestLocalDomain(t *testing.T) {
  547. port := udp.PickPort()
  548. dnsServer := dns.Server{
  549. Addr: "127.0.0.1:" + port.String(),
  550. Net: "udp",
  551. Handler: &staticHandler{},
  552. UDPSize: 1200,
  553. }
  554. go dnsServer.ListenAndServe()
  555. time.Sleep(time.Second)
  556. config := &core.Config{
  557. App: []*serial.TypedMessage{
  558. serial.ToTypedMessage(&Config{
  559. NameServer: []*NameServer{
  560. {
  561. Address: &net.Endpoint{
  562. Network: net.Network_UDP,
  563. Address: &net.IPOrDomain{
  564. Address: &net.IPOrDomain_Ip{
  565. Ip: []byte{127, 0, 0, 1},
  566. },
  567. },
  568. Port: 9999, /* unreachable */
  569. },
  570. },
  571. {
  572. Address: &net.Endpoint{
  573. Network: net.Network_UDP,
  574. Address: &net.IPOrDomain{
  575. Address: &net.IPOrDomain_Ip{
  576. Ip: []byte{127, 0, 0, 1},
  577. },
  578. },
  579. Port: uint32(port),
  580. },
  581. PrioritizedDomain: []*NameServer_PriorityDomain{
  582. // Equivalent of dotless:localhost
  583. {Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
  584. },
  585. Geoip: []*router.GeoIP{
  586. { // Will match localhost, localhost-a and localhost-b,
  587. CountryCode: "local",
  588. Cidr: []*router.CIDR{
  589. {Ip: []byte{127, 0, 0, 2}, Prefix: 32},
  590. {Ip: []byte{127, 0, 0, 3}, Prefix: 32},
  591. {Ip: []byte{127, 0, 0, 4}, Prefix: 32},
  592. },
  593. },
  594. },
  595. },
  596. {
  597. Address: &net.Endpoint{
  598. Network: net.Network_UDP,
  599. Address: &net.IPOrDomain{
  600. Address: &net.IPOrDomain_Ip{
  601. Ip: []byte{127, 0, 0, 1},
  602. },
  603. },
  604. Port: uint32(port),
  605. },
  606. PrioritizedDomain: []*NameServer_PriorityDomain{
  607. // Equivalent of dotless: and domain:local
  608. {Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
  609. {Type: DomainMatchingType_Subdomain, Domain: "local"},
  610. {Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
  611. },
  612. },
  613. },
  614. StaticHosts: []*Config_HostMapping{
  615. {
  616. Type: DomainMatchingType_Full,
  617. Domain: "hostnamestatic",
  618. Ip: [][]byte{{127, 0, 0, 53}},
  619. },
  620. {
  621. Type: DomainMatchingType_Full,
  622. Domain: "hostnamealias",
  623. ProxiedDomain: "hostname.localdomain",
  624. },
  625. },
  626. }),
  627. serial.ToTypedMessage(&dispatcher.Config{}),
  628. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  629. serial.ToTypedMessage(&policy.Config{}),
  630. },
  631. Outbound: []*core.OutboundHandlerConfig{
  632. {
  633. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  634. },
  635. },
  636. }
  637. v, err := core.New(config)
  638. common.Must(err)
  639. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  640. startTime := time.Now()
  641. { // Will match dotless:
  642. ips, err := client.LookupIP("hostname", feature_dns.IPOption{
  643. IPv4Enable: true,
  644. IPv6Enable: true,
  645. FakeEnable: false,
  646. })
  647. if err != nil {
  648. t.Fatal("unexpected error: ", err)
  649. }
  650. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
  651. t.Fatal(r)
  652. }
  653. }
  654. { // Will match domain:local
  655. ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
  656. IPv4Enable: true,
  657. IPv6Enable: true,
  658. FakeEnable: false,
  659. })
  660. if err != nil {
  661. t.Fatal("unexpected error: ", err)
  662. }
  663. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
  664. t.Fatal(r)
  665. }
  666. }
  667. { // Will match static ip
  668. ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
  669. IPv4Enable: true,
  670. IPv6Enable: true,
  671. FakeEnable: false,
  672. })
  673. if err != nil {
  674. t.Fatal("unexpected error: ", err)
  675. }
  676. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 53}}); r != "" {
  677. t.Fatal(r)
  678. }
  679. }
  680. { // Will match domain replacing
  681. ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
  682. IPv4Enable: true,
  683. IPv6Enable: true,
  684. FakeEnable: false,
  685. })
  686. if err != nil {
  687. t.Fatal("unexpected error: ", err)
  688. }
  689. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
  690. t.Fatal(r)
  691. }
  692. }
  693. { // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
  694. ips, err := client.LookupIP("localhost", feature_dns.IPOption{
  695. IPv4Enable: true,
  696. IPv6Enable: true,
  697. FakeEnable: false,
  698. })
  699. if err != nil {
  700. t.Fatal("unexpected error: ", err)
  701. }
  702. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 2}}); r != "" {
  703. t.Fatal(r)
  704. }
  705. }
  706. { // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
  707. ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
  708. IPv4Enable: true,
  709. IPv6Enable: true,
  710. FakeEnable: false,
  711. })
  712. if err != nil {
  713. t.Fatal("unexpected error: ", err)
  714. }
  715. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 3}}); r != "" {
  716. t.Fatal(r)
  717. }
  718. }
  719. { // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
  720. ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
  721. IPv4Enable: true,
  722. IPv6Enable: true,
  723. FakeEnable: false,
  724. })
  725. if err != nil {
  726. t.Fatal("unexpected error: ", err)
  727. }
  728. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 4}}); r != "" {
  729. t.Fatal(r)
  730. }
  731. }
  732. { // Will match dotless:
  733. ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
  734. IPv4Enable: true,
  735. IPv6Enable: true,
  736. FakeEnable: false,
  737. })
  738. if err != nil {
  739. t.Fatal("unexpected error: ", err)
  740. }
  741. if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
  742. t.Fatal(r)
  743. }
  744. }
  745. endTime := time.Now()
  746. if startTime.After(endTime.Add(time.Second * 2)) {
  747. t.Error("DNS query doesn't finish in 2 seconds.")
  748. }
  749. }
  750. func TestMultiMatchPrioritizedDomain(t *testing.T) {
  751. port := udp.PickPort()
  752. dnsServer := dns.Server{
  753. Addr: "127.0.0.1:" + port.String(),
  754. Net: "udp",
  755. Handler: &staticHandler{},
  756. UDPSize: 1200,
  757. }
  758. go dnsServer.ListenAndServe()
  759. time.Sleep(time.Second)
  760. config := &core.Config{
  761. App: []*serial.TypedMessage{
  762. serial.ToTypedMessage(&Config{
  763. NameServer: []*NameServer{
  764. {
  765. Address: &net.Endpoint{
  766. Network: net.Network_UDP,
  767. Address: &net.IPOrDomain{
  768. Address: &net.IPOrDomain_Ip{
  769. Ip: []byte{127, 0, 0, 1},
  770. },
  771. },
  772. Port: 9999, /* unreachable */
  773. },
  774. },
  775. {
  776. Address: &net.Endpoint{
  777. Network: net.Network_UDP,
  778. Address: &net.IPOrDomain{
  779. Address: &net.IPOrDomain_Ip{
  780. Ip: []byte{127, 0, 0, 1},
  781. },
  782. },
  783. Port: uint32(port),
  784. },
  785. PrioritizedDomain: []*NameServer_PriorityDomain{
  786. {
  787. Type: DomainMatchingType_Subdomain,
  788. Domain: "google.com",
  789. },
  790. },
  791. Geoip: []*router.GeoIP{
  792. { // Will only match 8.8.8.8 and 8.8.4.4
  793. Cidr: []*router.CIDR{
  794. {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
  795. {Ip: []byte{8, 8, 4, 4}, Prefix: 32},
  796. },
  797. },
  798. },
  799. },
  800. {
  801. Address: &net.Endpoint{
  802. Network: net.Network_UDP,
  803. Address: &net.IPOrDomain{
  804. Address: &net.IPOrDomain_Ip{
  805. Ip: []byte{127, 0, 0, 1},
  806. },
  807. },
  808. Port: uint32(port),
  809. },
  810. PrioritizedDomain: []*NameServer_PriorityDomain{
  811. {
  812. Type: DomainMatchingType_Subdomain,
  813. Domain: "google.com",
  814. },
  815. },
  816. Geoip: []*router.GeoIP{
  817. { // Will match 8.8.8.8 and 8.8.8.7, etc
  818. Cidr: []*router.CIDR{
  819. {Ip: []byte{8, 8, 8, 7}, Prefix: 24},
  820. },
  821. },
  822. },
  823. },
  824. {
  825. Address: &net.Endpoint{
  826. Network: net.Network_UDP,
  827. Address: &net.IPOrDomain{
  828. Address: &net.IPOrDomain_Ip{
  829. Ip: []byte{127, 0, 0, 1},
  830. },
  831. },
  832. Port: uint32(port),
  833. },
  834. PrioritizedDomain: []*NameServer_PriorityDomain{
  835. {
  836. Type: DomainMatchingType_Subdomain,
  837. Domain: "api.google.com",
  838. },
  839. },
  840. Geoip: []*router.GeoIP{
  841. { // Will only match 8.8.7.7 (api.google.com)
  842. Cidr: []*router.CIDR{
  843. {Ip: []byte{8, 8, 7, 7}, Prefix: 32},
  844. },
  845. },
  846. },
  847. },
  848. {
  849. Address: &net.Endpoint{
  850. Network: net.Network_UDP,
  851. Address: &net.IPOrDomain{
  852. Address: &net.IPOrDomain_Ip{
  853. Ip: []byte{127, 0, 0, 1},
  854. },
  855. },
  856. Port: uint32(port),
  857. },
  858. PrioritizedDomain: []*NameServer_PriorityDomain{
  859. {
  860. Type: DomainMatchingType_Full,
  861. Domain: "v2.api.google.com",
  862. },
  863. },
  864. Geoip: []*router.GeoIP{
  865. { // Will only match 8.8.7.8 (v2.api.google.com)
  866. Cidr: []*router.CIDR{
  867. {Ip: []byte{8, 8, 7, 8}, Prefix: 32},
  868. },
  869. },
  870. },
  871. },
  872. },
  873. }),
  874. serial.ToTypedMessage(&dispatcher.Config{}),
  875. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  876. serial.ToTypedMessage(&policy.Config{}),
  877. },
  878. Outbound: []*core.OutboundHandlerConfig{
  879. {
  880. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  881. },
  882. },
  883. }
  884. v, err := core.New(config)
  885. common.Must(err)
  886. client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  887. startTime := time.Now()
  888. { // Will match server 1,2 and server 1 returns expected ip
  889. ips, err := client.LookupIP("google.com", feature_dns.IPOption{
  890. IPv4Enable: true,
  891. IPv6Enable: true,
  892. FakeEnable: false,
  893. })
  894. if err != nil {
  895. t.Fatal("unexpected error: ", err)
  896. }
  897. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  898. t.Fatal(r)
  899. }
  900. }
  901. { // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
  902. ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
  903. IPv4Enable: true,
  904. IPv6Enable: false,
  905. FakeEnable: false,
  906. })
  907. if err != nil {
  908. t.Fatal("unexpected error: ", err)
  909. }
  910. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 7}}); r != "" {
  911. t.Fatal(r)
  912. }
  913. }
  914. { // Will match server 3,1,2 and server 3 returns expected one
  915. ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{
  916. IPv4Enable: true,
  917. IPv6Enable: true,
  918. FakeEnable: false,
  919. })
  920. if err != nil {
  921. t.Fatal("unexpected error: ", err)
  922. }
  923. if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 7}}); r != "" {
  924. t.Fatal(r)
  925. }
  926. }
  927. { // Will match server 4,3,1,2 and server 4 returns expected one
  928. ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
  929. IPv4Enable: true,
  930. IPv6Enable: true,
  931. FakeEnable: false,
  932. })
  933. if err != nil {
  934. t.Fatal("unexpected error: ", err)
  935. }
  936. if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 8}}); r != "" {
  937. t.Fatal(r)
  938. }
  939. }
  940. endTime := time.Now()
  941. if startTime.After(endTime.Add(time.Second * 2)) {
  942. t.Error("DNS query doesn't finish in 2 seconds.")
  943. }
  944. }