resolvconf_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package networking
  2. import (
  3. "context"
  4. "strings"
  5. "testing"
  6. "time"
  7. containertypes "github.com/docker/docker/api/types/container"
  8. "github.com/docker/docker/integration/internal/container"
  9. "github.com/docker/docker/integration/internal/network"
  10. "github.com/docker/docker/testutil/daemon"
  11. "gotest.tools/v3/assert"
  12. is "gotest.tools/v3/assert/cmp"
  13. "gotest.tools/v3/skip"
  14. )
  15. // Regression test for https://github.com/moby/moby/issues/46968
  16. func TestResolvConfLocalhostIPv6(t *testing.T) {
  17. // No "/etc/resolv.conf" on Windows.
  18. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  19. ctx := setupTest(t)
  20. tmpFileName := network.WriteTempResolvConf(t, "127.0.0.53")
  21. d := daemon.New(t, daemon.WithEnvVars("DOCKER_TEST_RESOLV_CONF_PATH="+tmpFileName))
  22. d.StartWithBusybox(ctx, t, "--experimental", "--ip6tables")
  23. defer d.Stop(t)
  24. c := d.NewClientT(t)
  25. defer c.Close()
  26. netName := "nnn"
  27. network.CreateNoError(ctx, t, c, netName,
  28. network.WithDriver("bridge"),
  29. network.WithIPv6(),
  30. network.WithIPAM("fd49:b5ef:36d9::/64", "fd49:b5ef:36d9::1"),
  31. )
  32. defer network.RemoveNoError(ctx, t, c, netName)
  33. result := container.RunAttach(ctx, t, c,
  34. container.WithImage("busybox:latest"),
  35. container.WithNetworkMode(netName),
  36. container.WithCmd("cat", "/etc/resolv.conf"),
  37. )
  38. defer c.ContainerRemove(ctx, result.ContainerID, containertypes.RemoveOptions{
  39. Force: true,
  40. })
  41. output := strings.ReplaceAll(result.Stdout.String(), tmpFileName, "RESOLV.CONF")
  42. assert.Check(t, is.Equal(output, `# Generated by Docker Engine.
  43. # This file can be edited; Docker Engine will not make further changes once it
  44. # has been modified.
  45. nameserver 127.0.0.11
  46. options ndots:0
  47. # Based on host file: 'RESOLV.CONF' (internal resolver)
  48. # ExtServers: [host(127.0.0.53)]
  49. # Overrides: []
  50. # Option ndots from: internal
  51. `))
  52. }
  53. // Check that when a container is connected to an internal network, DNS
  54. // requests sent to daemon's internal DNS resolver are not forwarded to
  55. // an upstream resolver listening on a localhost address.
  56. // (Assumes the host does not already have a DNS server on 127.0.0.1.)
  57. func TestInternalNetworkDNS(t *testing.T) {
  58. skip.If(t, testEnv.DaemonInfo.OSType == "windows", "No resolv.conf on Windows")
  59. skip.If(t, testEnv.IsRootless, "Can't use resolver on host in rootless mode")
  60. ctx := setupTest(t)
  61. // Start a DNS server on the loopback interface.
  62. network.StartDaftDNS(t, "127.0.0.1")
  63. // Set up a temp resolv.conf pointing at that DNS server, and a daemon using it.
  64. tmpFileName := network.WriteTempResolvConf(t, "127.0.0.1")
  65. d := daemon.New(t, daemon.WithEnvVars("DOCKER_TEST_RESOLV_CONF_PATH="+tmpFileName))
  66. d.StartWithBusybox(ctx, t, "--experimental", "--ip6tables")
  67. defer d.Stop(t)
  68. c := d.NewClientT(t)
  69. defer c.Close()
  70. intNetName := "intnet"
  71. network.CreateNoError(ctx, t, c, intNetName,
  72. network.WithDriver("bridge"),
  73. network.WithInternal(),
  74. )
  75. defer network.RemoveNoError(ctx, t, c, intNetName)
  76. extNetName := "extnet"
  77. network.CreateNoError(ctx, t, c, extNetName,
  78. network.WithDriver("bridge"),
  79. )
  80. defer network.RemoveNoError(ctx, t, c, extNetName)
  81. // Create a container, initially with external connectivity.
  82. // Expect the external DNS server to respond to a request from the container.
  83. ctrId := container.Run(ctx, t, c, container.WithNetworkMode(extNetName))
  84. defer c.ContainerRemove(ctx, ctrId, containertypes.RemoveOptions{Force: true})
  85. res, err := container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
  86. assert.NilError(t, err)
  87. assert.Check(t, is.Equal(res.ExitCode, 0))
  88. assert.Check(t, is.Contains(res.Stdout(), network.DNSRespAddr))
  89. // Connect the container to the internal network as well.
  90. // External DNS should still be used.
  91. err = c.NetworkConnect(ctx, intNetName, ctrId, nil)
  92. assert.NilError(t, err)
  93. res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
  94. assert.NilError(t, err)
  95. assert.Check(t, is.Equal(res.ExitCode, 0))
  96. assert.Check(t, is.Contains(res.Stdout(), network.DNSRespAddr))
  97. // Disconnect from the external network.
  98. // Expect no access to the external DNS.
  99. err = c.NetworkDisconnect(ctx, extNetName, ctrId, true)
  100. assert.NilError(t, err)
  101. res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
  102. assert.NilError(t, err)
  103. assert.Check(t, is.Equal(res.ExitCode, 1))
  104. assert.Check(t, is.Contains(res.Stdout(), "SERVFAIL"))
  105. // Reconnect the external network.
  106. // Check that the external DNS server is used again.
  107. err = c.NetworkConnect(ctx, extNetName, ctrId, nil)
  108. assert.NilError(t, err)
  109. res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
  110. assert.NilError(t, err)
  111. assert.Check(t, is.Equal(res.ExitCode, 0))
  112. assert.Check(t, is.Contains(res.Stdout(), network.DNSRespAddr))
  113. }
  114. // TestNslookupWindows checks that nslookup gets results from external DNS.
  115. // Regression test for https://github.com/moby/moby/issues/46792
  116. func TestNslookupWindows(t *testing.T) {
  117. skip.If(t, testEnv.DaemonInfo.OSType != "windows")
  118. ctx := setupTest(t)
  119. c := testEnv.APIClient()
  120. attachCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
  121. defer cancel()
  122. res := container.RunAttach(attachCtx, t, c,
  123. container.WithCmd("nslookup", "docker.com"),
  124. )
  125. defer c.ContainerRemove(ctx, res.ContainerID, containertypes.RemoveOptions{Force: true})
  126. assert.Check(t, is.Equal(res.ExitCode, 0))
  127. // Current default is to not-forward requests to external servers, which
  128. // can only be changed in daemon.json using feature flag "windows-dns-proxy".
  129. // So, expect the lookup to fail...
  130. assert.Check(t, is.Contains(res.Stderr.String(), "Server failed"))
  131. // When the default behaviour is changed, nslookup should succeed...
  132. //assert.Check(t, is.Contains(res.Stdout.String(), "Addresses:"))
  133. }