For a question (name, type), an authoritative server
determines:
A query beneath a delegated child should produce a referral, not an authoritative negative answer from the parent. A query outside all configured zones should normally be refused. These boundary checks matter more than a simple map lookup.
rgbdns’s Zone stores records in a
BTreeMap<Name, Vec<Record>>, authoritative
apices and delegation owners in ordered sets, and separate metadata for
location and activation. Lookup walks name ancestry, recognizes cuts,
filters visible records, applies exact-name and wildcard rules, and
returns the typed Lookup outcome.
The response builder then:
The finite CNAME bound and visited set are deliberate denial-of-service and correctness controls. A cyclic zone must not turn one datagram into unbounded work.
djbdns uses a compact line-oriented zone source called
data. The first character selects a record form. Common
forms include:
| Prefix | Meaning |
|---|---|
. |
zone authority plus NS and address data |
& |
delegation NS and optional glue |
Z |
explicit SOA |
= |
A plus matching reverse PTR |
+ |
A only |
6 |
AAAA plus reverse PTR forms |
3 |
AAAA only |
@ |
MX and optional exchanger address |
C |
CNAME |
A |
private ANAME (flattened A/AAAA alias) |
^ |
PTR |
' |
TXT |
S |
SRV |
: |
generic record |
% |
client-location mapping |
Fields are colon-separated with octal escapes for bytes that would otherwise be ambiguous. Optional fields carry TTL, timestamp, and location information. The format is terse because it was designed for mechanical generation as well as hand editing.
Zone::parse reads this language line by line. It ignores
blank, comment, and disabled lines; reports the failing line number;
expands convenience forms into ordinary typed records; validates IPv4,
flat 32-digit IPv6, names, numeric ranges, and escaped bytes; and
records authoritative and delegation structure. When an SOA serial is
omitted, file loading derives a nonzero default from the source
modification time.
Timestamp fields use TAI64-style cutoffs. Depending on the marker, a record can be visible before or after a specified instant. Location codes select records using configured client IPv4 prefixes. rgbdns carries that metadata beside the record and evaluates it at lookup time.
A zone apex necessarily owns SOA and NS data. A CNAME owner, by contrast, cannot also own ordinary records. A literal apex CNAME would therefore make the zone internally contradictory: the alias rule says the owner has no other data while the authority rules require other data at that same owner.
Hosted sites still need a way for example.com to track
addresses controlled by a platform such as
customer.blog-host.example. DNS providers commonly call the
solution CNAME flattening, ALIAS, or ANAME. The authoritative server
resolves the configured target itself and publishes the resulting
addresses under the configured owner.
rgbdns calls this feature ANAME and uses the private
A source marker:
# Authority and nameserver address.
.example.com:192.0.2.53:ns1.example.com
# ANAME owner:target:maximum-ttl
Aexample.com:customer.blog-host.example:300
# Other apex data remains independent.
@example.com::mail.example.com:10:3600
'example.com:v=spf1 -all:3600
The form is:
Aowner:target:maximum-ttl
The TTL field is optional and defaults to 300 seconds. It is a ceiling, not a promise to extend the target’s lifetime. If the upstream address has 45 seconds remaining and the ANAME limit is 300, rgbdns returns 45. If the upstream has 900 seconds remaining, rgbdns returns no more than 300.
ANAME is stored separately from ordinary Record values.
It can coexist with SOA, NS, MX, TXT, CAA, and other non-address data.
Zone validation rejects:
ANAME is private configuration rather than a standard DNS RR type, so
a plain AXFR cannot represent it. rgbdns peers negotiate preservation
explicitly: axfr-get places private EDNS option 65001 with
the RGA1 version token in the AXFR request. An rgbdns
primary then inserts private-use TYPE65401 records whose TTL is the
ANAME cap and whose payload is the token followed by the target’s
uncompressed wire name. The receiving rgbdns validates that payload and
reconstructs the Aowner:target:ttl directive before
compilation.
An ordinary AXFR request does not receive TYPE65401. This keeps standard secondaries free of private metadata, but it also means they do not reproduce ANAME behavior. Delegate an ANAME-backed zone only to upgraded rgbdns peers, or use standard address records when non-rgbdns secondaries must serve it.
The server only applies ANAME to A and AAAA questions. SOA, NS, MX, TXT, CAA, and all other questions continue through normal authoritative lookup. ANAME also does not override a delegation cut: a name beneath a delegated child still produces a referral from the parent.
For an address question, the response path is:
For example, an upstream result such as:
customer.blog-host.example. 180 IN CNAME edge.host.example.
edge.host.example. 120 IN A 192.0.2.80
becomes:
example.com. 120 IN A 192.0.2.80
The CNAME is deliberately absent. Consumers see a conventional authoritative address RRset at the apex.
The resolver cache is shared by requests handled by one server process. Positive entries expire with the upstream chain’s shortest relevant TTL. Negative results use the authority SOA’s negative TTL when available and 60 seconds otherwise. The configured ANAME ceiling is applied when constructing each response, so two owners may safely share a target while using different TTL policies. Concurrent misses for one target and address family are coalesced into one upstream query. A failed lookup is retained for five seconds, during which matching requests fail without starting another recursive chain. This short circuit limits retry storms and cross-provider ANAME loop amplification without turning a transient failure into long-lived negative DNS data.
Resolution is bounded in the same spirit as the rest of rgbdns:
DNSCACHEIP selects one or more recursive endpoints,
separated by commas. Each endpoint may be an IP address using port 53 or
an explicit socket address. Without it, rgbdns reads
/etc/resolv.conf. A local validating dnscache
is the preferred upstream when operators want DNSSEC validation and a
cache shared with other local DNS work:
DNSCACHEIP=127.0.0.1:5354 IP=0.0.0.0 PORT=53 tinydnsANAME metadata survives tinydns-data compilation through
private CDB entries; it is not encoded as a made-up public RR type. This
retains the source semantics across text and CDB operation without
teaching ordinary DNS clients about a private wire format.
Standard AXFR has no interoperable way to describe this private
policy. rgbdns therefore emits no ANAME metadata to an ordinary AXFR
client. Upgraded rgbdns peers can explicitly negotiate the experimental
RGA1 extension: the requester sends EDNS option 65001 and
the primary returns validated private-use TYPE65401 records only for
that transfer. The receiver restores the source directive and resolves
the target independently. A conventional secondary still receives only
standard DNS records and cannot reproduce ANAME behavior. Operators must
delegate an ANAME-backed zone only to upgraded rgbdns peers unless they
materialize standard A and AAAA records instead.
The traditional tinydns-data compiles text into a
constant database, CDB. The serving process reads the compiled file
instead of reparsing editable text for every startup or query.
Compilation also enables atomic replacement: write and validate a new
file, then rename it into place.
rgbdns’s src/cdb.rs preserves the djbdns key/value
layout for ordinary records and uses a private, NUL-prefixed key
namespace for ANAME metadata. compile serializes typed
records and metadata; load reads entries and reconstructs a
Zone. The loader does not trust the database merely because
it is local. It bounds file and entry sizes, validates keys, checks
record layouts, decodes names and RDATA through explicit lengths, and
rejects malformed data.
This is an important general rule: compiled configuration is still input. It may be truncated by a failed copy, generated by an older tool, or replaced by an attacker with filesystem access. Memory safety should not depend on the provenance story being perfect.