Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embedded DNS does not compress responses for container aliases #2490

Open
asilvr opened this issue Dec 7, 2019 · 0 comments
Open

Embedded DNS does not compress responses for container aliases #2490

asilvr opened this issue Dec 7, 2019 · 0 comments

Comments

@asilvr
Copy link

asilvr commented Dec 7, 2019

Description

When running one or more Docker containers with the --network-alias flag set, Docker's embedded DNS does not compress the DNS responses for DNS requests against the alias.

According to RFC-1123 Section 6.1.2.4, "Name servers MUST use compression in responses."

Docker's embedded DNS currently does support compression, but only when the response is coming from an upstream/external DNS server. When the embedded DNS server is serving the answer for the request, it is not currently compressing the response.

This presents problems for applications consuming aliases answered by the embedded DNS, as the response does not adhere to the RFC, and can fail in some client libraries. Examples include applications that utilize the embedded DNS for service discovery.

Steps to reproduce

To reproduce the issue, three containers are spun up with the network alias docker.com. A DNS request to Google DNS (8.8.8.8) for the real docker.com responds with three answers and is compressed. A DNS request to embedded DNS for the aliased docker.com responds with three answers and is not compressed.

This issue occurs for me on docker version 19.03.5.

  1. Create a test network:
$ docker network create test-dns
  1. Run this command three times to create three containers (make sure they're all started):
$ docker run --network-alias docker.com --network test-dns -it centos:7 bash
  1. Inside one of the containers, add bind-utils for performing DNS lookups:
$ yum install -y bind-utils
  1. Inside the same container, add tcpdump to perform a packet capture:
$ yum install -y tcpdump
  1. Inside the same container, start the tcpdump to capture to a file:
$ tcpdump -i any -nnn -w capture.pcap
  1. Inside the same container, lookup docker.com:
$ dig @127.0.0.11 docker.com
  1. Inside the same container, lookup docker.com against Google DNS:
$ dig @8.8.8.8 docker.com
  1. End the tcpdump. Compare the first DNS response in the packet capture against the second DNS response. See the difference in the payloads, specifically related to the use of compression pointers.

Embedded DNS (notice no pointers):
embedded_dns

External DNS (notice pointers indicated by leading 11 bits):
external_dns

Workaround

A workaround noted in a similar (but not exactly the same issue) is to use an external DNS server (container or otherwise) and pass that in to your container(s). While this can be used as a solution, it bypasses the benefit of using the embedded DNS. It also requires an added layer of complexity by coordinating DNS records with Docker container IP addresses.

Fix

Currently, compression is only performed on external DNS responses, which is made by doing resp.Compress = true on this line.

A proposed fix would be to move and/or copy this logic to the outer scope of the ServeDNS function, at the end of the function just before w.WriteMsg(resp). This would ensure that all responses are utilizing compression.

I'll happily push a PR with the above fix if this is an agreeable solution. I have not yet figured out how new test cases would fit for this, but I believe it should be reasonable to test. I'd be open to test suggestions.

References

A similar issue was reported a few years ago here but did not seem to be addressed in any commits (the code links in that issue seem out-of-date since they use master as the branch). I cannot immediately tell from that issue if there was a reason for not addressing it as described above. Please let me know if this is deemed out of scope for some reason; I believe it's a simple fix which can only yield a net benefit in terms of RFC compliance.

Also, embedded DNS is a reference to the use of the term from these excellent docs.

Thanks for reading!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant