You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
Create a test network:
$ docker network create test-dns
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
Inside one of the containers, add bind-utils for performing DNS lookups:
$ yum install -y bind-utils
Inside the same container, add tcpdump to perform a packet capture:
$ yum install -y tcpdump
Inside the same container, start the tcpdump to capture to a file:
$ tcpdump -i any -nnn -w capture.pcap
Inside the same container, lookup docker.com:
$ dig @127.0.0.11 docker.com
Inside the same container, lookup docker.com against Google DNS:
$ dig @8.8.8.8 docker.com
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):
External DNS (notice pointers indicated by leading 11 bits):
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!
The text was updated successfully, but these errors were encountered:
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 realdocker.com
responds with three answers and is compressed. A DNS request to embedded DNS for the aliaseddocker.com
responds with three answers and is not compressed.This issue occurs for me on docker version 19.03.5.
bind-utils
for performing DNS lookups:tcpdump
to perform a packet capture:tcpdump
to capture to a file:docker.com
:docker.com
against Google DNS: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):
External DNS (notice pointers indicated by leading 11 bits):
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 beforew.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!
The text was updated successfully, but these errors were encountered: