25

According to domain name specifications RFC 1035:

2.3.4. Size limits

names 255 octets or less

According to the SMTP RFC 5321:

4.5.3.1.2. Domain

The maximum total length of a domain name or number is 255 octets.

The RFCs are thus consistent and clear in my opinion.

However, some people claim it is 254 because of the possible presence of a dot at the end, although there is no mention of such dot in the RFCs 1.

Other people claim it is 253 for weird reason like the presence of a prefix string length byte and the trailing ’\0’ of C strings 2,3,4.

What is the maximum domain byte length ?

2
  • 1
    The trailing dot is used by DNS to make sure there is a clear differentation between relative and absolute domains. See RFC1304 (datatracker.ietf.org/doc/html/rfc1034 section 3.1). However, it is referred to as 'leading to a printed dot', so its unclear to me if this means it is or isnt part of the 255 octets. It at least explains what the trailing dot is.
    – Silbee
    Commented May 27 at 10:52
  • 2
    Beware that whatever the spec might be, it is common for implementations to have bugs (i.e. not match the spec). So even if you get a solid answer about what the spec says here, don't discount people telling you about exceptions -- they may have intimate and valuable knowledge of a buggy implementation that you nevertheless would like to work with your domain! Commented May 28 at 17:18

1 Answer 1

36

It depends on the context. Your RFCs list different limits because they talk about different things – the SMTP limit of 255 is specifically for the domain-part of local@domain email addresses and has little, if anything, to do with the limit set by the DNS protocol.

(This is in part because SMTP predates DNS by years – it was designed when HOSTS.TXT was still in use on the ARPANET (see RFC 810/811); and it used to exist in a world where email was trans­ported across 10 different networks so that an SMTP email address domain might have not been an Internet domain at all.)

Prerequisites

To start with an important detail:

However, some people claim it is 254 because of the possible presence of a dot at the end, although there is no mention of such dot in the RFCs

There is. RFC 1034 section 3.1:

When a user needs to type a domain name, the length of each label is
omitted and the labels are separated by dots (".").  Since a complete
domain name ends with the root label, this leads to a printed form which
ends in a dot.  We use this property to distinguish between:

   - a character string which represents a complete domain name
     (often called "absolute").  For example, "poneria.ISI.EDU."

   - a character string that represents the starting labels of a
     domain name which is incomplete, and should be completed by
     local software using knowledge of the local domain (often
     called "relative").  For example, "poneria" used in the
     ISI.EDU domain.

Relative names are either taken relative to a well known origin, or to a
list of domains used as a search list.  Relative names appear mostly at
the user interface, where their interpretation varies from
implementation to implementation, and in master files, where they are
relative to a single origin domain name.  The most common interpretation
uses the root "." as either the single origin or as one of the members
of the search list, so a multi-label relative name is often one where
the trailing dot has been omitted to save typing.

So per specification, www.google.com is not the full domain name – www.google.com. is – and the trailing dot is merely "omitted to save typing", but is very much valid and has a specific purpose. You add a trailing dot to tell the system that a local domain should not be appended.

  • As a practical example, ICANN used to allow top-level domains to have "host" records. For example, the tk. TLD had a website at http://tk./ – which had to be written with the trailing dot, otherwise your system would look up tk.dlink.lan or whatever.

  • The RFC uses a single-label example, and many assume that all systems treat any multi-component domain name as already absolute, but that is not always the case – Windows, in particular, does not limit itself like that.

    Instead, if a DNS search suffix is configured in Windows, it will be applied to any non-absolute name even if it has multiple components. For example, if corp.example.com is your system's domain, then www.google.com will be first attempted as www.google.com.corp.example.com. and only then as www.google.com..

    In this situation, you would explicitly add the trailing dot to your input to prevent the OS from automatically suffixing it with the local domain.

The other RFC that you were reading – RFC 1035 – does not talk about the "trailing dot" because it mostly concerns itself with the network protocol, while the user-facing details are in RFC 1034.

But the text representation is not where the actual length limit comes from.

The actual limits

The real limit is "255 octets or less" when applied to the domain name as it is represented in DNS network (packet) format, which doesn't use 'dot' separators – it indeed uses a length-prefix byte – and the equivalent of the "trailing dot" is not optional.

