PSA: dns 2.0 -- a new udns era dawns

The DNS protocol implementation in MirageOS has been around for a very, very long time. The codebase began way back in 2003 and got used in research projects such as Melange (the precursor to MirageOS) and the Main Name System.

Over the years, the ocaml-dns codebase has been refactored many times as we developed new libraries: early versions were moved from a declarative parsing language (lost in the sands of time) over to bitstring and then to the newly developed cstruct and so on. Meanwhile, our overall coding standards and library infrastructure in MirageOS also improved, and the DNS codebase didn’t always keep up.

The DNS interfaces tended to leak exceptions from awkward places, whereas other Mirage libraries have been adopting an explicit approach to error handling to ensure exceptions are indeed exceptional events. The DNS protocol itself has continued to grow many more extensions, and now systems such as LetsEncrypt that can generate TLS certificates via DNS really motivate supporting these.

So it is with enormous pleasure that I recently merged mirage/ocaml-dns#159 into the trunk branch of the DNS repository. This represents a rewrite of the implementation of DNS from the ground up using the same rigorous coding standards first adopted in ocaml-tls, and spearheaded for over two years by @hannes and @cfcs in their udns library. As udns has matured, we recently took the decision for it to merge with the venerable ocaml-dns repository and supplant the old implementation. You can view the odoc of the master branch online.

This means that the dns.2.0.0 package will essentially be udns (which has deliberately not been released to date). The first thing I would like to do is to thank @hannes and @cfcs for their enormous persistence and attention to detail in constructing this new version, and then secondly to issue a call for help and contributions from anyone in the OCaml community who is interested in assisting with missing features that have regressed from the 1.x branch.

The core library is in great shape, so I have created some issues for known missing elements that we can tackle before cutting a dns.2.0.0 release:

If you are a current user of the dns.1.x branch, we would also really like to hear from you about whether the master branch of ocaml-dns is suitable for your use. Please feel free to create new issues about regressions from 1.x, or to make suggestions. If you’re new to DNS and curious to learn more, then do also try to do your own deployment of a DNS server and let us know how it goes!

mirage.io will shortly be running this DNS server as well, of course, and @hannes can no doubt chime in about his own usecases in production with this new codebase over the past few years.

Enjoy!

13 Likes

I don’t quite understand what you mean with TCP server… if you take a look at ns0.robur.io (or ns1.robur.io) or ns1/ns2/ns3.mehnert.org or ns.nqsb.disabled / sn.nqsb.disabled (they’re all running udns), they are already listening on TCP, and if your request (via udp) is too large to fit into 400 bytes, you get a truncated answer (an example would be dig tlsa _letsencrypt._tcp.hannes.nqsb.disabled @ns.nqsb.disabled).

for the motivation behind udns: initially i wanted to write an iterative resolver, but then the “how to configure it” question was raised, and i discovered NSUPDATE, an in-protocol dynamic update mechanism (with authentication), and started to implemented these, together with a server implementation. Afterwards I intended to use let’s encrypt via DNS (since I hate to have to run web servers for let’s encrypt) – thanks to Michele, the ocaml-letsencrypt got me started with the DNS challenge).

nowadays, I store TLS certificates (and signing requests) as TLSA in DNS, have the zone in a git repository that is pushed and pulled by the primary implementation, which NOTIFY secondaries (even the let’s encrypt service is a (hidden) secondary), and transfers zones incrementally.

if you’re interested in server-side unikernels, take a look at GitHub - robur-coop/unikernels: MirageOS unikernels – they contain primary, secondary, primary-git, let’s encrypt, …

what is more to do? there are still some TODO in the code which should be fixed, the test coverage (esp. in server) is not yet optimal, and various DNS extensions (DNSSec, DNS-over-TLS, irmin-storage-in-dns, tcp-over-dns, …) are just not there yet… but in the end, I use and rewrite this stack since some years (first commit was from end of april 2017) – also using the resolver on my laptop :slight_smile:

5 Likes

further preparation for a release are upper bounds PRed to opam-repository…

2 Likes