{ "id": "https://ryan.freumh.org/eon.html", "title": "Eon", "link": "https://ryan.freumh.org/eon.html", "updated": "2025-04-21T00:00:00", "published": "2025-04-21T00:00:00", "summary": "
Eon\nis an Effects-based OCaml Nameserver using MirageOS’s functionally pure Domain Name\nSystem (DNS) library\nwith direct-style\nIO (as opposed to monadic\nIO) using OCaml 5’s\neffect handlers\n[1] created as the basis to implement\nsome of ideas from the Spatial Name\nSystem.
\nDNS is well-known to be used for data\nexfiltration and tunneling,\nsince DNS is one of the few protocols that’s almost always allowed\nthrough a firewall (at least through a recursive resolver) since it’s so\nfundamental to the operation of the Internet. I’ve implemented a\ntransport layer over DNS in\nEon, a simple netcat\nexample shows how this can be used to transport data using DNS queries.\nMany thanks to Paul-Elliot for\nhelping clean up the transport interface and making it more\nidiomatically functional. At the moment there’s no multiplexing – a\nserver can only handle one communication at a time, but that could\naddresses by adding a demultiplexing field (a ‘port’).
\nThe well-defined interfaces that\nOCaml gives us allows this to be combined in interesting ways, such as a\nshell\nover DNS (SoD), or an IP\ntunnel. Note that you wouldn’t want to use this in production\nwithout some form of encryption (maybe ocaml-tls?) and\nauthentication (e.g. public/private keys, or capabilities). A standalone\nexample of a capability interface to a shell can be found at capability-shell.
\nThere’s some interesting performance\ncharacteristics of this tunneling in a variable asymmetry of latency\nbetween the sender and receiver, since we’re retrofitting bidirectional\npacket switching onto a request response protocol. That is, for the DNS\nserver to send data to a client it has to have a query to respond to. We\ncan’t wait to respond to a query until we have data, since recursive\nresolvers aggressively timeout and return a SERVFAIL in the case of a delayed reply. So we\nhave the client periodically poll the server with queries containing no\ndata, so the latency of the server to client link is bounded by the\nperiod of this polling.
This is interesting as it allows us\nto bootstrap communication with a nameserver using nothing but\nDNS.
\nDNS is an old protocol, and\nhas some baked-in limitations due to protocol\nossification (such as a maximum domain name length of 255 bytes).\nThe ‘back-end’ of the protocol, interactions between services under your\ncontrol, is easier to evolve. The AXFR zone transfers defined with the\nDomain Name System [2] are often replaced with some form of\ndatabase replication in nameserver implementations. Dynamic updates\n[3] using secret key transaction\nsignatures [4] are often eschewed in favour of\ncustom APIs1. While using these protocols allows\nan variety of nameserver implementations to interoperate, in practice\nthey are often replaced with custom solutions.
\nWe’ve experimented with a programmable\ninterface to the nameserver with Cap’n Proto capability-based\nRPCs. This creates capabilities for dynamically updating a domain, or\nreceiving a zonefile and dynamic updates as a secondary nameserver.\nPlease feel free to try deploying it for your own domain, and get in touch if you’d like to set up a reciprocal\nsecondarying relationship.
\nHaving a programmable interface\ninto the domain name system is powerful, because domain names are\npowerful. Domain names are the root of identity for the Internet\nprotocol suite. Federated communication networks derive user’s identify\nfrom domain names including Matrix, Mastodon, Bluesky’s AT Protocol\n[5], and good old E-Mail.
\nThe DNS is also used to prove\nowership of domains. The security of the modern internet is built on the\nTransport Layer Security (TLS) protocol [6], which uses X509 certificates signed\nby certificate authorities. The Internet Security Research Group\n(ISRG)’s Let’s Encrypt certificate authority (CA) provides the majority\nof the Internet’s certificates, over 500 million in 2025. Traditionally\nprovisioning a certificate was costly and manual process, but the\nAutomatic Certificate Management Environment (ACME) protocol [7] used by Let’s Encrypt allows for an\nautomated provisioning of certificates by proving ownership of a domain\nby displaying a token with one of a number of challenges; HTTP,\nTLS-ALPN, and DNS.
\nOnly the DNS challenge is possible\nif the address the domain name points to is not publicly accessible,\nwhich is often the case for remote and resource constrained devices\nbehind NATs or firewalls. However, it requires a complex\ndance of managing DNS UPDATE keys and specifying the subdomain and\nzone which it can modify. With our capability interface to the nameserver\nwe can expose fine-grained access control to provision a certificate for\na subdomain.
\nMotivated by a desire to curb the power\nuse of self-hosted services which are often idle for large periods of\ntime, such as storage servers, we implemented hibernia\nnameserver than can wake a machine up on a name resolution with Eon and\na OCaml Wake-on-LAN implementation.\nWe published this idea as ‘Carbon-aware Name\nResolution’ in LOCO2024.
\nI’m looking at extending this interface\nto support additional functionality for networked services such as\nstorage, identity, and more. Eilean is an\nattempt to parameterise a federated service deployment by a domain name\nleveraging the NixOS deployment system to do so, but it lacks a runtime\ncomponent.
\nNote that prior\nto TSIG introduced with DNSSEC, DNS UPDATEs and zone transfers were\ntypically enforced with IP-based access control.↩︎
Eon\nis an Effects-based OCaml Nameserver using MirageOS’s functionally pure Domain Name\nSystem (DNS) library\nwith direct-style\nIO (as opposed to monadic\nIO) using OCaml 5’s\neffect handlers\n[1] created as the basis to implement\nsome of ideas from the Spatial Name\nSystem.
\nDNS is well-known to be used for data\nexfiltration and tunneling,\nsince DNS is one of the few protocols that’s almost always allowed\nthrough a firewall (at least through a recursive resolver) since it’s so\nfundamental to the operation of the Internet. I’ve implemented a\ntransport layer over DNS in\nEon, a simple netcat\nexample shows how this can be used to transport data using DNS queries.\nMany thanks to Paul-Elliot for\nhelping clean up the transport interface and making it more\nidiomatically functional. At the moment there’s no multiplexing – a\nserver can only handle one communication at a time, but that could\naddresses by adding a demultiplexing field (a ‘port’).
\nThe well-defined interfaces that\nOCaml gives us allows this to be combined in interesting ways, such as a\nshell\nover DNS (SoD), or an IP\ntunnel. Note that you wouldn’t want to use this in production\nwithout some form of encryption (maybe ocaml-tls?) and\nauthentication (e.g. public/private keys, or capabilities). A standalone\nexample of a capability interface to a shell can be found at capability-shell.
\nThere’s some interesting performance\ncharacteristics of this tunneling in a variable asymmetry of latency\nbetween the sender and receiver, since we’re retrofitting bidirectional\npacket switching onto a request response protocol. That is, for the DNS\nserver to send data to a client it has to have a query to respond to. We\ncan’t wait to respond to a query until we have data, since recursive\nresolvers aggressively timeout and return a SERVFAIL in the case of a delayed reply. So we\nhave the client periodically poll the server with queries containing no\ndata, so the latency of the server to client link is bounded by the\nperiod of this polling.
This is interesting as it allows us\nto bootstrap communication with a nameserver using nothing but\nDNS.
\nDNS is an old protocol, and\nhas some baked-in limitations due to protocol\nossification (such as a maximum domain name length of 255 bytes).\nThe ‘back-end’ of the protocol, interactions between services under your\ncontrol, is easier to evolve. The AXFR zone transfers defined with the\nDomain Name System [2] are often replaced with some form of\ndatabase replication in nameserver implementations. Dynamic updates\n[3] using secret key transaction\nsignatures [4] are often eschewed in favour of\ncustom APIs1. While using these protocols allows\nan variety of nameserver implementations to interoperate, in practice\nthey are often replaced with custom solutions.
\nWe’ve experimented with a programmable\ninterface to the nameserver with Cap’n Proto capability-based\nRPCs. This creates capabilities for dynamically updating a domain, or\nreceiving a zonefile and dynamic updates as a secondary nameserver.\nPlease feel free to try deploying it for your own domain, and get in touch if you’d like to set up a reciprocal\nsecondarying relationship.
\nHaving a programmable interface\ninto the domain name system is powerful, because domain names are\npowerful. Domain names are the root of identity for the Internet\nprotocol suite. Federated communication networks derive user’s identify\nfrom domain names including Matrix, Mastodon, Bluesky’s AT Protocol\n[5], and good old E-Mail.
\nThe DNS is also used to prove\nowership of domains. The security of the modern internet is built on the\nTransport Layer Security (TLS) protocol [6], which uses X509 certificates signed\nby certificate authorities. The Internet Security Research Group\n(ISRG)’s Let’s Encrypt certificate authority (CA) provides the majority\nof the Internet’s certificates, over 500 million in 2025. Traditionally\nprovisioning a certificate was costly and manual process, but the\nAutomatic Certificate Management Environment (ACME) protocol [7] used by Let’s Encrypt allows for an\nautomated provisioning of certificates by proving ownership of a domain\nby displaying a token with one of a number of challenges; HTTP,\nTLS-ALPN, and DNS.
\nOnly the DNS challenge is possible\nif the address the domain name points to is not publicly accessible,\nwhich is often the case for remote and resource constrained devices\nbehind NATs or firewalls. However, it requires a complex\ndance of managing DNS UPDATE keys and specifying the subdomain and\nzone which it can modify. With our capability interface to the nameserver\nwe can expose fine-grained access control to provision a certificate for\na subdomain.
\nMotivated by a desire to curb the power\nuse of self-hosted services which are often idle for large periods of\ntime, such as storage servers, we implemented hibernia\nnameserver than can wake a machine up on a name resolution with Eon and\na OCaml Wake-on-LAN implementation.\nWe published this idea as ‘Carbon-aware Name\nResolution’ in LOCO2024.
\nI’m looking at extending this interface\nto support additional functionality for networked services such as\nstorage, identity, and more. Eilean is an\nattempt to parameterise a federated service deployment by a domain name\nleveraging the NixOS deployment system to do so, but it lacks a runtime\ncomponent.
\nNote that prior\nto TSIG introduced with DNSSEC, DNS UPDATEs and zone transfers were\ntypically enforced with IP-based access control.↩︎