iroh
iroh copied to clipboard
RFC: `_iroh` DNS records and pkarr signed packets
This is a proposal for spec on how Iroh uses the Domain Name System (DNS) and Pkarr for node discovery.
Implementation in iroh is at #2045, and iroh-dns-server, and a first discussion on the design happened in n0-computer/iroh-dns-server#5.
This is a first draft without much focus on edge cases, but wanted to condense the discussion into something we can finalize.
Node discovery via DNS
When connecting to an unknown NodeId, the DNS discovery mechanism in Iroh will perform a DNS query to discover relays or addresses for the node. The DNS discovery is configured with a origin domain (which defaults to dns.iroh.link, a server run by n0). Iroh will then perform a DNS query through the DNS resolver (which defaults to using the host system's nameservers):
_iroh.<z32-node-id>.<origin-domain> TXT
_irohis the record name defined in this spec<z32-node-id>is the z32 encoding of the 32-byte longNodeId(which is a string of 52 characters)<origin-domain>is the configured origin domainTXTis the queried record type
The returned TXT records must contain a string value of the form key=value, as defined in RFC1464. If a record contains multiple character strings, they will be concatenated first. All characters after the first = character form the value string, and those before the first = are the key. The attributes from all valid TXT records will be merged, and each key can therefore have either one or multiple values.
This spec defines the following attributes:
relay=<url>: The home relay for this node, e.g.https://euw1-1.derp.iroh.network.addr=<addr> <addr> ..A space-seperated list of socket addresses for this Iroh node. Each address is an IPv4 or IPv6 address with a port (e.g.1.2.3.4:7367or[::1]:3521
Node announces via pkarr
Nodes announce their address information in Pkarr signed packets. The TXT records, as described above, are added to the answers section of a DNS section as specified by pkarr. Their name must be _iroh.<z32-node-id>. The z32 encoded node ID must be the root name, no other origin but . (the single dot) is permitted.
Those packets can either be published to a Pkarr relay or to the mainline DHT, as specified by Pkarr.
DNS servers that support this spec will receive these Pkarr signed packets, check their signature and format validity, and then serve each contained record, with the DNS server's configured origin domain appended to all record names.
Further reading
See https://github.com/n0-computer/iroh-dns-server/pull/5#issuecomment-2034165030 for links to more resources.
This seems pretty nice. It adheres to DNS conventions as far as I can see, also adheres to pkarr philosophy ("The z32 encoded node ID must be the root name, no other origin but . (the single dot) is permitted.").
The only thing debatable is whether the addr=<addr> <addr> .. format of combining multiple addrs won't exceed some size limit or should be separate records.
Why not
addr=<addr1>
addr=<addr1>
instead of
addr=<addr1> <addr2>
?
There is probably a good reason, just curious about that choice.
I'm kind of surprised we add direct addrs in there. If we even publish those they could easily go in A and AAAA records, but I guess they'd be unsigned in that case.
I'm kind of surprised we add direct addrs in there. If we even publish those they could easily go in A and AAAA records, but I guess they'd be unsigned in that case.
We need ip addr plus port, and A/AAAA does not have a port.
Signing is no issue, all records are from a single signed packet.
The current DNS PRs do not support addr yet, only relay. I do think it makes sense to support addr at least for resolving, that's why I added it to the spec draft here.
Address format, I'd be fine with changing to single addr per record as @rklaehn suggests. It is simpler and more straightforward.
The space-separated list was an idea to save space. I think separate record per address would add around 16 bytes per address (vs space-separated list in a single attribute):
- space separated:
16 + (n_addr * 24) - record each:
(16 + 24) * n_addr
but there should only be a couple not lots, so doesn't matter in practice likely even with the 1024 byte limit by pkarr.
This is now implemented