In this format each string is prefixed with a length byte, and the entire list is terminated by a 0-byte string. To quote RFC 1035:

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.  The
high order two bits of every length octet must be zero, and the
remaining six bits of the length field limit the label to 63 octets or
less.

For example, www.google.com would become:

14 characters:    www.google.com

Interpreted as:   [3] "www"
                  [6] "google"
                  [3] "com"
                  [0] ""          ("null label of the root")

16 bytes:         <0x03> w w w <0x06> g o o g l e <0x03> c o m <0x00>

(The trailing 0x00 byte here has nothing to do with C strings; in a way it's the complete opposite – the format is much more like a series of Pascal-strings – but really it is not related to any programming language at all. It is specifically the way domain names are transferred in the network protocol.)

So according to the same RFC, the limit for domain names in this specific form is 255 bytes:

To simplify implementations, the total length of a domain name (i.e.,
label octets and label length octets) is restricted to 255 octets or
less.

It happens that the binary (network) representation is almost always¹ two bytes longer than the commonly used text representation (i.e. without the trailing dot). So if a domain name is limited to 255 octets on the wire, it is therefore limited to 253 ASCII characters in text form (plus optional trailing dot as the 254th character).

In other words, all three numbers are correct in their own right – but they are often "claimed" without any context to interpret them with; 255 is correct for the packet format, 254 is correct for the ASCII format with trailing dot (absolute name), and 253 is correct for the "conventional" ASCII format without trailing dot.

¹ (Unless something like \. is present, which is one octet in binary form but represented as two in text – but that's extremely rare in practice; the only time you'll see this is when looking at the SOA "responsible person" field. If you're writing a DNS library, you must account for this, but otherwise you can ignore it.)


Since your module accepts domain names in ASCII format, it should:

  1. Allow at most one trailing dot – best to either always add or always strip it before continuing validation (for consistency).

  2. Allow at most 254 bytes if trailing dot is present, or at most 253 bytes if it's removed.

  3. Merge most of the "top level domain validity" checks into the regular "label" checks, as the basic rules are exactly the same for every label no matter if it's first or last or in the middle.

    (While there do exist additional rules for TLDs, they aren't set by protocol – they are set by policy by ICANN as the maintainer of the root zone which defines TLDs. So while it's reasonable to have e.g. a "begins with a digit" rule for TLDs, it should be kept separate.)

  4. Have a mode that relaxes the "allowed characters" rule. Domain names in general may contain any character – only domain names that are used as hostnames have stronger restrictions, and those come from them being "used as hostnames" (i.e. for A/AAAA lookup), not from their being "domain names".

    At DNS level, non-"hostname" domain names are allowed to contain almost anything – e.g. they commonly contain characters like _ (which are practically mandatory for SRV records; _minecraft._tcp.example.com is a typical example) – so at the very minimum, domain name validation needs to distinguish between "hostname (no underscore)" and "non-hostname (underscore OK)" as different contexts.

10
  • 1
    For example, take any DNS client and have it query test/test.nullroute.lt or test\.test.nullroute.lt – e.g. nslookup -q=ANY test\.test.nullroute.lt or Python's dns.resolver.query("test/test.nullroute.lt", "TXT").rrset or dns.name.from_text("test\\.test.nullroute.lt").labels. It's perfectly reasonable to disallow this in most cases, e.g. you'd never see a legitimate SRV or PTR record having a slash in its name – but the point was that the restrictions are context-dependent, and not inherent in DNS protocol. Commented May 27 at 15:19
  • 1
    Hence the recommendation to have, at least, a lax mode that allows _ for "subdomains" or something (as there are plenty of SRV/TXT/CNAMEs with it) and a stricter mode that disallows it for "hostnames". Commented May 27 at 15:23
  • 1
    Regarding your bullet point on tk, ICANN still do, http://ai works.
    – JoL
    Commented May 27 at 20:05
  • 1
    @chmike Re: non-ASCII names see Internationalized Domain Name
    – grahamj42
    Commented May 27 at 21:20
  • 1
    The advent of unlimited gTLDs in general, and Google's .dev in particular, has really put a crimp in the "global names properly end in a dot" story. Anything might be a valid global name tomorrow, even if it isn't today, and people like browser vendors (i.e. Google again) consider local names shadowing global names to be a "hijacking opportunity" rather than a feature. Because nobody writes "real" FQDNs in URLs.
    – hobbs
    Commented May 28 at 20:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .