You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.5 KiB

DNS-web

An authoritative DNS server with a web interface. As a MirageOS unikernel. Storage in a git remote repository.

Features:

  • Secure, reliable, fast (MirageOS unikernels)
  • Import and export of zone files (no vendor lock)
  • Let's encrypt integration
  • Dynamic updates (via nsupdate, HTTP API, web interface)
  • Two factor authentication with webauthn
  • Checks modifications of a zone and does not accept changes leading to invalid data
  • Donation based

Future features

  • Dynamic update via ssh
  • IPv6 support (authoritative nameservers)
  • DNSSec support (nsec and nsec3)
  • Audit logs for each zone and user account (provided by using git storage)
  • Metrics
  • Notification system (for cyber threats / anomalities)
  • Git interface for zone editing (needs a git server)
  • Social login
  • email verification

Design

A unikernel using Dream and webauthn. It relies on a git remote repository for persisting data.

The available services are HTTP/HTTPS.

The data, apart from the zone files, are user accounts and shared secrets for dynamic updates. This data is kept in text files. Each user has a name, email address, authentication data, and a set of domains. The authentication data should be a list of webauthn tokens and optionally a passphrase.

If privileged access is necessary, we can manually shutdown the service and push to the git repository directly.

Workflows

Enroll a new account

Basically the code from the webauthn demo. The email address must be unique across users.

Register a second authentication mechanism

Requires a logged in user. May as well remove a webauthn token, or the passphrase. There must be at least one authentication mechanism present at any time. There should be no more than 5 authentication mechanisms.

Pass privileges to another user for that domain

Requires a logged in user with access to that domain. Specifies an email address of another registered user to provide them access.

Delete an account

Should be possible if there's no domain that is now not maintained by anyone.

Add a domain

Requires a logged in user and that the domain is not yet on the system.

Import a zonefile for a domain

Requires a logged in user and that the domain either does not exist yet, or is owned by the user (bulk change).

Manage a domain: add/edit/remove DNS records

Requires a logged in user with access to that domain. The domain check should succeed before writing.

Export domain as zone file

Requires a logged in user with access to that domain.

Register a token for a dynamic update (HTTP/nsupdate)

Either generate or upload a shared secret. Usable via HTTP or nsupdate (as a SHA256 hash). The output is a key file downloadable and usable with nsupdate (from bind-tools).

Future workflows

Add a domain and prove ownership (future)

Similar to let's encrypt: user requests a domain, and the system asks the user to add a TXT record with a token, which is then verified.

Register ssh public key for dynamically updating an address record

A ssh login with any user from a remote machine should trigger an update.

Change email address of an user account

TBD

Data storage

This is meant to work well with dns-primary-git unikernel:

  • zone data is kept flat at the root in one file per domain named after the domain
  • secret keys are at the root in a file with the "._keys" suffix

The user data is kept in the "users/" subdirectory, one file per user named after the email address (currently allowed characters

Synchronisation, source of truth

The git repository is the single source of truth. Keeping data synchronized is crucial for the operation. Both dns-primary-git and dns-web are using the same git repository for storage of data:

  • the "users" subdirectory is only read and written by dns-web
  • zone data is read and written by both dns-primary-git and dns-web
  • key data is read by dns-primary-git and read and written by dns-web
  • if a manual git push is done, both unikernels need to be notified to pull the current HEAD: dns-web via post-commit hook, dns-primary-git via DNS notify

Notification from dns-web to dns-primary-git: this is trivially achieved by sending a DNS notify with a respective key. Likely needs to be done even when only "users" was updated (at the moment, should be improved to handle merges appropriately). The key can be read from the main _keys file. Any zone, even the root one, can be used for this notify.

Notifications from dns-primary-git to dns-web: this cannot be achieved directly since dns-primary-git does not know of the existance of dns-web. So the git repository should have a post-commit webhook installed that requests dns-web to trigger a repo update (but not send a notify to dns-primary-git).

Now, the scenario that a user changes a zone and between the GET and the POST there was some (automated change): the POST should be rejected at first (and later an appropriate merge could be done).

What about the git repo was updated and the dns-primary-git receives a nsupdate? Certainly there's a merge conflict as well, which should be handled (same strategy as above).

TODO:

  • For consistency and observation, the commit ID of the last pull (or push) should be exposed via a network request (dns-web: HTTP request, dns-primary-git: some DNS packet)
  • For usability, should DNS update packets sent to dns-web be forwarded to dns-primary-git? Otherwise the endpoints for the web service and the DNS update are different (and may be confused).
  • Should users be stored in a separate branch or a separate repository?