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