1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-16 09:26:21 -05:00
v2fly/app/dns/dns_test.go

1005 lines
23 KiB
Go
Raw Normal View History

2017-12-19 17:55:09 -05:00
package dns_test
2017-11-14 18:36:14 -05:00
import (
"testing"
"time"
2017-11-14 18:36:14 -05:00
2019-01-06 17:30:38 -05:00
"github.com/google/go-cmp/cmp"
2019-02-06 04:21:04 -05:00
"github.com/miekg/dns"
2021-10-28 06:34:19 -04:00
"google.golang.org/protobuf/types/known/anypb"
2021-02-16 15:31:50 -05:00
core "github.com/v2fly/v2ray-core/v5"
"github.com/v2fly/v2ray-core/v5/app/dispatcher"
. "github.com/v2fly/v2ray-core/v5/app/dns"
"github.com/v2fly/v2ray-core/v5/app/policy"
"github.com/v2fly/v2ray-core/v5/app/proxyman"
_ "github.com/v2fly/v2ray-core/v5/app/proxyman/outbound"
"github.com/v2fly/v2ray-core/v5/app/router/routercommon"
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/common/serial"
"github.com/v2fly/v2ray-core/v5/common/strmatcher"
feature_dns "github.com/v2fly/v2ray-core/v5/features/dns"
"github.com/v2fly/v2ray-core/v5/proxy/freedom"
"github.com/v2fly/v2ray-core/v5/testing/servers/udp"
2017-11-14 18:36:14 -05:00
)
2021-05-19 17:28:52 -04:00
type staticHandler struct{}
2017-11-14 18:36:14 -05:00
func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
ans := new(dns.Msg)
ans.Id = r.Id
2018-11-19 08:13:20 -05:00
var clientIP net.IP
opt := r.IsEdns0()
if opt != nil {
for _, o := range opt.Option {
if o.Option() == dns.EDNS0SUBNET {
subnet := o.(*dns.EDNS0_SUBNET)
clientIP = subnet.Address
}
}
}
2017-11-14 18:36:14 -05:00
for _, q := range r.Question {
switch {
case q.Name == "google.com." && q.Qtype == dns.TypeA:
2018-11-19 08:13:20 -05:00
if clientIP == nil {
rr, _ := dns.NewRR("google.com. IN A 8.8.8.8")
ans.Answer = append(ans.Answer, rr)
} else {
rr, _ := dns.NewRR("google.com. IN A 8.8.4.4")
ans.Answer = append(ans.Answer, rr)
}
case q.Name == "api.google.com." && q.Qtype == dns.TypeA:
rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7")
ans.Answer = append(ans.Answer, rr)
case q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA:
rr, _ := dns.NewRR("v2.api.google.com. IN A 8.8.7.8")
ans.Answer = append(ans.Answer, rr)
case q.Name == "facebook.com." && q.Qtype == dns.TypeA:
2017-11-14 18:36:14 -05:00
rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
ans.Answer = append(ans.Answer, rr)
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA:
rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
common.Must(err)
ans.Answer = append(ans.Answer, rr)
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA:
rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
common.Must(err)
ans.Answer = append(ans.Answer, rr)
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
ans.MsgHdr.Rcode = dns.RcodeNameError
case q.Name == "hostname." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
ans.Answer = append(ans.Answer, rr)
case q.Name == "hostname.local." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("hostname.local. IN A 127.0.0.1")
ans.Answer = append(ans.Answer, rr)
case q.Name == "hostname.localdomain." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("hostname.localdomain. IN A 127.0.0.1")
ans.Answer = append(ans.Answer, rr)
case q.Name == "localhost." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("localhost. IN A 127.0.0.2")
ans.Answer = append(ans.Answer, rr)
case q.Name == "localhost-a." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("localhost-a. IN A 127.0.0.3")
ans.Answer = append(ans.Answer, rr)
case q.Name == "localhost-b." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("localhost-b. IN A 127.0.0.4")
ans.Answer = append(ans.Answer, rr)
case q.Name == "Mijia\\ Cloud." && q.Qtype == dns.TypeA:
2020-08-09 04:51:06 -04:00
rr, _ := dns.NewRR("Mijia\\ Cloud. IN A 127.0.0.1")
ans.Answer = append(ans.Answer, rr)
case q.Name == "xn--vi8h.ws." /* 🍕.ws */ && q.Qtype == dns.TypeA:
rr, err := dns.NewRR("xn--vi8h.ws. IN A 208.100.42.200")
common.Must(err)
ans.Answer = append(ans.Answer, rr)
case q.Name == "xn--l8jaaa.com." /* ああああ.com */ && q.Qtype == dns.TypeA:
rr, err := dns.NewRR("xn--l8jaaa.com. IN AAAA a:a:a:a::aaaa")
common.Must(err)
ans.Answer = append(ans.Answer, rr)
2017-11-14 18:36:14 -05:00
}
}
w.WriteMsg(ans)
}
2018-11-19 08:13:20 -05:00
func TestUDPServerSubnet(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
2018-11-19 08:13:20 -05:00
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
},
ClientIp: []byte{7, 8, 9, 10},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
2019-01-06 17:30:38 -05:00
common.Must(err)
2018-11-19 08:13:20 -05:00
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
ips, err := client.LookupIP("google.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
2018-11-19 08:13:20 -05:00
2019-01-06 17:30:38 -05:00
if r := cmp.Diff(ips, []net.IP{{8, 8, 4, 4}}); r != "" {
t.Fatal(r)
2018-09-10 17:43:17 -04:00
}
2019-01-06 17:30:38 -05:00
}
2017-11-14 18:36:14 -05:00
2019-01-06 17:30:38 -05:00
func TestUDPServer(t *testing.T) {
2017-11-14 18:36:14 -05:00
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
2017-11-14 18:36:14 -05:00
}
go dnsServer.ListenAndServe()
2018-09-10 16:29:35 -04:00
time.Sleep(time.Second)
2017-11-14 18:36:14 -05:00
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
2017-11-14 18:36:14 -05:00
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
2018-01-12 18:07:37 -05:00
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
2017-11-14 18:36:14 -05:00
},
},
}
v, err := core.New(config)
2019-01-06 17:30:38 -05:00
common.Must(err)
2017-11-14 18:36:14 -05:00
2018-10-21 04:27:13 -04:00
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
2017-11-14 18:36:14 -05:00
2019-01-06 17:30:38 -05:00
{
ips, err := client.LookupIP("google.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
2017-11-14 18:36:14 -05:00
2019-01-06 17:30:38 -05:00
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
{
ips, err := client.LookupIP("facebook.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{9, 9, 9, 9}}); r != "" {
t.Fatal(r)
}
}
2017-11-14 18:36:14 -05:00
{
_, err := client.LookupIP("notexist.google.com")
if err == nil {
t.Fatal("nil error")
}
if r := feature_dns.RCodeFromError(err); r != uint16(dns.RcodeNameError) {
t.Fatal("expected NameError, but got ", r)
}
}
{
clientv6 := client.(feature_dns.IPv6Lookup)
ips, err := clientv6.LookupIPv6("ipv4only.google.com")
if err != feature_dns.ErrEmptyResponse {
t.Fatal("error: ", err)
}
if len(ips) != 0 {
t.Fatal("ips: ", ips)
}
}
{
ips, err := client.LookupIP(common.Must2(strmatcher.ToDomain("🍕.ws")).(string))
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{208, 100, 42, 200}}); r != "" {
t.Fatal(r)
}
}
{
ips, err := client.LookupIP(common.Must2(strmatcher.ToDomain("ああああ.com")).(string))
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{0, 0xa, 0, 0xa, 0, 0xa, 0, 0xa, 0, 0, 0, 0, 0, 0, 0xaa, 0xaa}}); r != "" {
t.Fatal(r)
}
}
2017-11-14 18:36:14 -05:00
dnsServer.Shutdown()
2019-01-06 17:30:38 -05:00
{
ips, err := client.LookupIP("google.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
2019-01-06 17:30:38 -05:00
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
2018-09-10 17:43:17 -04:00
}
2019-01-06 17:30:38 -05:00
}
2019-01-06 17:30:38 -05:00
func TestPrioritizedDomain(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
2018-09-10 16:29:35 -04:00
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Full,
Domain: "google.com",
},
},
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
2019-01-06 17:30:38 -05:00
common.Must(err)
2018-10-21 04:27:13 -04:00
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
startTime := time.Now()
2019-01-06 17:30:38 -05:00
{
ips, err := client.LookupIP("google.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.")
}
}
func TestUDPServerIPv6(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
2019-01-06 17:30:38 -05:00
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
client6 := client.(feature_dns.IPv6Lookup)
2019-01-06 17:30:38 -05:00
{
ips, err := client6.LookupIPv6("ipv6.google.com")
2019-01-06 17:30:38 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136}}); r != "" {
t.Fatal(r)
}
}
}
func TestStaticHostDomain(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
},
2021-09-07 08:43:28 -04:00
StaticHosts: []*HostMapping{
{
Type: DomainMatchingType_Full,
Domain: "example.com",
ProxiedDomain: "google.com",
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{
ips, err := client.LookupIP("example.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
dnsServer.Shutdown()
}
2019-11-18 10:46:56 -05:00
func TestIPMatch(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
2019-11-18 10:46:56 -05:00
serial.ToTypedMessage(&Config{
NameServer: []*NameServer{
// private dns, not match
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
2019-11-18 10:46:56 -05:00
{
CountryCode: "local",
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
2019-11-18 10:46:56 -05:00
{
// inner ip, will not match
Ip: []byte{192, 168, 11, 1},
Prefix: 32,
},
},
},
},
},
// second dns, match ip
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
2019-11-18 10:46:56 -05:00
{
CountryCode: "test",
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
2019-11-18 10:46:56 -05:00
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
},
},
{
CountryCode: "test",
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
2019-11-18 10:46:56 -05:00
{
Ip: []byte{8, 8, 8, 4},
Prefix: 32,
},
},
},
},
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
startTime := time.Now()
{
ips, err := client.LookupIP("google.com")
2019-11-18 10:46:56 -05:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.")
}
}
2020-08-09 04:51:06 -04:00
func TestLocalDomain(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
2020-08-09 04:51:06 -04:00
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
// Equivalent of dotless:localhost
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
2020-08-09 04:51:06 -04:00
{ // Will match localhost, localhost-a and localhost-b,
CountryCode: "local",
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
2020-08-09 04:51:06 -04:00
{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
{Ip: []byte{127, 0, 0, 4}, Prefix: 32},
},
},
},
},
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
// Equivalent of dotless: and domain:local
{Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
{Type: DomainMatchingType_Subdomain, Domain: "local"},
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
},
},
},
2021-09-07 08:43:28 -04:00
StaticHosts: []*HostMapping{
2020-08-09 04:51:06 -04:00
{
Type: DomainMatchingType_Full,
Domain: "hostnamestatic",
Ip: [][]byte{{127, 0, 0, 53}},
},
{
Type: DomainMatchingType_Full,
Domain: "hostnamealias",
ProxiedDomain: "hostname.localdomain",
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
startTime := time.Now()
{ // Will match dotless:
ips, err := client.LookupIP("hostname")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
t.Fatal(r)
}
}
{ // Will match domain:local
ips, err := client.LookupIP("hostname.local")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
t.Fatal(r)
}
}
{ // Will match static ip
ips, err := client.LookupIP("hostnamestatic")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 53}}); r != "" {
t.Fatal(r)
}
}
{ // Will match domain replacing
ips, err := client.LookupIP("hostnamealias")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
t.Fatal(r)
}
}
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
ips, err := client.LookupIP("localhost")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 2}}); r != "" {
t.Fatal(r)
}
}
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-a")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 3}}); r != "" {
t.Fatal(r)
}
}
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-b")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 4}}); r != "" {
t.Fatal(r)
}
}
{ // Will match dotless:
ips, err := client.LookupIP("Mijia Cloud")
2020-08-09 04:51:06 -04:00
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.")
}
}
func TestMultiMatchPrioritizedDomain(t *testing.T) {
port := udp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "udp",
Handler: &staticHandler{},
UDPSize: 1200,
}
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
config := &core.Config{
2021-06-19 09:36:54 -04:00
App: []*anypb.Any{
serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Subdomain,
Domain: "google.com",
},
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
{ // Will only match 8.8.8.8 and 8.8.4.4
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
{Ip: []byte{8, 8, 4, 4}, Prefix: 32},
},
},
},
},
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Subdomain,
Domain: "google.com",
},
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
{ // Will match 8.8.8.8 and 8.8.8.7, etc
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
},
},
},
},
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Subdomain,
Domain: "api.google.com",
},
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
{ // Will only match 8.8.7.7 (api.google.com)
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
},
},
},
},
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Full,
Domain: "v2.api.google.com",
},
},
2021-09-07 08:43:28 -04:00
Geoip: []*routercommon.GeoIP{
{ // Will only match 8.8.7.8 (v2.api.google.com)
2021-09-07 08:43:28 -04:00
Cidr: []*routercommon.CIDR{
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
},
},
},
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
v, err := core.New(config)
common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
startTime := time.Now()
{ // Will match server 1,2 and server 1 returns expected ip
ips, err := client.LookupIP("google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
t.Fatal(r)
}
}
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
clientv4 := client.(feature_dns.IPv4Lookup)
ips, err := clientv4.LookupIPv4("ipv6.google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 7}}); r != "" {
t.Fatal(r)
}
}
{ // Will match server 3,1,2 and server 3 returns expected one
ips, err := client.LookupIP("api.google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 7}}); r != "" {
t.Fatal(r)
}
}
{ // Will match server 4,3,1,2 and server 4 returns expected one
ips, err := client.LookupIP("v2.api.google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 8}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.")
}
}