And now it's unstable ("can't find host" errors)
From where/how?
All properly set up resolvers, as you noticed, will get a Truncated flag on their first query over UDP and then will switch over TCP and everything will be fine.
Of course, you remember that DNS is over UDP AND TCP (contrary to a popular myth) so you need to make sure your authoritative nameservers can be queried over TCP, and all will be fine.
After some Google searches, I found out that a multi-IP query must have no more than 512 bytes to guarantee that UDP will be used
It depends. You can sometimes go over 1000. But most importantly, things fallback to TCP so shouldn't be a problem (just a slight loss in performances, maybe).
and avoid an extra query (or problems with no-tcp dns clients or providers, old dns sw, etc).
"no-tcp dns clients or providers" shouldn't exist as it makes no sense and is against the DNS specifications written... more than 40 years ago!
Or do you have specific proofs of those cases?
Don't try to go around things like that. If these pieces of software exist they are broken and will have A TON of other problems, like for DNSSEC secured domains.
So, how can I know how many v4 IPs can I have in a single dns entry to guarantee a maximum of 512 bytes UDP answer?
This is not possible to answer in general (because depends on the name) but most important, it is kind of futile to try optimizing things that way.
Anyway you can do the computation easily:
- a UDP packet has 8 bytes header before the data (RFC 768)
- a DNS packet, see RFC 1035, has an header (12 bytes), then the question (variable amount of bytes, see later), then the answer (see later), and we will consider additional and authority section to be empty.
So we are already at 512-8-12 = 492 bytes for DNS question + answer.
In answer, an A
record will be name (variable length) + type (2 bytes) + class (2 bytes) + TTL (4 bytes) + length (2 bytes) and then the data. For A
the data is 4 bytes (an IPv4 address).
The question is name (variable length) + type (2 bytes) + class (2 bytes).
Names in DNS packets have these two properties:
- they are encoded as a list of labels prefixed by length
- there may be compressed so that a given name or part of name appears only once.
So for example example.com
is encoded in DNS as 7,e,x,a,m,p,l,e,3,c,o,m,0
where each length is one byte, but if the name is later needed it will be replaced by a pointer using 2 bytes only.
If we take that name:
- the size of the name part in question will be: 13 bytes, so total size of question: 13 + 2 + 2 = 17
- in answer, each name can be a pointer of 2 bytes referencing the name in the question, so each record in answer will be in length 2 bytes for name and then the rest above, so 16 bytes.
Hence the full DNS packet will be of size 12 (header) + 17 (question) + x times 16 where x is the number of A
records.
So we have to resolve: 512 = 8 + 12 + 17 + 16x
for x, which yields x=29
or so.
Remember that this is under the best circumstances (no additional/authority records, and name compression used in full) and for a specific name (but if using compression the name appears in full only once in question, so only that size changes).
[Also, by the way, don't be trapped in last century legacy Internet; nowadays IPv6 should be the norm; of course you put even less AAAA
record types in a fixed size DNS packet than IPv4 ones :-) ]
Is it possible to configure ISC Bind to return only one IP in a multi-IP query?
I don't think so and if it existed how bind would choose which IP to return? If you are here it is up to you to only list one IP in the zonefile. Or if you are really attached to this idea (but again all the time you loose in this won't prevent other problems because the clients are buggy so you are trying to battle an infinite hill anyway), you may try dnsdist
that is kind of a swiss-army knife and allows fine tuning.
PS: also remember that DNS has an extension to allow one party to specify the (UDP) buffer size it can receive. See RFC 6891. A recent dig
uses 1232
as default there. You might be interested in general to look at https://kb.isc.org/docs/aa-01219 or the DNS flag day of 2020 at https://dnsflagday.net/2020/ that was exactly about this.