It's good to know what the RFCs say on the subject, and we already have a good authoritative answer on that, but for practical purposes, I find the advice from Prof. Daniel J. Bernstein, PhD, the author of DJBDNS, quite entertaining.
http://cr.yp.to/djbdns/tcp.html#why (2003-01-16)
When are TCP queries sent?
If you're in one of the following situations, you need to configure your DNS server to answer TCP queries:
- You want to publish record sets larger than 512 bytes. (This is almost always a mistake.)
- You want to allow outgoing zone transfers, for example to a third-party server.
- A parent server refuses to delegate a name to you until you set up TCP service.
If you aren't in any of those situations, you have no need to provide TCP service, and you should not set it up. DNS-over-TCP is much slower than DNS-over-UDP and is inherently much more vulnerable to denial-of-service attacks. (This applies to BIND too.)
Note that he omits an explicit mention of DNSSEC; the reason being is that, according to DJB, DNSSEC falls under the "always a mistake" category. See https://cr.yp.to/djbdns/forgery.html for more details. DJB has an alternative standard, called DNSCurve — http://dnscurve.org/ — which has already been independently adopted by some providers (like OpenDNS). Of interest: https://security.stackexchange.com/questions/45770/if-dnssec-is-so-questionable-why-is-it-ahead-of-dnscurve-in-adoption.
Note that if the above documentation on DJBDNS setup is any indication of its features, it appears that it only supports AXFR for TCP. As many providers still use DJBDNS, they would thus unlikely to support DNS over TCP without extra efforts.
P.S. Note that DJB does, in fact, practice what he preaches. His own servers, (1), do run DNSCurve, (2), don't properly answer TCP. Only the +notcp
would succeed (which is default):
% dig +trace @ordns.he.net +notcp cr.yp.to | tail
yp.to. 86400 IN NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.yp.to.
yp.to. 86400 IN NS uz5jmyqz3gz2bhnuzg0rr0cml9u8pntyhn2jhtqn04yt3sm5h235c1.yp.to.
;; Received 300 bytes from 216.74.32.100#53(tonic.to) in 151 ms
cr.yp.to. 600 IN A 131.155.70.11
cr.yp.to. 600 IN A 131.155.70.13
yp.to. 3600 IN NS uz5jmyqz3gz2bhnuzg0rr0cml9u8pntyhn2jhtqn04yt3sm5h235c1.yp.to.
yp.to. 3600 IN NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.yp.to.
;; Received 244 bytes from 131.155.70.13#53(uz5jmyqz3gz2bhnuzg0rr0cml9u8pntyhn2jhtqn04yt3sm5h235c1.yp.to) in 14 ms
, whereas a +tcp
would fail (apparently with a different error message, depending on which of his servers gets selected):
% dig +trace @ordns.he.net +tcp cr.yp.to | tail
yp.to. 86400 IN NS uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.yp.to.
;; Received 300 bytes from 216.74.32.100#53(tonic.to) in 150 ms
;; Connection to 131.155.71.143#53(uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.yp.to) for cr.yp.to failed: connection refused.
;; communications error to 131.155.70.13#53: end of file
;; Connection to 131.155.71.143#53(uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.yp.to) for cr.yp.to failed: connection refused.
;; communications error to 131.155.70.13#53: end of file
;; Connection to 131.155.71.143#53(uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.yp.to) for cr.yp.to failed: connection refused.
;; communications error to 131.193.32.147#53: end of file
;; connection timed out; no servers could be reached