1. Home
  2. The trailing dot in domain names, a detail that is often poorly managed

A view on Manhattan by night
A view on Manhattan by night

While inspecting traffic logs for my website in redirection.io recently, I noticed several requests logged on the lacot.org. domain name. Did you see the final trailing dot in the hostname? I first thought it was a bug in the logging platform, but I was surprised to learn that it is perfectly possible to add a dot at the end of a domain name. To be more precise, I already knew about trailing dots in domain names, but never thought about checking how it was handled in web browers and in HTTP traffic.

Wait, what? I can put a dot at the end of my domain names?

Short anwser: Yes, you can. The domain name system (DNS) allows you to put a dot at the end of a domain name. This is not a common practice (at least in the "Web browsing" world), but it is possible. Adding a dot at the end of a domain name turns it into a specific notation that is called the "Fully Qualified Domain Name" (FQDN). A FQDN is a domain name that specifies its exact location in the tree hierarchy of the Domain Name System (DNS). It specifies all domain levels, including the top-level domain and the root zone.

A website domain, eg. www.example.com, is made of several parts:

The syntax www.example.com is the most commonly used on the Web, and it relies on the fact that your local DNS resolver will resolve com as the top level domain. If you need or want to be more explicit, you can add a trailing dot, eg. www.example.com.. In this case, the dot at the end of the domain name represents the root of the DNS hierarchy, ie. the top-level DNS zone in the hierarchical tree that is served by the root name servers. Therefore, using the FQDN syntax disambiguishes the fact that the request is for www.example.com., not for an other address. For this request, the IP address will be resolved as the one configured in the A record by the owner of the example.com. domain name, and it will not use any other configuration that could have been setup in any other local network DNS server.

To summarize:

What happens when there's no trainling dot at the end of a domain name?

With the syntax example.com, the domain name is not in its Fully Qualified form. Imagine a company local network area - say, acme.com - in which several web services are hosted, with different hostnames. It is perfectly possible to omit the LAN domain when adressing such services: ssh audio will work the same way like ssh audio.acme.com.

And you get it: setting up a machine with the hostname admin.finance.example.com will make its service locally reachable at both the adresses http://admin.finance.example.com or http://admin.finance. In the meantime, ædmin.finance also exists as a fully qualified domain name (ie. ædmin.finance., not an alias for admin.finance.example.com.).

In other words, a customer on this local network who would type "http://admin.finance" in their web browser would be redirected to the service hosted on the machine with the hostname admin.finance.example.com. This is because the local DNS resolver will append the local domain name to the hostname, and will resolve the IP address of the machine. This is a common practice in local networks, and it is called "search domain".

So, there's a possible confusion here: example.com and example.com. are not the same thing. The first one is a domain name, the second one is a fully qualified domain name.

Most of the time however, a domain name holder will not make a difference between the two. Also network administrators usually take care not to setup machines with names that could be confused with a domain name. But it is possible to have a machine with a name that is the same as a domain name, and in this case, the trailing dot will make the difference.

So, how to handle trailing dots in domain names?

We are left in a sort of dilema here:

The usual way to handle this would be to setup a redirect from one to the other. But which way?

Actually, a good solution might be to serve a static page on the FQDN, that would perform a client-side fetch request to the non-FQDN domain name, check if the response originates from the real website, and then redirect the user to the non-FQDN domain name if it is the case. If it is not the case, it could load the content to display from the FQDN domain name (with a cookie or some other way to avoid duplicate content issues). This would however be a bit tricky to setup, and would require some JavaScript code to be executed on the client side.

Architectural choices are always a tradoff, and sometimes you are left to choose the least bad solution. For this reason and for simplicity sake, I chose to setup a redirect from the FQDN to the non-FQDN domain name. In my opinion, it is the most common and user-friendly way to handle this case. Yet it will let some users unable to reach my real website, if:

  1. they connect from a local network
  2. with a search domain configured
  3. and a machine name that is identical to my domain name (lacot.org)

This is a rare case, and I think it is acceptable in this context, though it could lead to some confusion for users (or even make the way easier for phishing attacks!). I may not go with the same advice for a banking website, for example :-)

However, the "redirect everything" solution has also major advantages (see the "Browsers behavior" chapter below).

How do Web servers handle trailing dots in domain names?

There's no easy answer to this question, as it depends on the web server or reverse-proxy you are using.

Browsers behavior

Browser do consider that the domain name example.com and example.com. are different. They will not share the same cache, and they will not share the same memory spaces within the browser. This is a normal behavior, as they're different hostnames, but it can also lead to some unexpected behaviors. For example, the user may not expect to be logged out when switching from one domain name to the other. Here are the impacts of serving a content on both a domain name and its FQDN version:

So, to summarize the risks associated with an improper handling of trailing dots in domain names, you could face potential costs, security, SEO, and user experience issues.

How do large websites handle things?

Here is a summary of how several large websites handle trailing dots in domain names. It is based on a quick test I made with Symfony's HttpCLient, and it may not be perfectly exhaustive.

Domain http https http + www https + www Remarks
amazon.com. 301 400 301 200 😡 The root domain is not reachable in https. The www version in https serves content, but with a separate session from https://www.amazon.com, which means that you can be connected on both with separate accounts at the same time.
apple.com. 404 404 301 200 😡 The root domain is not reachable in both http and https. The www version in https serves content, but no asset is loaded as their URL violates the Content-Security-Policy of the website.
bbc.com. 301 301 302 200 The www version in https serves content instead of redirecting to https://www.bbc.com.
bing.com. 400 400 200 or 307 SSL error and 200 😡 The root domain returns an HTTP error. The www version in https does not have a valid certificate. For clients that do not check the certificate, a response is served with a 200 status code instead of redirecting to https://www.bing.com.
cloudflare.com. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.cloudflare.com.
developer.mozilla.org. 301 or 307 SSL error N/A N/A 😡 The www. version does not exist. The root domain in http redirects to the non-FQDN domain name or to the https version of the FQDN, depending on whether the client supports HSTS or not. The root domain in https does not have a valid certificate.
duckduckgo.com. 301 200 301 301 The root domain in https serves content, but no asset is loaded as their URL violates the Content-Security-Policy of the website.
ebay.com. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.ebay.com.
free.fr. 301 301 301 302
github.com. 301 301 301 301
gitlab.com. 301 302 301 302
gnu.org. 301 301 200 or 307 200 The www version in https serves content instead of redirecting to https://www.gnu.org, or it redirects to the https version of the FQDN if the client supports HSTS. The www version in https serves content instead of redirecting to https://www.gnu.org.
google.com. 301 301 301 301
instagram.com. 301 400 301 400 😡 The http versions are redirected to the https versions, but these return a 400 error (with, strangely, an HTML content that states "5xx Server Error" 🙃).
jolicode.com. 301 301 301 301
lacot.org. 301 301 301 301
lemonde.fr. 301 301 301 200 https://www.lemonde.fr./ servers content instead of redirecting to https://www.lemonde.fr/.
linkedin.com. 400 or 307 400 404 or 307 404 😡 The root domain returns a 400 error. The www version in https returns a 404 error.
medium.com. 301 404 301 301 😡 The root domain in https returns a 404 error, while all other configurations redirect to https://medium.com.
microsoft.com. 404 or 307 SSL error 302 302 😡 The root domain returns a 404 error. The SSL certificate is invalid for the https version of the root domain.
mozilla.org. 302 SSL error 301 200 😡 The root domain in https does not have a valid certificate. The www version in https serves content instead of redirecting to https://www.mozilla.org.
netflix.com. 301 301 301 301
nytimes.com. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.nytimes.com.
ovhcloud.com. 301 SSL error and 503 400 400 😡 The SSL certificate is invalid for the https version of the root and the www domains. Additionally, the http version of the www domain returns a 400 error.
php.net. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.php.net.
reddit.com. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.reddit.com.
stackoverflow.com. 301 400 301 400 😡 The https versions return a 400 error.
symfony.com. 301 or 307 502 301 or 307 502 😡 The https versions return a 502 error.
twitter.com. 404 404 404 404 😡 Twitter (and X) does not work with a Fully Qualified Domain Name.
ubuntu.com. 302 SSL error and 200 302 SSL error and 200 😡 The https versions do not have a valid SSL certificate. For clients that do not check the certificate, a response is served with a 200 status code instead of redirecting to https://ubuntu.com
vercel.com. 308 SSL error and 200 308 SSL error and 308 😡 The https versions do not have a valid SSL certificate. For clients that do not check the certificate, a response is served with a 200 status code instead of redirecting to https://vercel.com.
w3.org. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.w3.org.
wikipedia.org. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.wikipedia.org.
wordpress.com. 301 301 301 301
xkcd.com. 301 200 301 200 The https versions serve content instead of redirecting to https://xkcd.com.
youtube.com. 301 301 301 301
zend.com. 301 301 301 200 The www version in https serves content instead of redirecting to https://www.zend.com.

This table gives some insights on how trailing dots in domain names are supported. Basically, there are often mistakes:

Recommendations

As a conclusion, even if it is not a silver-bullet solution for all cases, here are some recommendations on how to handle trailing dots in domain names:

I implemented the trailing-dot domain name redirection using the "Redirect a Fully Qualified Domain" redirection.io recipe, but you're free to go your way :-)

written on