Two years ago, Afnic announced the open-source release of IBDNS, which stands for Intentionally Broken DNS. It is a tool for testing the robustness of DNS clients when faced with erroneous behaviour or malformed packets from authoritative name servers.
In the time since the announcement, the tool has reached version 0.5.0, incorporating several major changes and drawing on two years of development and operational experience. Over the past two years, IBDNS has added several new features, the most significant of which is a new configuration file format incorporating a domain-specific language. It has also received a number of bug fixes and seen its documentation expanded using a technical documentation methodology. It has even gained a mascot.
Inteview with Marc van der Wal.
Image description: A black cat with a red nose innocently knocks over the stacked letters “DNS” with its paw. The small tower becomes unbalanced. This is the chosen mascot for IBDNS.
What does the new domain-specific language-based configuration system offer?
In earlier versions of IBDNS, behaviour could only be configured according to the queried domain name. This proved to be insufficient: we needed to trigger faulty behaviour when an incoming query met specific criteria that went beyond just the queried domain name.
That’s why version 0.5.0 introduces a new configuration file format. It allows for expressing rules: if an incoming DNS query matches one or more criteria, expressed in a domain-specific language, the server shall trigger some corresponding failure mode.
For example, the rule below, which could not be expressed in the previous configuration system, stipulates that for all queries whose queried name (“QNAME”) is breaks-on-edns.test or one of its subdomains and which contain an EDNS option of type number 65,500, the server shall not respond to EDNS queries.
[[rule]] if = "$qname @= breaks-on-edns.test and $edns.has_option(65500)" edns_mode = "drop"
In short, one of the goals of IBDNS is the ability to reproduce bugs that have been observed in other authoritative name servers on demand. This new system provides much finer control over IBDNS’s behaviour, allowing it to simulate these faulty servers much more faithfully.
What is the Diátaxis approach, and why is the IBDNS documentation designed around it?
Diátaxis is a methodology for writing technical documentation; its main characteristic is that it makes a clear distinction between tutorials, guides, explanatory documents, and reference material.
And owing to its design, IBDNS is offers numerous configuration options whose purpose and function must be rigorously documented. Which is why I decided early in the development process to adopt the Diátaxis approach for the documentation.
For IBDNS, reference documentation is the most important of the four categories in Diátaxis, especially for configuration options. Each parameter is carefully documented: it begins with a summary of the possible values, followed by a detailed description of its effects, the specifications being broken and the consequences, before concluding with possible uses for that parameter.
Here is an example for a parameter called
empty_non_terminal_rcode:
empty_non_terminal_rcode = “NOERROR” (default) | RCODE mnemonic | integer
Sets the RCODE that the server is to return when the queried name (QNAME) matches a node that exists, but has no entries. By default, this is not an error.
For example, if the server is authoritative for zone.example and there is at least one resource record for key._domainkey.zone.example, then _domainkey.zone.example is an empty non-terminal and this setting influences the RCODE returned for queries to this name.
If set to anything except “NOERROR” or 0, this breaks RFC 8020. If set to “NXDOMAIN”, it will also break resolvers because this RCODE implies that the queried name does not exist, nor does anything below it. This setting can be useful to replicate an incorrect implementation of DNS in another authoritative name server.
It is about reproducing the erroneous behaviour of some authoritative name servers in an edge case: it can happen that records exist at zone.example and records exist at the subdomain key._domainkey.zone.example (for a DKIM key, for example). In this case, _domainkey.zone.example is a name that does exist but contains no records: this is called an empty non-terminal (or ENT). So a query for _domainkey.zone.example should return a NOERROR response code. Instead, some servers return NXDOMAIN, as for a nonexistent name; in that case, it is a bug in the server. Unfortunately, this is a common bug that clients must be able to handle. For example, they should only cache the nonexistence of _domainkey.zone.example, not the entire subtree.
How has IBDNS been used in practice?
In October 2025, some colleagues and I took part in a DNS hackathon in Stockholm organised by Internetstiftelsen, DNS-OARC and Netnod. The hackathon was an opportunity to work with IBDNS, and I gave a lightning talk on the topic at RIPE 91 in late October 2025.
The project I worked on involved implementing a proposed DNS extension that would allow a client to request that the server return the server time in its response
(draft-liman-dns-utcstamp-00). This extension can help diagnose problems caused by a server’s clock being out of sync with the rest of the cluster.
I worked in tandem with the specification’s author to implement it in IBDNS while he implemented the client side by patching dig. With the extension, dig could display the time returned by the server. For example:
;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; UTCSTAMP: 00 00 00 00 68 f6 16 fa (2025-10-20T11:03:22Z)
Because the specification was fairly simple, I had plenty of time to start by adding support for EDNS in IBDNS (which it lacked, but was necessary for the next steps), then to implement the specification itself, and eventually to add some failure modes. Here they are:
- Omit the time from the response even if the client requested it.
- Return the time even if the client didn’t request it.
- Return the special value to signal that the time information is missing.
- For something sneaky: apply a time offset (set in the configuration file) relative to the time returned by the server.
- Sneakier yet, return random bytes instead of the correct time.
This let us verify that the modified dig could handle these failure modes. The first time, when I told him to test with the domain that returns random bytes, the client crashed: the code was not robust enough. But he was able to correct and test it completely on his own.
In the end, we had two server-side implementations of the extension: in BIND and in IBDNS. Plus a client-side implementation in dig.
The hackathon demonstrated that IBDNS is a relevant tool for testing DNS clients and a useful development tool for developing new extensions for DNS. That’s also where Ibby was born, the IBDNS mascot shown at the top of this post.
Conclusion
We’ve seen how IBDNS has evolved since Afnic officially announced its release as open-source software. There are still a lot of items on the roadmap, and we also have plans to expand the range of failure modes it offers.
In the meantime, whether you are developing a DNS client or a DNS testing tool or you are simply interested in the server’s architecture, you can explore the IBDNS GitLab repository at Afnic Labs.