dns_test.go 9.0 KB

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