[GH-ISSUE #1078] UDP - IO Error when EDNS max payload is larger then 2048 #599

Closed
opened 2026-03-15 23:23:02 +03:00 by kerem · 6 comments
Owner

Originally created by @DevQps on GitHub (Apr 24, 2020).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1078

Describe the bug
I was used the UDP Async resolver and figured out that responses larger then 2048 bytes trigger an IO error in case that the EDNS maximum payload is set to a higher value. In trust-dns/crates/proto/src/udp/udp_stream.rs I saw the code:

// TODO: this should match edns settings
let mut buf = [0u8; 2048];
let (len, src) = ready!(socket.recv_from(&mut buf).poll_unpin(cx))?;

I guess the buffer size seems hardcoded?

To Reproduce
Query any DNS domain with larger responses while EDNS max_payload is set to something higher then 2048.

Expected behavior
Expects a way to change the buffer size of UDP sockets or to use a higher default size. The RFC recommends a maximum of 4096 if I remember correctly.

RFC6891

6.2.5.  Payload Size Selection

   Due to transaction overhead, it is not recommended to advertise an
   architectural limit as a maximum UDP payload size.  Even on system
   stacks capable of reassembling 64 KB datagrams, memory usage at low
   levels in the system will be a concern.  A good compromise may be the
   use of an EDNS maximum payload size of 4096 octets as a starting
   point.

System:

  • OS: Windows 10
  • Architecture: x64
  • Version: Latest
  • rustc version: 1.41.1

Version:
Crate: [e.g. client, server, resolver]
Version: [e.g. 0.9.1]

Additional context
Add any other context about the problem here.

Originally created by @DevQps on GitHub (Apr 24, 2020). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1078 **Describe the bug** I was used the UDP Async resolver and figured out that responses larger then 2048 bytes trigger an IO error in case that the EDNS maximum payload is set to a higher value. In ` trust-dns/crates/proto/src/udp/udp_stream.rs` I saw the code: ``` // TODO: this should match edns settings let mut buf = [0u8; 2048]; let (len, src) = ready!(socket.recv_from(&mut buf).poll_unpin(cx))?; ``` I guess the buffer size seems hardcoded? **To Reproduce** Query any DNS domain with larger responses while EDNS max_payload is set to something higher then 2048. **Expected behavior** Expects a way to change the buffer size of UDP sockets or to use a higher default size. The RFC recommends a maximum of 4096 if I remember correctly. RFC6891 ``` 6.2.5. Payload Size Selection Due to transaction overhead, it is not recommended to advertise an architectural limit as a maximum UDP payload size. Even on system stacks capable of reassembling 64 KB datagrams, memory usage at low levels in the system will be a concern. A good compromise may be the use of an EDNS maximum payload size of 4096 octets as a starting point. ``` **System:** - OS: Windows 10 - Architecture: x64 - Version: Latest - rustc version: 1.41.1 **Version:** Crate: [e.g. client, server, resolver] Version: [e.g. 0.9.1] **Additional context** Add any other context about the problem here.
kerem 2026-03-15 23:23:02 +03:00
Author
Owner

@bluejekyll commented on GitHub (Apr 27, 2020):

I'm open to expanding this, though I have some concerns about reflection attacks that this might support. My preference would be that folks use TCP instead for larger packet sizes. I believe that Cloudflare and Google are trying to limit packet sizes over UDP to 512, and force TCP for packets larger than that.

Out of curiosity, could you share the query where your running into this limit? I'm curious what the response is that is this large. Anything over 1500 bytes starts getting into UDP fragmentation, that's not desirable.

I'm open to expanding this, but I also want to be cognizant of concerns with some of the downsides of large UDP packet sizes.

<!-- gh-comment-id:620127853 --> @bluejekyll commented on GitHub (Apr 27, 2020): I'm open to expanding this, though I have some concerns about reflection attacks that this might support. My preference would be that folks use TCP instead for larger packet sizes. I believe that Cloudflare and Google are trying to limit packet sizes over UDP to 512, and force TCP for packets larger than that. Out of curiosity, could you share the query where your running into this limit? I'm curious what the response is that is this large. Anything over 1500 bytes starts getting into UDP fragmentation, that's not desirable. I'm open to expanding this, but I also want to be cognizant of concerns with some of the downsides of large UDP packet sizes.
Author
Owner

@DevQps commented on GitHub (May 4, 2020):

@bluejekyll Thank you for your reply and sorry for my late reply!

The problem mainly occurs when you're trying to fetch DNSSEC results with UDP, since the signatures are often pretty large. An example query is:

A random example is: Querying CAA for gelreziekenhuizen.nl or TXT on maasstadziekenhuis.nl

The error message given by my OS states that the received message is larger then the internal buffer size. There are quite some other cases! It's mainly when multiple responses are given.

I first thought about using TCP as well but that of course has some significant overhead. For applications that need to do many DNS requests at different hosts, this is much less of an option.

I would already be very happy if I could somehow specify a custom buffer size!

<!-- gh-comment-id:623418993 --> @DevQps commented on GitHub (May 4, 2020): @bluejekyll Thank you for your reply and sorry for my late reply! The problem mainly occurs when you're trying to fetch DNSSEC results with UDP, since the signatures are often pretty large. An example query is: A random example is: Querying CAA for `gelreziekenhuizen.nl` or TXT on `maasstadziekenhuis.nl` The error message given by my OS states that the received message is larger then the internal buffer size. There are quite some other cases! It's mainly when multiple responses are given. I first thought about using TCP as well but that of course has some significant overhead. For applications that need to do many DNS requests at different hosts, this is much less of an option. I would already be very happy if I could somehow specify a custom buffer size!
Author
Owner

@bluejekyll commented on GitHub (May 4, 2020):

ok, I can be convinced. I think we should take care of this one as well: #664

Basically, I think the strategy could be just to bump the UDP read size up to the max UDP packet size, and after read, immediately trim it down to a properly sized Vec to pass around.

Is this something you'd be interested in working on? I can give pointers to where in the code to handle this.

<!-- gh-comment-id:623596651 --> @bluejekyll commented on GitHub (May 4, 2020): ok, I can be convinced. I think we should take care of this one as well: #664 Basically, I think the strategy could be just to bump the UDP read size up to the max UDP packet size, and after read, immediately trim it down to a properly sized Vec to pass around. Is this something you'd be interested in working on? I can give pointers to where in the code to handle this.
Author
Owner

@DevQps commented on GitHub (May 4, 2020):

I can work on it if you like! I am not familiar with the codebase, so I could use some points.

Do you think we should just bump the reader size from 2048 to 4096? Or did I misinterpret what you meant? And with trimming a Vec you mean allocating a new Vec that is smaller and deallocate the old Vec to save space? Or do you mean something else by this?

<!-- gh-comment-id:623725851 --> @DevQps commented on GitHub (May 4, 2020): I can work on it if you like! I am not familiar with the codebase, so I could use some points. Do you think we should just bump the reader size from 2048 to 4096? Or did I misinterpret what you meant? And with trimming a Vec you mean allocating a new Vec that is smaller and deallocate the old Vec to save space? Or do you mean something else by this?
Author
Owner

@bluejekyll commented on GitHub (May 5, 2020):

Ok, to fix this, all that needs to happen is the change you already identified: github.com/bluejekyll/trust-dns@aa315c13b9/crates/proto/src/udp/udp_stream.rs (L161)

Just bump that value to 4096, and that would handle most cases. #664 is a windows specific issue. I don't think we necessarily want to handle that though, as it would require passing in a buffer of 64k. I don't think we want to do that, so I'm fine with setting this to 4k for now.

If you want to make that change, I believe the rest of the code already does the correct thing.

<!-- gh-comment-id:623775146 --> @bluejekyll commented on GitHub (May 5, 2020): Ok, to fix this, all that needs to happen is the change you already identified: https://github.com/bluejekyll/trust-dns/blob/aa315c13b9c6a75f6c383b435a2506373e312d96/crates/proto/src/udp/udp_stream.rs#L161 Just bump that value to 4096, and that would handle most cases. #664 is a windows specific issue. I don't think we necessarily want to handle that though, as it would require passing in a buffer of 64k. I don't think we want to do that, so I'm fine with setting this to 4k for now. If you want to make that change, I believe the rest of the code already does the correct thing.
Author
Owner

@DevQps commented on GitHub (May 6, 2020):

I think we can close this one as well then since PR #1096 was merged.

<!-- gh-comment-id:624496126 --> @DevQps commented on GitHub (May 6, 2020): I think we can close this one as well then since PR #1096 was merged.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#599
No description provided.