github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/proxy/dns/dns_test.go (about)

     1  package dns_test
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/miekg/dns"
    10  
    11  	"v2ray.com/core"
    12  	"v2ray.com/core/app/dispatcher"
    13  	dnsapp "v2ray.com/core/app/dns"
    14  	"v2ray.com/core/app/policy"
    15  	"v2ray.com/core/app/proxyman"
    16  	_ "v2ray.com/core/app/proxyman/inbound"
    17  	_ "v2ray.com/core/app/proxyman/outbound"
    18  	"v2ray.com/core/common"
    19  	"v2ray.com/core/common/net"
    20  	"v2ray.com/core/common/serial"
    21  	dns_proxy "v2ray.com/core/proxy/dns"
    22  	"v2ray.com/core/proxy/dokodemo"
    23  	"v2ray.com/core/testing/servers/tcp"
    24  	"v2ray.com/core/testing/servers/udp"
    25  )
    26  
    27  type staticHandler struct {
    28  }
    29  
    30  func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
    31  	ans := new(dns.Msg)
    32  	ans.Id = r.Id
    33  
    34  	var clientIP net.IP
    35  
    36  	opt := r.IsEdns0()
    37  	if opt != nil {
    38  		for _, o := range opt.Option {
    39  			if o.Option() == dns.EDNS0SUBNET {
    40  				subnet := o.(*dns.EDNS0_SUBNET)
    41  				clientIP = subnet.Address
    42  			}
    43  		}
    44  	}
    45  
    46  	for _, q := range r.Question {
    47  		if 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  		} else if q.Name == "facebook.com." && q.Qtype == dns.TypeA {
    56  			rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
    57  			ans.Answer = append(ans.Answer, rr)
    58  		} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA {
    59  			rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
    60  			common.Must(err)
    61  			ans.Answer = append(ans.Answer, rr)
    62  		} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA {
    63  			rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
    64  			common.Must(err)
    65  			ans.Answer = append(ans.Answer, rr)
    66  		} else if q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA {
    67  			ans.MsgHdr.Rcode = dns.RcodeNameError
    68  		}
    69  	}
    70  	w.WriteMsg(ans)
    71  }
    72  
    73  func TestUDPDNSTunnel(t *testing.T) {
    74  	port := udp.PickPort()
    75  
    76  	dnsServer := dns.Server{
    77  		Addr:    "127.0.0.1:" + port.String(),
    78  		Net:     "udp",
    79  		Handler: &staticHandler{},
    80  		UDPSize: 1200,
    81  	}
    82  	defer dnsServer.Shutdown()
    83  
    84  	go dnsServer.ListenAndServe()
    85  	time.Sleep(time.Second)
    86  
    87  	serverPort := udp.PickPort()
    88  	config := &core.Config{
    89  		App: []*serial.TypedMessage{
    90  			serial.ToTypedMessage(&dnsapp.Config{
    91  				NameServers: []*net.Endpoint{
    92  					{
    93  						Network: net.Network_UDP,
    94  						Address: &net.IPOrDomain{
    95  							Address: &net.IPOrDomain_Ip{
    96  								Ip: []byte{127, 0, 0, 1},
    97  							},
    98  						},
    99  						Port: uint32(port),
   100  					},
   101  				},
   102  			}),
   103  			serial.ToTypedMessage(&dispatcher.Config{}),
   104  			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
   105  			serial.ToTypedMessage(&proxyman.InboundConfig{}),
   106  			serial.ToTypedMessage(&policy.Config{}),
   107  		},
   108  		Inbound: []*core.InboundHandlerConfig{
   109  			{
   110  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   111  					Address:  net.NewIPOrDomain(net.LocalHostIP),
   112  					Port:     uint32(port),
   113  					Networks: []net.Network{net.Network_UDP},
   114  				}),
   115  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   116  					PortRange: net.SinglePortRange(serverPort),
   117  					Listen:    net.NewIPOrDomain(net.LocalHostIP),
   118  				}),
   119  			},
   120  		},
   121  		Outbound: []*core.OutboundHandlerConfig{
   122  			{
   123  				ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{}),
   124  			},
   125  		},
   126  	}
   127  
   128  	v, err := core.New(config)
   129  	common.Must(err)
   130  	common.Must(v.Start())
   131  	defer v.Close()
   132  
   133  	{
   134  		m1 := new(dns.Msg)
   135  		m1.Id = dns.Id()
   136  		m1.RecursionDesired = true
   137  		m1.Question = make([]dns.Question, 1)
   138  		m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
   139  
   140  		c := new(dns.Client)
   141  		in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
   142  		common.Must(err)
   143  
   144  		if len(in.Answer) != 1 {
   145  			t.Fatal("len(answer): ", len(in.Answer))
   146  		}
   147  
   148  		rr, ok := in.Answer[0].(*dns.A)
   149  		if !ok {
   150  			t.Fatal("not A record")
   151  		}
   152  		if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
   153  			t.Error(r)
   154  		}
   155  	}
   156  
   157  	{
   158  		m1 := new(dns.Msg)
   159  		m1.Id = dns.Id()
   160  		m1.RecursionDesired = true
   161  		m1.Question = make([]dns.Question, 1)
   162  		m1.Question[0] = dns.Question{Name: "ipv4only.google.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET}
   163  
   164  		c := new(dns.Client)
   165  		c.Timeout = 10 * time.Second
   166  		in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
   167  		common.Must(err)
   168  
   169  		if len(in.Answer) != 0 {
   170  			t.Fatal("len(answer): ", len(in.Answer))
   171  		}
   172  	}
   173  
   174  	{
   175  		m1 := new(dns.Msg)
   176  		m1.Id = dns.Id()
   177  		m1.RecursionDesired = true
   178  		m1.Question = make([]dns.Question, 1)
   179  		m1.Question[0] = dns.Question{Name: "notexist.google.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET}
   180  
   181  		c := new(dns.Client)
   182  		in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
   183  		common.Must(err)
   184  
   185  		if in.Rcode != dns.RcodeNameError {
   186  			t.Error("expected NameError, but got ", in.Rcode)
   187  		}
   188  	}
   189  }
   190  
   191  func TestTCPDNSTunnel(t *testing.T) {
   192  	port := udp.PickPort()
   193  
   194  	dnsServer := dns.Server{
   195  		Addr:    "127.0.0.1:" + port.String(),
   196  		Net:     "udp",
   197  		Handler: &staticHandler{},
   198  	}
   199  	defer dnsServer.Shutdown()
   200  
   201  	go dnsServer.ListenAndServe()
   202  	time.Sleep(time.Second)
   203  
   204  	serverPort := tcp.PickPort()
   205  	config := &core.Config{
   206  		App: []*serial.TypedMessage{
   207  			serial.ToTypedMessage(&dnsapp.Config{
   208  				NameServer: []*dnsapp.NameServer{
   209  					{
   210  						Address: &net.Endpoint{
   211  							Network: net.Network_UDP,
   212  							Address: &net.IPOrDomain{
   213  								Address: &net.IPOrDomain_Ip{
   214  									Ip: []byte{127, 0, 0, 1},
   215  								},
   216  							},
   217  							Port: uint32(port),
   218  						},
   219  					},
   220  				},
   221  			}),
   222  			serial.ToTypedMessage(&dispatcher.Config{}),
   223  			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
   224  			serial.ToTypedMessage(&proxyman.InboundConfig{}),
   225  			serial.ToTypedMessage(&policy.Config{}),
   226  		},
   227  		Inbound: []*core.InboundHandlerConfig{
   228  			{
   229  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   230  					Address:  net.NewIPOrDomain(net.LocalHostIP),
   231  					Port:     uint32(port),
   232  					Networks: []net.Network{net.Network_TCP},
   233  				}),
   234  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   235  					PortRange: net.SinglePortRange(serverPort),
   236  					Listen:    net.NewIPOrDomain(net.LocalHostIP),
   237  				}),
   238  			},
   239  		},
   240  		Outbound: []*core.OutboundHandlerConfig{
   241  			{
   242  				ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{}),
   243  			},
   244  		},
   245  	}
   246  
   247  	v, err := core.New(config)
   248  	common.Must(err)
   249  	common.Must(v.Start())
   250  	defer v.Close()
   251  
   252  	m1 := new(dns.Msg)
   253  	m1.Id = dns.Id()
   254  	m1.RecursionDesired = true
   255  	m1.Question = make([]dns.Question, 1)
   256  	m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
   257  
   258  	c := &dns.Client{
   259  		Net: "tcp",
   260  	}
   261  	in, _, err := c.Exchange(m1, "127.0.0.1:"+serverPort.String())
   262  	common.Must(err)
   263  
   264  	if len(in.Answer) != 1 {
   265  		t.Fatal("len(answer): ", len(in.Answer))
   266  	}
   267  
   268  	rr, ok := in.Answer[0].(*dns.A)
   269  	if !ok {
   270  		t.Fatal("not A record")
   271  	}
   272  	if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
   273  		t.Error(r)
   274  	}
   275  }
   276  
   277  func TestUDP2TCPDNSTunnel(t *testing.T) {
   278  	port := tcp.PickPort()
   279  
   280  	dnsServer := dns.Server{
   281  		Addr:    "127.0.0.1:" + port.String(),
   282  		Net:     "tcp",
   283  		Handler: &staticHandler{},
   284  	}
   285  	defer dnsServer.Shutdown()
   286  
   287  	go dnsServer.ListenAndServe()
   288  	time.Sleep(time.Second)
   289  
   290  	serverPort := tcp.PickPort()
   291  	config := &core.Config{
   292  		App: []*serial.TypedMessage{
   293  			serial.ToTypedMessage(&dnsapp.Config{
   294  				NameServer: []*dnsapp.NameServer{
   295  					{
   296  						Address: &net.Endpoint{
   297  							Network: net.Network_UDP,
   298  							Address: &net.IPOrDomain{
   299  								Address: &net.IPOrDomain_Ip{
   300  									Ip: []byte{127, 0, 0, 1},
   301  								},
   302  							},
   303  							Port: uint32(port),
   304  						},
   305  					},
   306  				},
   307  			}),
   308  			serial.ToTypedMessage(&dispatcher.Config{}),
   309  			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
   310  			serial.ToTypedMessage(&proxyman.InboundConfig{}),
   311  			serial.ToTypedMessage(&policy.Config{}),
   312  		},
   313  		Inbound: []*core.InboundHandlerConfig{
   314  			{
   315  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   316  					Address:  net.NewIPOrDomain(net.LocalHostIP),
   317  					Port:     uint32(port),
   318  					Networks: []net.Network{net.Network_TCP},
   319  				}),
   320  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   321  					PortRange: net.SinglePortRange(serverPort),
   322  					Listen:    net.NewIPOrDomain(net.LocalHostIP),
   323  				}),
   324  			},
   325  		},
   326  		Outbound: []*core.OutboundHandlerConfig{
   327  			{
   328  				ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{
   329  					Server: &net.Endpoint{
   330  						Network: net.Network_TCP,
   331  					},
   332  				}),
   333  			},
   334  		},
   335  	}
   336  
   337  	v, err := core.New(config)
   338  	common.Must(err)
   339  	common.Must(v.Start())
   340  	defer v.Close()
   341  
   342  	m1 := new(dns.Msg)
   343  	m1.Id = dns.Id()
   344  	m1.RecursionDesired = true
   345  	m1.Question = make([]dns.Question, 1)
   346  	m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
   347  
   348  	c := &dns.Client{
   349  		Net: "tcp",
   350  	}
   351  	in, _, err := c.Exchange(m1, "127.0.0.1:"+serverPort.String())
   352  	common.Must(err)
   353  
   354  	if len(in.Answer) != 1 {
   355  		t.Fatal("len(answer): ", len(in.Answer))
   356  	}
   357  
   358  	rr, ok := in.Answer[0].(*dns.A)
   359  	if !ok {
   360  		t.Fatal("not A record")
   361  	}
   362  	if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
   363  		t.Error(r)
   364  	}
   365  }