Domains, DNS, and SSL, oh my!

I recently helped a friend navigate the process of untangling himself from his registrar’s expensive SSL offerings, and wrote up the following to help illustrate what the pieces are and how they fit together. He asked that I publish this somewhere that others could benefit from it, so here it is!

Registrars, DNS, Servers, and SSL.

  1. Registrars are gatekeepers for registering “names”, which are subdomains on top-level domains (TLDs). There’s something called the “internet root nameservers” which are the bottom of the turtle stack. They say “this so and so can answer queries for this particular TLD” like .com and .net and .mobile and whatever. There are 13 root servers on the internet (actually served by hundreds of machines, but logically, there are 13), and they currently serve about 730 TLDs. All the software in the world that uses DNS knows about these 13 root servers (or delegates that knowledge). This is known as the DNS Root Zone.

    The root servers are administrated by ICANN, and Domain Name Registrars (like GoDaddy and Namecheap) contract with ICANN to provide domain registration services, so Namecheap says “I want to be able to sell domains on the .com TLD”, they pay ICANN, ICANN lets the root servers know about Namecheap as a valid resolver of .com domains.

    Registrars’ primary function is to sell registration of domains on the TLDs they contract on. They may provide other services, but fundamentally you pay them money, they agree to resolve DNS lookups for NS (nameserver) queries for yourname.com to a nameserver of your choosing to figure out where it should actually go.

    This is the point at which your NECESSARY engagement with them is at an end. Most registrars sell a bunch of other services, like hosting, SSL, and mail. None of this is required (but may be convenient, if often overpriced).

  2. Once I, as a requesting client, have discovered the nameserver for a domain, I send a query to that nameserver for the record I want. If you want to discover the webserver IP address for a name, you send a query for an A record. If you want the mailserver, you send a query for the MX record. So on and so forth.

    The nameserver responds with an IP address to the querying client.

  3. The client can make a request of the kind and shape of its choosing to the IP address. If you know the IP address, you don’t have to go through the whole rigamarole, but nobody wants to hand out “please visit 152.43.20.221/~mysite/public/ for more information” on their business cards.

  4. So, SSL. SSL is used during step 3, usually by clients making HTTP requests (which are used for serving web pages). It’s a way to validate that the IP you’re talking to actually is authorized to respond to requests for yourname.com, and it allows for the encryption of traffic in a way that both ends can understand. Clients send a request to an IP, but they also include a Host: yourname.com header which indicates “this request was made because a client wanted yourname.com”, which lets the server do some routing (in case multiple domains are hosted on one IP) and lets it decide what cert to respond with (the one that matches the request for that domain)

  5. To validate an SSL certificate, your client has to know about a certificate authority that has signed the certificate you receive from the server. CAs can be thought of as notaries public. Browsers come with a list of trusted CAs (LetsEncrypt is one). If a random website hands you a cert, you have no idea if they made it up or not. But if the cert you receive for a given domain is cryptographically signed as valid by a CA (notary) you trust, then you can trust that the certificate was issued by someone who owns that domain, because the CA trusts that they own the domain. Many domain name registrars also provide CA services (they get themselves registered as trusted notaries for signing certs).

  6. To get an SSL cert that’s signed as valid by a CA, I therefore have to prove to the CA operator that I do, in fact, have permission to serve traffic on yourname.com. How this proof is established is up to the CA. Some registars do that by requiring that you host your domain registration with them, so they know by lazy virtue of the fact that you’re logged in and that you registered yourname.com that you do in fact have permissions on that name, but there are other ways, too.

    By contrast, LetsEncrypt lets you prove ownership by either

    1. making your website answer to a random challenge they provide, or
    2. making your DNS answer to a random challenge they provide

    Both prove you have control over the domain. This is why it works anywhere with any host, though, because as long as you can provide those challenges you can prove ownership and get your certs signed by them.

  7. The SSL certificate is basically just a binary blob which can be read by computers as a cryptographically-signed claim of “this certificate is for this domain and is good through this date”. Once you HAVE the cert you can install and use it anywhere you want (as along as the name you’re serving under matches what’s on the cert). You don’t have to use a registrar’s hosting services, you don’t have to use their mail services, you can serve that binary blob from any server you want. As long as the client’s expectation (I requested yourname.com and got a certificate for yourname.com) is met, and the certificate is signed as valid by a CA the client trusts, you’re good to go.

A Practical Example

I register my domains through Namecheap, and I tell Namecheap “use these DigitalOcean nameservers for my names”.

$ whois heald.me | grep Name
Domain Name: HEALD.ME
Registrar: NameCheap, Inc.
Name Server: NS1.DIGITALOCEAN.COM
Name Server: NS2.DIGITALOCEAN.COM
Name Server: NS3.DIGITALOCEAN.COM

I configure my DNS at DigitalOcean, which publishes the records I specify on their nameservers. These records include things like:

heald.me.        300  IN      TXT     "v=spf1 include:_spf.protonmail.ch mx ~all"
chris.heald.me.  300  IN      A       178.128.3.212

My DNS is configured to point my names to my DigitalOcean servers (178.128.3.212).

When my client goes to look up my DNS, it goes to the root servers (or to a server that has information from the root servers cached) and figures out where we’re going. Here’s a full verbose trace of a query for “the A record for chris.heald.me”.

dig IN A heald.me +trace

; <<>> DiG 9.16.15-Ubuntu <<>> IN A heald.me +trace
;; global options: +cmd
.                       12681   IN      NS      f.root-servers.net.
.                       12681   IN      NS      g.root-servers.net.
.                       12681   IN      NS      h.root-servers.net.
.                       12681   IN      NS      i.root-servers.net.
.                       12681   IN      NS      j.root-servers.net.
.                       12681   IN      NS      k.root-servers.net.
.                       12681   IN      NS      l.root-servers.net.
.                       12681   IN      NS      m.root-servers.net.
.                       12681   IN      NS      a.root-servers.net.
.                       12681   IN      NS      b.root-servers.net.
.                       12681   IN      NS      c.root-servers.net.
.                       12681   IN      NS      d.root-servers.net.
.                       12681   IN      NS      e.root-servers.net.
;; Received 525 bytes from 192.168.4.248#53(192.168.4.248) in 63 ms

me.                     172800  IN      NS      a0.nic.me.
me.                     172800  IN      NS      a2.nic.me.
me.                     172800  IN      NS      b0.nic.me.
me.                     172800  IN      NS      b2.nic.me.
me.                     172800  IN      NS      c0.nic.me.
me.                     86400   IN      DS      45352 8 2
;; Received 681 bytes from 192.203.230.10#53(e.root-servers.net) in 9 ms

Here’s the root server query. My computer talks to my upstream DNS servers, which are preconfigured to know about the root servers. It went to the root servers and said “I need to know where to find information about .me domains”. It learns that this a set of servers at nic.me.

These records exist because nic.me is contracted with ICANN to provide .me registrations.

heald.me.               86400   IN      NS      ns2.digitalocean.com.
heald.me.               86400   IN      NS      ns3.digitalocean.com.
heald.me.               86400   IN      NS      ns1.digitalocean.com.
;; Received 606 bytes from 199.253.60.1#53(b0.nic.me) in 206 ms

It went to b0.nic.me and asked for where to find nameservers for heald.me. b0.nic.me said “Oh, that’s these DigitalOcean servers”.

These records exist because Namecheap is contracted with nic.me and was permitted to write the records for heald.me after I bought the domain through them.

chris.heald.me.         300     IN      A       178.128.3.212
;; Received 53 bytes from 173.245.59.41#53(ns2.digitalocean.com) in 31 ms

Finally, it went to ns.digitalocean.com and said “I need the A record for chris.heald.me” and ns2.digitalocean.com responded “That’s 178.128.3.212.

These records exist because I instructed DigitalOcean to serve them for the domain heald.me via their nameservers.


My DigitalOcean servers are running nginx, which I’ve configured to automatically provision SSL certificates for my names from LetsEncrypt, and which respond to challenges by LetsEncrypt by creating an arbitrary challenge file on demand to be fetched via an HTTP request.

Requests for chris.heald.me go to the root name servers to find out who can serve .me, then delegates down the chain to find who registered heald.me. Namecheap says “I’ve got that one! Go to ns1.digitalocean.com to find out more”.

Your client goes to ns1.digitalocean.com and says “I want the A record for chris.heald.me”, and DO says “that’s 178.128.3.212”.

Your client connects to 178.128.3.212 on port 443 (which is the port for HTTPS by convention) and says “This is an HTTPS request for Host: chris.heald.me”.

My server responds with “Here’s my certificate for *.heald.me”. Your client says “Yup, it’s signed by LetsEncrypt, and I trust LetsEncrypt, so I trust you. And chris.heald.me matches what I asked for, so we can go ahead. Give me what you have for Path: /”

My server responds with HTML content and your browser displays it. Et voila!