Thank you for the detailed test results. I tested 124.6.190.249 and 124.6.190.88. The problem is that their limit on the size of is smaller than the default assumed by dnstt-server. The default is 1232 and these resolvers only support 512 or 1220. To solve the problem, provide the command line option -mtu 512
to dnstt-server:
dnstt-server -mtu 512 -udp addr:port -privkey-file filename domain upstreamaddr:upstreamport
The MTU issue is lightly documented at the home page and in the dnstt-server man page, but reading them just now, the documentation on this point is not clear and should be improved.
More details
The problem is not with TXT resource records. Both 124.6.190.249 and 124.6.190.88 can do TXT records:
$ dig @124.6.190.249 -t TXT example.com
; <<>> DiG 9.18.24-1-Debian <<>> @124.6.190.249 -t TXT example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6112
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1220
; COOKIE: 682760d4590465a4232f4c146648c75ee62c96b134f7ace1 (good)
;; QUESTION SECTION:
;example.com. IN TXT
;; ANSWER SECTION:
example.com. 86400 IN TXT "v=spf1 -all"
example.com. 86400 IN TXT "wgyf8z8cgvm2qmxpnbnldrcltvk4xqfn"
;; Query time: 628 msec
;; SERVER: 124.6.190.249#53(124.6.190.249) (UDP)
;; WHEN: Sat May 18 15:21:03 UTC 2024
;; MSG SIZE rcvd: 137
$ dig @124.6.190.88 -t TXT example.com
; <<>> DiG 9.18.24-1-Debian <<>> @124.6.190.88 -t TXT example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4075
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1220
; COOKIE: cb5527d58aa4ae5a6e1992c66648c792278391521e202916 (good)
;; QUESTION SECTION:
;example.com. IN TXT
;; ANSWER SECTION:
example.com. 86400 IN TXT "wgyf8z8cgvm2qmxpnbnldrcltvk4xqfn"
example.com. 86400 IN TXT "v=spf1 -all"
;; Query time: 692 msec
;; SERVER: 124.6.190.88#53(124.6.190.88) (UDP)
;; WHEN: Sat May 18 15:21:54 UTC 2024
;; MSG SIZE rcvd: 137
The clue is actually this:
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1220
This number 1220 is the maximum size of a UDP packet the resolver is able to receive. The default assumed by dnstt-server is 1232 bytes, which is a compromise between performance and compatibility.
But I tried -mtu 1220
, and it didn’t work. The reason is that while the recursive resolvers themselves may be able to receive UDP packets of 1220 bytes, when they forward queries to the authoritative resolver, the forwarded queries declare a maximum packet size of only 512. (Actually 124.6.190.249 seems to use a mix of 512 and 1220: it probably is a load balancer over multiple resolvers with different configurations.)
The symptom of the MTU problem is FORMERR
messages in the dnstt-server log. When running dnstt-server with the default MTU of 1232, and using 124.6.190.88 as a resolver, I see this:
2024/05/18 15:49:30 FORMERR: requester payload size 512 is too small (minimum 1232)
2024/05/18 15:49:31 FORMERR: requester payload size 512 is too small (minimum 1232)
2024/05/18 15:49:31 FORMERR: requester payload size 512 is too small (minimum 1232)
2024/05/18 15:49:31 FORMERR: requester payload size 512 is too small (minimum 1232)
With 124.6.190.249 as a resolver I see a mix of 512 and 1220:
2024/05/18 15:44:35 FORMERR: requester payload size 512 is too small (minimum 1232)
2024/05/18 15:44:35 FORMERR: requester payload size 1220 is too small (minimum 1232)
2024/05/18 15:44:35 FORMERR: requester payload size 512 is too small (minimum 1232)
2024/05/18 15:44:36 FORMERR: requester payload size 1220 is too small (minimum 1232)
In either case, -mtu 512
on the server makes it work.
Ideally it would be possible to have the MTU be determined dynamically on the server according to the capabilities of each resolver. I think it’s possible, but it’s not trivial to implement, because the MTU is a global option of KCP. You can see some general discussion on this point here:
It may be we can cajole the sequencing/reliability layer to give us a packet of no larger than a specific size on demand, like, “give me a packet whose total size is at most 80 bytes, or else return an error.” The libraries I’ve looked at so far seem not to be architected that way; you don’t “pull” packets from them, rather they “push” one on you via a callback, but maybe it’s possible to achieve something similar by manipulating the MTU.