fakedns_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package dns_test
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/google/go-cmp/cmp"
  6. "github.com/miekg/dns"
  7. "google.golang.org/protobuf/types/known/anypb"
  8. core "github.com/v2fly/v2ray-core/v5"
  9. "github.com/v2fly/v2ray-core/v5/app/dispatcher"
  10. . "github.com/v2fly/v2ray-core/v5/app/dns"
  11. "github.com/v2fly/v2ray-core/v5/app/dns/fakedns"
  12. "github.com/v2fly/v2ray-core/v5/app/policy"
  13. "github.com/v2fly/v2ray-core/v5/app/proxyman"
  14. "github.com/v2fly/v2ray-core/v5/common"
  15. "github.com/v2fly/v2ray-core/v5/common/net"
  16. "github.com/v2fly/v2ray-core/v5/common/serial"
  17. feature_dns "github.com/v2fly/v2ray-core/v5/features/dns"
  18. "github.com/v2fly/v2ray-core/v5/proxy/freedom"
  19. "github.com/v2fly/v2ray-core/v5/testing/servers/udp"
  20. )
  21. func TestFakeDNS(t *testing.T) {
  22. port := udp.PickPort()
  23. dnsServer := dns.Server{
  24. Addr: "127.0.0.1:" + port.String(),
  25. Net: "udp",
  26. Handler: &staticHandler{},
  27. UDPSize: 1200,
  28. }
  29. go dnsServer.ListenAndServe()
  30. time.Sleep(time.Second)
  31. config := &core.Config{
  32. App: []*anypb.Any{
  33. serial.ToTypedMessage(&Config{
  34. NameServer: []*NameServer{
  35. { // "fakedns"
  36. Address: &net.Endpoint{
  37. Network: net.Network_UDP,
  38. Address: &net.IPOrDomain{
  39. Address: &net.IPOrDomain_Domain{
  40. Domain: "fakedns",
  41. },
  42. },
  43. Port: uint32(53),
  44. },
  45. },
  46. { // { "address": "127.0.0.1", "port": "<port>", "domains": ["domain:google.com"], "fakedns": "198.19.0.0/16", "fallbackStrategy": "disabled" }
  47. Address: &net.Endpoint{
  48. Network: net.Network_UDP,
  49. Address: &net.IPOrDomain{
  50. Address: &net.IPOrDomain_Ip{
  51. Ip: []byte{127, 0, 0, 1},
  52. },
  53. },
  54. Port: uint32(port),
  55. },
  56. PrioritizedDomain: []*NameServer_PriorityDomain{
  57. {Type: DomainMatchingType_Subdomain, Domain: "google.com"},
  58. },
  59. FakeDns: &fakedns.FakeDnsPoolMulti{
  60. Pools: []*fakedns.FakeDnsPool{
  61. {IpPool: "198.19.0.0/16", LruSize: 256},
  62. },
  63. },
  64. FallbackStrategy: FallbackStrategy_Disabled.Enum(),
  65. },
  66. },
  67. FakeDns: &fakedns.FakeDnsPoolMulti{ // "fakedns": "198.18.0.0/16"
  68. Pools: []*fakedns.FakeDnsPool{
  69. {IpPool: "198.18.0.0/16", LruSize: 256},
  70. },
  71. },
  72. }),
  73. serial.ToTypedMessage(&dispatcher.Config{}),
  74. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  75. serial.ToTypedMessage(&policy.Config{}),
  76. },
  77. Outbound: []*core.OutboundHandlerConfig{
  78. {
  79. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  80. },
  81. },
  82. }
  83. v, err := core.New(config)
  84. common.Must(err)
  85. common.Must(v.Start())
  86. dnsClient := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  87. fakeClient := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSClient()
  88. var fakeIPForFacebook net.IP
  89. var fakeIPForGoogle net.IP
  90. { // Lookup facebook.com with Fake Client will return 198.18.0.0/16 (global fake pool)
  91. ips, err := fakeClient.LookupIP("facebook.com")
  92. if err != nil {
  93. t.Fatal("unexpected error: ", err)
  94. }
  95. for _, ip := range ips {
  96. if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip) {
  97. t.Fatal("Lookup facebook.com with fake client not in global pool 198.18.0.0/16")
  98. }
  99. }
  100. fakeIPForFacebook = ips[0]
  101. }
  102. { // Lookup facebook.com with Normal Client with return empty record (because UDP server matching "domain:google.com" are configured with fallback disabled)
  103. _, err := dnsClient.LookupIP("facebook.com")
  104. if err != feature_dns.ErrEmptyResponse {
  105. t.Fatal("Lookup facebook.com with normal client not returning empty response")
  106. }
  107. }
  108. { // Lookup google.com with Fake Client will return 198.19.0.0/16 (local fake pool)
  109. ips, err := fakeClient.LookupIP("google.com")
  110. if err != nil {
  111. t.Fatal("unexpected error: ", err)
  112. }
  113. for _, ip := range ips {
  114. if !(&net.IPNet{IP: net.IP{198, 19, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip) {
  115. t.Fatal("Lookup google.com with fake client not in global pool 198.19.0.0/16")
  116. }
  117. }
  118. fakeIPForGoogle = ips[0]
  119. }
  120. { // Lookup google.com with Normal Client will return 8.8.8.8
  121. ips, err := dnsClient.LookupIP("google.com")
  122. if err != nil {
  123. t.Fatal("unexpected error: ", err)
  124. }
  125. if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
  126. t.Fatal("Lookup google.com with normal client not returning 8.8.8.8")
  127. }
  128. }
  129. fakeEngine := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSEngine().(feature_dns.FakeDNSEngineRev0)
  130. {
  131. if !fakeEngine.IsIPInIPPool(net.IPAddress(fakeIPForFacebook)) {
  132. t.Fatal("Fake IP of domain facebook.com not in FakeDNSEngine's pool.")
  133. }
  134. if !fakeEngine.IsIPInIPPool(net.IPAddress(fakeIPForGoogle)) {
  135. t.Fatal("Fake IP of domain google.com not in FakeDNSEngine's pool.")
  136. }
  137. }
  138. {
  139. if domain := fakeEngine.GetDomainFromFakeDNS(net.IPAddress(fakeIPForFacebook)); domain != "facebook.com" {
  140. t.Fatal("Recover fake IP to get domain facebook.com failed.")
  141. }
  142. if domain := fakeEngine.GetDomainFromFakeDNS(net.IPAddress(fakeIPForGoogle)); domain != "google.com" {
  143. t.Fatal("Recover fake IP to get domain google.com failed.")
  144. }
  145. }
  146. {
  147. ips := fakeEngine.GetFakeIPForDomain("api.google.com")
  148. for _, ip := range ips {
  149. if !(&net.IPNet{IP: net.IP{198, 19, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip.IP()) {
  150. t.Fatal("Fake IP for api.google.com not in local pool 198.19.0.0/16")
  151. }
  152. }
  153. }
  154. {
  155. ips := fakeEngine.GetFakeIPForDomain3("v2fly.org", true, false)
  156. for _, ip := range ips {
  157. if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip.IP()) {
  158. t.Fatal("Fake IP for v2fly.org not in global pool 198.18.0.0/16")
  159. }
  160. }
  161. }
  162. }
  163. func TestFakeDNSEmptyGlobalConfig(t *testing.T) {
  164. config := &core.Config{
  165. App: []*anypb.Any{
  166. serial.ToTypedMessage(&Config{
  167. NameServer: []*NameServer{
  168. { // "fakedns"
  169. Address: &net.Endpoint{
  170. Network: net.Network_UDP,
  171. Address: &net.IPOrDomain{
  172. Address: &net.IPOrDomain_Domain{
  173. Domain: "fakedns",
  174. },
  175. },
  176. },
  177. QueryStrategy: QueryStrategy_USE_IP4.Enum(),
  178. },
  179. { // "localhost"
  180. Address: &net.Endpoint{
  181. Network: net.Network_UDP,
  182. Address: &net.IPOrDomain{
  183. Address: &net.IPOrDomain_Domain{
  184. Domain: "localhost",
  185. },
  186. },
  187. },
  188. QueryStrategy: QueryStrategy_USE_IP6.Enum(),
  189. PrioritizedDomain: []*NameServer_PriorityDomain{
  190. {Type: DomainMatchingType_Subdomain, Domain: "google.com"},
  191. },
  192. FakeDns: &fakedns.FakeDnsPoolMulti{Pools: []*fakedns.FakeDnsPool{}}, // "fakedns": true
  193. },
  194. },
  195. }),
  196. serial.ToTypedMessage(&dispatcher.Config{}),
  197. serial.ToTypedMessage(&proxyman.OutboundConfig{}),
  198. serial.ToTypedMessage(&policy.Config{}),
  199. },
  200. Outbound: []*core.OutboundHandlerConfig{
  201. {
  202. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  203. },
  204. },
  205. }
  206. v, err := core.New(config)
  207. common.Must(err)
  208. common.Must(v.Start())
  209. dnsClient := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
  210. fakeClient := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSClient()
  211. { // Lookup facebook.com will return 198.18.0.0/15 (default IPv4 pool)
  212. ips, err := fakeClient.LookupIP("facebook.com")
  213. if err != nil {
  214. t.Fatal("unexpected error: ", err)
  215. }
  216. for _, ip := range ips {
  217. if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(15, 8*net.IPv4len)}).Contains(ip) {
  218. t.Fatal("Lookup facebook.com with fake client not in default IPv4 pool 198.18.0.0/15")
  219. }
  220. }
  221. }
  222. { // Lookup google.com will return fc00::/18 (default IPv6 pool)
  223. ips, err := fakeClient.LookupIP("google.com")
  224. if err != nil {
  225. t.Fatal("unexpected error: ", err)
  226. }
  227. for _, ip := range ips {
  228. if !(&net.IPNet{IP: net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Mask: net.CIDRMask(18, 8*net.IPv6len)}).Contains(ip) {
  229. t.Fatal("Lookup google.com with fake client not in default IPv6 pool fc00::/18")
  230. }
  231. }
  232. }
  233. }