The status of putting a '.' at the end of domain names

September 1, 2024

A variety of things that interact with DNS interpret the host or domain name 'host.domain.' (with a '.' at the end) as the same as the fully qualified name 'host.domain'; for example this appears in web browsers and web servers. At this point one might wonder whether this is an official thing in DNS or merely a common convention and practice. The answer is somewhat mixed.

In the DNS wire protocol, initially described in RFC 1035, we can read this (in section 3.1):

Domain names in messages are expressed in terms of a sequence of labels. Each label is represented as a one octet length field followed by that number of octets. Since every domain name ends with the null label of the root, a domain name is terminated by a length byte of zero. [...]

DNS has a 'root', which all DNS queries (theoretically) start from, and a set of DNS servers, the root nameservers, that answer the initial queries that tell you what the DNS servers are for the top level domain is (such as the '.edu' or the '.ca' DNS servers). In the wire format, this root is explicitly represented as a 'null label', with zero length (instead of being implicit). In the DNS wire format, all domain names are fully qualified (and aren't represented as plain text).

RFC 1035 also defines a textual format to represent DNS information, Master files. When processing these files there is usually an 'origin', and textual domain names may be relative to that origin or absolute. The RFC says:

[...] Domain names that end in a dot are called absolute, and are taken as complete. Domain names which do not end in a dot are called relative; the actual domain name is the concatenation of the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as an argument to the master file loading routine. A relative name is an error when no origin is available.

So in textual DNS data that follows RFC 1035's format, 'host.domain.' is how you specify an absolute (fully qualified) DNS name, as opposed to one that is under the current origin. Bind uses this format (or something derived from it, here in 2024 I don't know if it's strictly RF 1035 compliant any more), and in hand-maintained Bind format zone files you can find lots of use of both relative and absolute domain names.

DNS data doesn't have to be represented in text in RFC 1035 form (and doing so has some traps), either for use by DNS servers or for use by programs who do things like look up domain names. However, it's not quite accurate to say that 'host.domain.' is only a convention. A variety of things use a more or less RFC 1035 format, and in those things a terminal '.' means an absolute name because that's how RFC 1035 says to interpret and represent it.

Since RFC 1035 uses a '.' at the end of a domain name to mean a fully qualified domain name, it's become customary for code to accept one even if the code already only deals with fully qualified names (for example, DNS lookup libraries). Every program that accepts or reports this format creates more pressure on other programs to accept it.

(It's also useful as a widely understood signal that the textual domain name returned through some API is fully qualified. This may be part of why Go's net package consistently returns results from various sorts of name resolutions with a terminating '.', including in things like looking up the name(s) of IP addresses.)

At the same time, this syntax for fully qualified domain names is explicitly not accepted in certain contexts that have their own requirements. One example is in email addresses, where 'user@some.domain.' is almost invariably going to be rejected by mail systems as a syntax error.


Comments on this page:

From 193.219.181.219 at 2024-09-02 08:14:52:

even if the code already only deals with fully qualified names (for example, DNS lookup libraries).

That's not necessarily true, as honoring the system's domain search suffix is often part of such libraries – even in the specific example of dnspython, hwose `dns.resolver.resolve()` takes a `search=` boolean (I believe it actually used to default to True), and similarly its `dns.name.from_text()` takes an `origin=` parameter.

I don't really agree with reducing it down to "peer pressure". Any API that might be used with user input will often find it useful to accept (or at least, not specifically reject) dot-qualified names, whether it's to handle edge cases like `foo.` deliberately specifying a TLD or a local hostname (NetBIOS and LLMNR names didn't have any domain suffix), or whether it's to handle the Windows system-wide resolver which sometimes attempts to qualify even multiple-dot names (becoming `utcc.utoronto.ca.xfinity.com.`, etc).

Yeah, as the other commenter said, I don’t think it has “become customary”, I think it always was. The main exception was always email addresses which never accepted a trailing dot, probably because the syntax for mail domains predates the DNS — RFC 822 vs RFC 883, roughly. But at the same time trailing dots have always been an ugly edge case that wasn’t supposed to matter. Web software has usually forgotten about trailing dots, and never properly addressed the resulting edge-case issues. The discussions on the topic will keep coming back in the same way they have for the last 25 years because it’s disproportionately hard to fix: it spans multiple standards organizations and software at almost every level in the stack.

Written on 01 September 2024.
« In practice, abstractions hide their underlying details
Apache's odd behavior for requests with a domain with a dot at the end »

Page tools: View Source, View Normal.
Search:
Login: Password:

Last modified: Sun Sep 1 22:29:22 2024
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.