5

I have a DNS domain with 3 TXT records:

$ORIGIN example.com.
@   IN TXT "thing one veryveryveryveryveryverylong"
@   IN TXT "thing two veryveryveryveryveryverylong"
@   IN TXT "thing three veryveryveryveryveryverylong"

When I do a DNS query (dig example.com. txt) the reply fits in a UDP packet because the payload is less than 512 bytes (resulting in a packet less than 576 bytes).

However I know that if the reply is long enough, it will be truncated and the DNS client will have to repeat the request using TCP, which has longer length limits.

How can I calculate whether or not I have exceeded the length limit without generating the DNS records and doing a query?

I assume that the formula is something like:

N: the number of TXT records on that label.
P: the number of bytes in all the TXT records.
S: the total number of text segments (TXT records can have multiple text segments per record)

UDP is required if N*a + P*b + S*c is more than 512

What are the values of a, b, and c?

(or am I going in the wrong direction?)

4 Answers 4

8

In practice, you should not be trying to pre-calculate the exact response size of your TXT records prior to implementing them. There are many variables in play, some of which you do not control. Most admins generalize based off the size of an existing TXT record response that they observe from their authoritative server and call it a day. Since the focus of your question is how to avoid generalizing, this answer is going to focus on why it is difficult to use precise calculations.

(This answer should not be taken as a statement for or against trying to stay inside of 512 bytes, it is a commentary on the approach used to do so.)

sDNSHeader + sQuestion + sAnswer + sAuthority + sAdditional
  • The query itself shows up in the question section of the reply packet, and must be taken into consideration.
  • As you surmised, the number of answers and their byte length must also be taken into consideration.
  • If the authoritative server is configured to list the nameservers in the authority section and the corresponding address records in the additional section, those have to be factored in as well.
  • If the request contained an EDNS0 pseudo-section inside the additional section, a compliant server will reply with its own pseudo-section. The query probably requested a message size of greater than 512 bytes if EDNS0 is in play, but it's still a consideration, particularly since network hardware in the communication path may incorrectly reject DNS packets >512 bytes as invalid and force the effective message limit back down to the original constraints.
  • RFC 1035 message compression is also a factor.

Can you write a program or script that will do all of this calculation for you? Sure. Is it a good use of time for the problem you're trying to solve? Probably not. Use an existing TXT record within the zone as your rough sizing guideline, and if growing over 512 bytes is a concern make sure you are familiar with any "include" functionality built into the relevant standard leveraging the TXT records. (SPF, etc.)

4

historically you get 512 octets of DNS payload, of which 10 octets is a fixed header. you have to make room for the copy of the question section that will be included in the response. that's roughly the question name plus four octets. each TXT RR will use a compression pointer up to the question name, for its owner name. that's two octets. then 10 octets of fixed overhead (ttl, class, type, and rdlen). you'll fit more text into a single really long TXT RR than into multiple discrete TXT RR's. in general you should try entering a bunch of different TXT RRs into one of your zones and then use "dig" to fetch each one and see how long "dig" says the payload is.

the historical 512 number was chosen for IPv4 but was not relaxed for IPv6. in IPv4, the payload plus the worst-case UDP and IP headers would yield a 568 octet IP datagram, which was the lowest allowed minimum reassembly buffer size -- an IPv4 endstation isn't "compliant" if it can't reassemble at least that much, so, noone is allowed to assume that you can reassemble more.

in modern DNS, the buffer size will be negotiated using an OPT RR ("EDNS0") and will usually be 4096. this reflects the much-larger-than-568-octets size that endstations can actually reassemble. obviously EDNS0 buffer sizes larger than your ethernet MTU (or your path MTU if you discover it) will cause IP fragmentation, and that often leads to loss since firewalls don't allow it. when EDNS0 @4K fails, it will often retry at 1460 (to leave room for IP and UDP headers plus your payload and still fit in an ethernet packet), and then retry at 512, and then perhaps retry without EDNS0 (which is also 512). if you depend on EDNS, you will often end up sending TC=1 ("truncation occurred") in which case the requestor will probably retry using TCP, or just fail outright.

what this means is if you depend on more than 512, you'll be using TCP a lot. since your question was about UDP, that likely means you should fit into 512.

1
  • DNSSEC often results in packets > 512 bytes, so firewalls that block these will cause severe performance problems. They should hopefully be rare these days.
    – Barmar
    Jul 28, 2017 at 14:39
2

If I read RFC1035 right, you have:

Header: 12 bytes
Question: querylen +1(null term)+4
Answer: N*(namelen+1+10+(S*(1+txtlen)))

So, for your example (where there is only one text segment S per TXT record):

query = example.com
querylen = 11
name: I'm not sure if that would be blank or example.com in your example
but I think it would be example.com, so

namelen = 11
txtlen1 = 38
txtlen2 = 38
txtlen3 = 40

So, we have 12+11+5=28 + answers

P1 = Answer1 = 11+11+1+38 = 61
P2 = Answer1 = 11+11+1+38 = 61
P3 = Answer1 = 11+11+1+40 = 63

28+61+61+63=213
1
  • The answers, if name compression is done correctly (it usually is), will use just 2 bytes to refer to the name in the question section, instead of copying the full name.
    – Habbie
    Jul 23, 2017 at 18:38
-3

TXT records can hold a maximum of 255 bytes of data and UDP packets can be any size. The UDP packet will be fragmented to fit into an IP at 65,507.

2
  • That's true but not how DNS limits UDP replies.
    – TomOnTime
    Jul 21, 2017 at 21:46
  • TXT records are limited to roughly 64 kilobytes each (slightly less due to DNS protocol overhead). As the previous comment says, DNS over UDP will however be limited to either 512 bytes or whatever the client said via EDNS0, capped to some sensible value, often 2-4 kilobytes. Above those 512 bytes/2-4 kilobytes, truncation happens and the client must retry over TCP.
    – Habbie
    Jul 23, 2017 at 18:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.