DNS over HTTPS for Mikrotik

With everything moving to HTTPS, there’s still one component that gets overlooked - DNS. Most of time lookups are still done via essentially plain-text protocol. And it’s not for the lack of encrypted alternatives as there are at least three different ways of doing it: DNS over HTTPS (DoH), DNS over TLS (DoT), and DNSCrypt. When it comes to Mikrotik, choice narrows a bit and only DNS over HTTPS is supported.

Realistically, DoH is enough. DoT might be a bit more elegant implementation at a lower OSI layer but both clients and public servers seem to prefer DoH due to it’s heavy reliance on HTTPS layer ubiquitous to pretty much any application these days. DNSCrypt never got off the ground and we pretty much can ignore it.

So, today’s task is to set Mikrotik router to use DNS over HTTPS lookups.

To start it all off, we first need to download CA certificate store. And yes, we could skip this step and simply not check certificates but I feel that leaves too much space for man-in-the-middle attach. Downloading one file every few years will not kill anybody.

/tool fetch url=https://curl.se/ca/cacert.pem
      status: finished
       total: 199KiB
    duration: 1s

/certificate import file-name=cacert.pem passphrase=""
     certificates-imported: 128``
     private-keys-imported: 0
            files-imported: 1
       decryption-failures: 0
  keys-with-no-certificate: 0

With certificates in place, we get to setup DNS over HTTPs.

/ip dns
set use-doh-server=^^https://cloudflare-dns.com/dns-query^^ verify-doh-cert=yes

And that’s it. To verify it working, you can visit https://1.1.1.1/help and look for “Using DNS over HTTPS (DoH)” line.


That said, one could notice one glaring issue - we still have our original DNS servers listed. And I personally do this intentionally as a fallback method. However, that does leak a bit of information and, if someone blocks our DNS resolver, can force plain-text legacy lookups.

To harden system a bit, first we need to add static entries for DNS IPs (you can find them out with nslookup cloudflare-dns.com).

/ip dns static
add name=cloudflare-dns.com address=^^2606:4700::6810:f8f9^^
add name=cloudflare-dns.com address=^^2606:4700::6810:f9f9^^
add name=cloudflare-dns.com address=^^104.16.248.249^^
add name=cloudflare-dns.com address=^^104.16.249.249^^

With static entries in place, we can clear the legacy DNS servers.

/ip dns
set servers=""

And, if we’re using DHCP, we need to disregard DNS IPs provided by upstream too.

/ip dhcp-client
set 0 use-peer-dns=no

/ipv6 dhcp-client
set 0 use-peer-dns=no

And now all DNS lookups done by router are done using DoH and nothing else.