Force forwarder DNS requests to TCP mode

16,112

Solution 1

First, I would not call that an error, just an informational message.

Second, DNS servers will always answer UDP queries (BIND at least, I cannot find options to disable UDP) and clients will always (?) try to send a UDP query first (for example there are no options in resolv.conf to change that nor in the JVM) - if they fit in a UDP packet (requests usually do)

If you have a specific use case, you can specify to use TCP, e.g. in shell script use 'dig +tcp' or 'host -T' for resolution, and you can use system calls 'sethostent/gethostbyname/endhostent' (see man page) to force TCP in other cases.

If you really want to try and block UDP, the only option I can see is with an iptable rule, but I am not sure that that set up would work. I expect that DNS resolution would simply fail.

Solution 2

Your BIND server should be using EDNS (see RFC 6891) to allow UDP packets longer than 512 bytes.

options {
    edns-udp-size 4096;
    max-udp-size 4096;
};

This should permit your large NS set to be retrieved over UDP, without requiring the overhead of a TCP connection for other smaller queries.

Note however that these are actually the default values. If EDNS isn't being used, either something is blocking it, or the servers receiving the EDNS options aren't supporting it.

Also, note that host doesn't support EDNS. It's perfectly possible that your forwarder -> server queries are already using EDNS, and you just can't see it when you try with your local client.

Try dig +bufsize=4096 @server hostname A instead of using host.

Share:
16,112

Related videos on Youtube

Nils
Author by

Nils

I studied information science and did computers from the old Commodore VC-20 onwards. I started during study as pc-admin for DOS, Windows, WfW and all related software and hardware stuff. Later I switched over to servers, starting with linux-samba and NT 3.5/4.0. My first job made me a Solaris admin in a huge company with over 500 solaris servers. There I got every day a new interesting problem that I have never encountered before. My next job brought me into project management and later back to system administration - mainly Linux. It was frustrating to manage a project when you knew that doing the admin`s job yourselv would have the current step finished in less than 30 minutes...

Updated on September 18, 2022

Comments

  • Nils
    Nils almost 2 years

    I have set up a DNS-server on SLES10 (currently bind 9.6) on a multi-homed server. This server can be queried from all internal networks and delivers answers for all internal networks. We have two separate DNS "master" zones. Each of these zones is being served by a number of authoritative Windows-DNS-servers.

    Now my linux-server is a secondary DNS server for one of these zones (private internal zone) and acting as forwarder for the other zone (public internal zone).

    Until recently this setup worked without problems. Now I get - upon querying the public internal zone (e.g. by the host command on a linux client) the error-message

    ;; Truncated, retrying in TCP mode

    a wireshark-dump revealed the cause of this: The first query goes out in UDP mode, the answer does not fit into UDP (due to the longish list of authoritative NS), then it is retried in TCP mode, delivering the right answer.

    Now the question: Can I configure my bind to query the forwarders in TCP mode without trying UDP first?

    Update: Trying my hand on ASCII-art...

    +--------------+   +--------------+   +-----------------+
    | W2K8R2 DNS   |   | SLES 10 DNS  |   | W2K8R2 DNS      |
    | Zone private +---+ All internal +---+ Zone public     |
    | internal 2x  |   |   Zones      |   | internal 30+ x  |
    +--------------+   +-+----------+-+   +-----------------+
                         |          |
                      +--+---+   +--+---+
                      |Client|   |Client|
                      +------+   +------+
    
    • Alnitak
      Alnitak over 12 years
      a small diagram of this would be useful - I'm struggling to figure out which server is which from your description.
    • Nils
      Nils over 12 years
      The clients request via SLES10 the entries from zone public internal. The zone private internal does not suffer - as there are only 2 NS entries there.
    • Alnitak
      Alnitak over 12 years
      and the clients are just plain stub resolvers?
    • Alnitak
      Alnitak over 12 years
      suggest you add minimal-responses: yes to the BIND config on SLES 10 - it may reduce the response sizes. In any event, most normal queries won't exceed the 512 byte limit.
  • Alnitak
    Alnitak over 12 years
    there's nominally a performance benefit from knowing a priori that the UDP query will fail, and trying over TCP first. See RFC 5966 for some discussion of that.
  • Nils
    Nils over 12 years
    @Alnitak and I would like to get that benefit.
  • Alnitak
    Alnitak over 12 years
    @Nils so we need to figure out why EDNS apparently isn't working...
  • Nils
    Nils over 12 years
    Who should be using this? Propably both my server and my forwarders from zone "public internal"?
  • Nils
    Nils over 12 years
    I have no special use case - the clients will use their resolver library - but each request and each answer will go over the network twice - I don`t like that.
  • Nils
    Nils over 12 years
    What is the sense of sending the complete list of NS in the answer anyway?
  • Alnitak
    Alnitak over 12 years
    @Nils the DNS protocol requires that the complete set of entries matching the same (QNAME, QTYPE and QCLASS) tuple are indivisible (aka an "RRset")
  • Nils
    Nils over 12 years
    can you please point me to the RFC regarding this RRset?
  • Alnitak
    Alnitak over 12 years
    I can't quote chapter and verse, it might be in RFC 1034 / 5 somewhere. If you search for "RRset indivisible" on Google you'll find stuff in RFC 5507 about it, although that's not where it's actually specified.
  • Dan Andreatta
    Dan Andreatta over 12 years
    @Nils, the issue is that the client decide UDP/TCP, but the server known the size of the answer.
  • Dan Andreatta
    Dan Andreatta over 12 years
    Actaully host uses the standard resolver library, and on my workstation it supports EDNS0. To test if the requests specifies EDNS0, run 'tcpdump -x port 53' and the hex dump should contain (towards the end, in the additional section) the sequence 0029 1000 0000 8000 0000, which is the binary representation of the OPT RR.
  • Alnitak
    Alnitak over 12 years
    @DanAndreatta On what OS? On MacOS X, the standard resolver library does support EDNS0, but only when told to by setting RES_USE_EDNS0 in the _res.options structure.
  • JdeBP
    JdeBP over 12 years
    The question says Linux for the machine running host, requiring option edns0 to be in resolv.conf.
  • ysdx
    ysdx over 9 years
    GNU libc has a (non documented) option for forcing TCP for DNS resolution: its use-vc (in res_init.c). It can be set with options use-vc in resolv.conf or in the environment: RES_OPTIONS="set-vc".
  • Alnitak
    Alnitak over 3 years
    @gidoBOSSftw5731 I've rejected your edit because at this point the so-called "flag day" change to recommended EDNS buffer sizes to avoid fragmentation are simply advisory, and have not been encoded in any DNS-related RFC.