How to limit UDP datagram size?
I am currently playing with the EDNS extension to DNS protocol.
I am trying to create a lab environment where I can limit the max size of UDP datagrams, in order to force my two lab DNS servers (resolver and authoritative) to negotiate a different limit than the default 4096 bytes.
I found a reference pointing to the tunable parameter "net.inet.udp.maxdgram", so I tried to modify this value, lowering it down to 512 bytes, with apparent no success: I can still send a EDNS-enabled query to the auth server and get a ~3kbyte response in a single UDP datagram.
What am I missing here?
Can anyone point me in the right direction?
Thank you all!
JKnott last edited by JKnott
It looks like the default maximum payload size for EDNS:
If you restrict it you force it to fall back to some smaller size which is what I assume OP is trying.
If you disable pfscrub it will stop assumbling packet fragments which should limit it to whatever the link MTU is set to.
Actually, you are right, I did not explain myself well.
Historically, responses to DNS queries are limited to 512 bytes in size. In case the response to a query is bigger, e.g. in case the query is for a full zone transfer, the DNS protocol used to switch to TCP, so a single UDP datagram is replaced by a stream of TCP packet, which is more expensive.
The EDNS protocol, in short, extends the DNS protocol to accept single UDP datagrams up to 4096 bytes in size. So, while most zone transfers still require switching to TCP, this is normally not necessary in cases like
- multiple IP addresses returned for a single FQDN
- large TXT records
- DNSSEC information
The resolver on which I am working, by default allows EDNS responses; when it receives a query from a client, and performs recursion, it sends all queries with the EDNS option enabled, offering a max UDP size of 4096 (which is the default). In case the remote server is not able to handle UDP frames that big, it will offer a smaller max size. This will leave a message in the resolver, on the line of "query XYZ.TLD has been resolved successfully after reducing EDNS size to xxxx bytes".
In case the remote server can only handle the old standard of 512 bytes, the message will be something like "query XYZ.TLD has been resolved successfully after disabling EDNS".
This is also true (and WAY more frequent) in case the remote server is fine with the 4096 bytes, but some router/firewall in between is not configured to support EDNS.
So here's what I did.
I deployed two DNS servers, one configured as authoritative for a test zone, the other as a pure resolver; I made sure to deploy them on different networks, with my lab pfSense inbetween.
Then I created a set of 300 A records, all for the same FQDN, pointing to different IP addresses.
I send a query for the record from a client to the resolver, which in turn sends it to the auth server. While I do this, I take a traffic capture on the resolver.
As expected, the traffic capture shows the query (approx 85 bytes in size) and a single-UDP-frame response, approx 3100 bytes in size.
This means that both my DNS servers are OK with UDP frames larger than 512 bytes.
Now, I would like to configure the firewall to block UDP frames larger than, say 2kbytes, in order to see how the two server reacts when a query for 3.1k is sent.
I did so by setting "net.inet.udp.maxdgram" to 2048, then to 1024, then to 512, but nothing seems to happen: traffic captures taken on the resolver still show the 3.1k UDP datagram happily cross the firewall.
Any idea why?
Am I looking in the wrong place?
'net.inet.udp.maxdgram' probably only applies to connections from the firewall directly rather than routed though it.
Short update: it looks like the "net.inet.udp.maxdgram" is actually doing what I expected it to do.
I double checked my lab layout and I found a piece of incorrect configuration.
With the lab correctly setup, I can see that
- in case "net.inet.udp.maxdgram" is larger than my 3.1kb made up record, the DNS response from the auth server is one large UDP frame
- in case "net.inet.udp.maxdgram" is smaller, the communications switch to TCP.
So, net.inet.upd.dgram seems to be the way to go.
Thank you all for your attention, my best wishes of a good weekend to you all.