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 }