dns_test.go 9.1 KB

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