Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

That's an excellent question! When I was writing that I was pretty deep in DNS code and standards I think I just understood that as a rule of DNS. Or at the least, I believed I understood. Looking back a decade later I can't find any standard which supports my statement. However lots of other secondary sources seem to agree with me.

"In these situations, the client needs to re-transmit over TCP for which the size limit is 64000 bytes" [0]

"The first response via UDP is, no surprise, truncated, so we retry via TCP. But now the DNS result delivered via TCP is also truncated! That is, the DNS server has determined that the result will not fit into the maximum response size. Why is that?

"Our payload is 4096 * 16 = 65536 bytes RDATA, which should fit into the DNS packet, which uses a two byte RDLENGTH field. But we also need to again account for the overhead noted above: 12 bytes DNS header, 36 bytes for the query, 11 bytes additional records, and 16 bytes for each A record, yielding (4096 * 16) + 12 + 36 + 11 = 65595 bytes in total. And the maximum size of an IP packet is 16 bit (via the IPv4 total length / IPv6 payload length). And that is now our limiting factor: 65536 bytes for DNS overhead + payload."

My best guess is that DNS just makes the assumption that everything needs to fit in a single IP packet and it doesn't care if it is UDP or TCP.

It is worth investigating if you have spare time.

[0]: https://www.infoblox.com/dns-security-resource-center/dns-se...

[1]: https://www.netmeister.org/blog/dns-size.html



I think that second reference has a couple errors, and this has nothing to do with IP packets (datagrams).

As js2 notes, the entire DNS message has to be prefixed with a 2 byte field (and they seem to have omitted that in their diagram at the top of the page, the DNS header is 14 bytes, not 12 for TCP). That is the limiting factor. The DNS server doesn't really care what the underlying limits of the TCP stack are or whether the response fits in a single IP datagram (that likely needs to be split up).

As they seem to figure out the actual limit is RD payload + DNS overhead <= 64k bytes. What they are forgetting is that the TCP segment overhead means that this maximum wouldn't fit in a single IP datagram anyhow. Since the minimum TCP header size is 20 bytes any DNS message >65514 bytes will have to be split.

In practice none of this matters though as the OS had better make the TCP maximum segment size less than the MTU to avoid fragmentation, often something 1460 or less. Any DNS query substantially over that is going to be going in multiple IP datagrams.


RFC 1035:

> Messages sent over TCP connections use server port 53 (decimal). The message is prefixed with a two byte length field which gives the message length, excluding the two byte length field. This length field allows the low-level processing to assemble a complete message before beginning to parse it.

https://www.rfc-editor.org/rfc/rfc1035#section-4.2.2


This is the actual reason. TCP being a stream-oriented protocol, it would be perfectly valid (although totally inefficient) for the DNS server to send back an answer in 25 small-sized TCP packets. The DNS client would possibly even not notice it.


Thanks!


> My best guess is that DNS just makes the assumption that everything needs to fit in a single IP packet and it doesn't care if it is UDP or TCP.

It's not an assumption, it's a requirement. "Legacy" DNS has no provision for a response to exceed a single IP packet size. The assumption part is that this is adequate for a DNS response. Before DNSSEC, it was.

I believe DoH and friends don't have this restriction.

EDIT: too late to delete but this is wrong. see child comments.


> It's not an assumption, it's a requirement.

Where is this requirement? A DNS server responding over a TCP socket has no idea of the underlying IP datagram size. In a typical Ethernet, the TCP MSS will be 1460 bytes so the IP packets will all be under 1500 bytes. You certainly can get regular TCP DNS responses bigger than 1460 bytes. See elsewhere in this thread, "legacy" RFC1035 DNS over TCP has a 16-bit message prefix which limits the total DNS message to 64kiB. A valid maximum DNS TCP response can exceed (the almost entirely theoretical) max IP packet size by 22 bytes, FWIW.


An IP packet can be much larger than a single TCP segment. It can be up to 65536 bytes. IP doesn't have datagrams, it has packets. Well, technically it does have datagrams but what I'm getting at is that with fragmentation (let's say you have broken PMTUD) an IP packet can be split up.

That said, terminology confusion aside, you are still correct and I was wrong. The response can indeed be larger than a single IP packet. 65536 + IP overhead, split across as many IP packets as needed (doesn't have to be a single very large fragmented packet).

I will delete my response!


> Well, technically it does have datagrams but what I'm getting at is that with fragmentation (let's say you have broken PMTUD) an IP packet can be split up.

Of course, but in the happy usual case your network stack should be starting off with a TCP MSS <= MTU + overhead and the IP datagrams will not be fragmented.

I used the term "datagram" because to higher layers like TCP, it is formally specified this way. I'm not too concerned about pedantry (except to avoid confusion) but this is the literal RFC9293 text: "The application byte-stream is conveyed over the network via TCP segments, with each TCP segment sent as an Internet Protocol (IP) datagram. "


Thanks for the corrections. I think pedantry is a good thing when discussing protocols.

Even today, PMTUD doesn't always work (as expected) because of VPN shenanigans. But right, usually you don't see fragments.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: