I had a DNS record (ex: test.example.com) pointing to a single IP:
test.example.com IN A 192.0.2.1
Working fine. Now I have +30 IPs answering for it, example:
teste.example.com IN A 192.0.2.1
teste.example.com IN A 192.0.2.2
(...)
teste.example.com IN A 192.0.2.31
And now it's unstable ("can't find host" errors). Using dig
I got a warning "Truncated, retrying in TCP mode". 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, and avoid an extra query (or problems with no-tcp dns clients or providers, old dns sw, etc).
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?
or
Is it possible to configure ISC Bind to return only one IP in a multi-IP query? I know that the IP can be cycled with rrset-order { order cyclic; };
.
Like:
> test.example.com
Server: x.x.x.x
Address: x.x.x.x:53
Name: test.example.com
Address: 192.0.2.6
so, only one of them? Thanks.
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.
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).
"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.
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:
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. ForA
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:
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:
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 yieldsx=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 :-) ]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
uses1232
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.