6. Announcing hostnames
Date: 2025-02-27
Status
Accepted
Context
There is no consistent approach for hostname resolution across VPN providers such as Tailscale, zerotier and so on. As Clan wishes to support as many of them as practical, we therefore require a common solution for announcing and resolving hostnames.
Claiming a hostname
A host should be able to claim one or more hostnames, with support for multiple IP addresses, both IPV4 and IPV6.
For example, a host with ip addresses 10.0.0.1
and 2606:4700:4700::1111
that wants to be resolvable with hostnames
mercury
and venus
.
Logical network
Hosts should be grouped under a logical network, independent of the underlying VPN solution, with an associated
top-level domain e.g. mercury.sol
, venus.sol
, with sol
being the top-level domain.
This is to support host resolution across multiple Clans in the future.
Hostname TTL
Hosts will be required to periodically re-assert their claims. Failure to do so will result in a host losing those hostnames after a configurable network-specific time-to-live.
The first host to claim a hostname should retain that claim until such time as it fails to re-assert it within the required timeframe.
Distributed control
Changing a network's top-level domain, hostname TTL and other properties should be possible via any node participating in the network.
Decision
We will start by introducing the concept of a Network with the following properties:
- an associated ED25519 key pair, with the base64-encoded public key being used as a unique identifier.
- a settings object containing values such as the top-level domain, hostname TTL and any other properties to be applied across the whole network.
- settings need to be signed by the network's ED25519 private key.
- signed settings can be provided to any node within the network for distribution as the signature can be verified against the network's id (public key).
Here is an example of signed network settings:
Next we will introduce a Host with the following properties:
- an associated ED25519 key pair, with the base64-encoded public key being used as a unique identifier.
- a host may report one or more IP addresses, signed by the host's private key.
- a host may claim one or more hostnames, signed by the host's private key.
- updates for a given host are ignored unless first signed by the host's private key.
- each host and hostname may be signed by one or more nodes within the network (chronology-through-trusted-attestation).
The model looks like this:
We include the hostname claims as separately indexed and signed subitems within the Host model. This is to allow us to facilitate allowing the earliest claimant to retain a hostname.
A Host may change the hostnames they are claiming. We need to keep track of when each was first seen by nodes within the network. Therefore, we require them to be signed individually, thereby retaining that history.
Merging Host entries
When merging two entries for the same Host, we will do the following:
- verify each has been signed by the host, using the host's id as the ED25519 public key, disregarding otherwise.
- verify each has been signed by at least one of the network's
signing_keys
, disregarding otherwise. - retain the values from the entry with the latest
signed_at
as per the host signature.
NOTE: In this scenario, we are trusting the clock of the signer.
Merging Hostnames
When merging two hostnames for the same host, we will do the following:
- verify it has been signed by the Host, using the Host's id as the ED25519 public key.
- combine the signature list between both entries, retaining only those which have been signed by the network's
signing_keys
.
Determining DNS entries
Determining the earliest claim for each respective hostname requires us to take a view across all the available state.
We must iterate through the hostname claims within each Host, combining them with the Network's top-level domain, and compiling a list of signatures for each fully qualified domain name.
The Host with the earliest signature is the Host to which that fully qualified domain name should point to
This will then be captured in a JSON lines encoded file called dns.json
.
Resolving DNS entries
To facilitate seamless integration of our DNS entries, we will create an NSS module supporting gethostbyname
which
will integrate the contents of dns.json
into the NSS hosts database.
Expiring DNS entries
As per the Network's hostname TTL setting, nodes will periodically examine their local state and remove any Host entries which have not recently been signed within the required timeframe.
After expiry (and merging), the dns.json
file is re-generated to reflect the new state of the world.
Hostname claims by expired Hosts are immediately released.
Consequences
Hostname resolution irrespective of VPN provider becomes possible, as it is now an orthogonal concern rather than implementation specific.