dns_test.go 9.2 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. 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. NameServer: []*dnsapp.NameServer{
  80. {
  81. Address: &net.Endpoint{
  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. }),
  93. serial.ToTypedMessage(&dispatcher.Config{}),
  94. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  95. serial.ToTypedMessage(&proxyman.InboundConfig{}),
  96. serial.ToTypedMessage(&policy.Config{}),
  97. },
  98. Inbound: []*core.InboundHandlerConfig{
  99. {
  100. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  101. Address: net.NewIPOrDomain(net.LocalHostIP),
  102. Port: uint32(port),
  103. Networks: []net.Network{net.Network_UDP},
  104. }),
  105. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  106. PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
  107. Listen: net.NewIPOrDomain(net.LocalHostIP),
  108. }),
  109. },
  110. },
  111. Outbound: []*core.OutboundHandlerConfig{
  112. {
  113. ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{}),
  114. },
  115. },
  116. }
  117. v, err := core.New(config)
  118. common.Must(err)
  119. common.Must(v.Start())
  120. defer v.Close()
  121. {
  122. m1 := new(dns.Msg)
  123. m1.Id = dns.Id()
  124. m1.RecursionDesired = true
  125. m1.Question = make([]dns.Question, 1)
  126. m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
  127. c := new(dns.Client)
  128. in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
  129. common.Must(err)
  130. if len(in.Answer) != 1 {
  131. t.Fatal("len(answer): ", len(in.Answer))
  132. }
  133. rr, ok := in.Answer[0].(*dns.A)
  134. if !ok {
  135. t.Fatal("not A record")
  136. }
  137. if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
  138. t.Error(r)
  139. }
  140. }
  141. {
  142. m1 := new(dns.Msg)
  143. m1.Id = dns.Id()
  144. m1.RecursionDesired = true
  145. m1.Question = make([]dns.Question, 1)
  146. m1.Question[0] = dns.Question{Name: "ipv4only.google.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET}
  147. c := new(dns.Client)
  148. c.Timeout = 10 * time.Second
  149. in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
  150. common.Must(err)
  151. if len(in.Answer) != 0 {
  152. t.Fatal("len(answer): ", len(in.Answer))
  153. }
  154. }
  155. {
  156. m1 := new(dns.Msg)
  157. m1.Id = dns.Id()
  158. m1.RecursionDesired = true
  159. m1.Question = make([]dns.Question, 1)
  160. m1.Question[0] = dns.Question{Name: "notexist.google.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET}
  161. c := new(dns.Client)
  162. in, _, err := c.Exchange(m1, "127.0.0.1:"+strconv.Itoa(int(serverPort)))
  163. common.Must(err)
  164. if in.Rcode != dns.RcodeNameError {
  165. t.Error("expected NameError, but got ", in.Rcode)
  166. }
  167. }
  168. }
  169. func TestTCPDNSTunnel(t *testing.T) {
  170. port := udp.PickPort()
  171. dnsServer := dns.Server{
  172. Addr: "127.0.0.1:" + port.String(),
  173. Net: "udp",
  174. Handler: &staticHandler{},
  175. }
  176. defer dnsServer.Shutdown()
  177. go dnsServer.ListenAndServe()
  178. time.Sleep(time.Second)
  179. serverPort := tcp.PickPort()
  180. config := &core.Config{
  181. App: []*serial.TypedMessage{
  182. serial.ToTypedMessage(&dnsapp.Config{
  183. NameServer: []*dnsapp.NameServer{
  184. {
  185. Address: &net.Endpoint{
  186. Network: net.Network_UDP,
  187. Address: &net.IPOrDomain{
  188. Address: &net.IPOrDomain_Ip{
  189. Ip: []byte{127, 0, 0, 1},
  190. },
  191. },
  192. Port: uint32(port),
  193. },
  194. },
  195. },
  196. }),
  197. serial.ToTypedMessage(&dispatcher.Config{}),
  198. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  199. serial.ToTypedMessage(&proxyman.InboundConfig{}),
  200. serial.ToTypedMessage(&policy.Config{}),
  201. },
  202. Inbound: []*core.InboundHandlerConfig{
  203. {
  204. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  205. Address: net.NewIPOrDomain(net.LocalHostIP),
  206. Port: uint32(port),
  207. Networks: []net.Network{net.Network_TCP},
  208. }),
  209. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  210. PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
  211. Listen: net.NewIPOrDomain(net.LocalHostIP),
  212. }),
  213. },
  214. },
  215. Outbound: []*core.OutboundHandlerConfig{
  216. {
  217. ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{}),
  218. },
  219. },
  220. }
  221. v, err := core.New(config)
  222. common.Must(err)
  223. common.Must(v.Start())
  224. defer v.Close()
  225. m1 := new(dns.Msg)
  226. m1.Id = dns.Id()
  227. m1.RecursionDesired = true
  228. m1.Question = make([]dns.Question, 1)
  229. m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
  230. c := &dns.Client{
  231. Net: "tcp",
  232. }
  233. in, _, err := c.Exchange(m1, "127.0.0.1:"+serverPort.String())
  234. common.Must(err)
  235. if len(in.Answer) != 1 {
  236. t.Fatal("len(answer): ", len(in.Answer))
  237. }
  238. rr, ok := in.Answer[0].(*dns.A)
  239. if !ok {
  240. t.Fatal("not A record")
  241. }
  242. if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
  243. t.Error(r)
  244. }
  245. }
  246. func TestUDP2TCPDNSTunnel(t *testing.T) {
  247. port := tcp.PickPort()
  248. dnsServer := dns.Server{
  249. Addr: "127.0.0.1:" + port.String(),
  250. Net: "tcp",
  251. Handler: &staticHandler{},
  252. }
  253. defer dnsServer.Shutdown()
  254. go dnsServer.ListenAndServe()
  255. time.Sleep(time.Second)
  256. serverPort := tcp.PickPort()
  257. config := &core.Config{
  258. App: []*serial.TypedMessage{
  259. serial.ToTypedMessage(&dnsapp.Config{
  260. NameServer: []*dnsapp.NameServer{
  261. {
  262. Address: &net.Endpoint{
  263. Network: net.Network_UDP,
  264. Address: &net.IPOrDomain{
  265. Address: &net.IPOrDomain_Ip{
  266. Ip: []byte{127, 0, 0, 1},
  267. },
  268. },
  269. Port: uint32(port),
  270. },
  271. },
  272. },
  273. }),
  274. serial.ToTypedMessage(&dispatcher.Config{}),
  275. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  276. serial.ToTypedMessage(&proxyman.InboundConfig{}),
  277. serial.ToTypedMessage(&policy.Config{}),
  278. },
  279. Inbound: []*core.InboundHandlerConfig{
  280. {
  281. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  282. Address: net.NewIPOrDomain(net.LocalHostIP),
  283. Port: uint32(port),
  284. Networks: []net.Network{net.Network_TCP},
  285. }),
  286. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  287. PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
  288. Listen: net.NewIPOrDomain(net.LocalHostIP),
  289. }),
  290. },
  291. },
  292. Outbound: []*core.OutboundHandlerConfig{
  293. {
  294. ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{
  295. Server: &net.Endpoint{
  296. Network: net.Network_TCP,
  297. },
  298. }),
  299. },
  300. },
  301. }
  302. v, err := core.New(config)
  303. common.Must(err)
  304. common.Must(v.Start())
  305. defer v.Close()
  306. m1 := new(dns.Msg)
  307. m1.Id = dns.Id()
  308. m1.RecursionDesired = true
  309. m1.Question = make([]dns.Question, 1)
  310. m1.Question[0] = dns.Question{Name: "google.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET}
  311. c := &dns.Client{
  312. Net: "tcp",
  313. }
  314. in, _, err := c.Exchange(m1, "127.0.0.1:"+serverPort.String())
  315. common.Must(err)
  316. if len(in.Answer) != 1 {
  317. t.Fatal("len(answer): ", len(in.Answer))
  318. }
  319. rr, ok := in.Answer[0].(*dns.A)
  320. if !ok {
  321. t.Fatal("not A record")
  322. }
  323. if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
  324. t.Error(r)
  325. }
  326. }