You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Optional hostname validation and zone scoping for hostsfile
#684
Would you consider adding two optional controls to hostsfile:
hostsfile = "/etc/hosts"# Check imported hostnames against RFC 952/1123 host-name rules.hostsfilechecknames = true# Only publish names within these DNS zones.hostsfilezones = ["home.arpa."]
with current behaviour preserved when neither is configured?
My use case is VyOS, where /etc/hosts is useful as a dynamic source of DHCP-generated LAN records, but the same file also contains entries intended for the router itself rather than its DNS clients.
I think there are two separate issues:
name validation — should a hosts-file token be accepted as a host name?
publication scope — even if valid, should that name be published by SDNS?
Current behaviour
Current SDNS hostsfile parsing validates the first field using net.ParseIP(), but after that parseLine() returns the remaining fields directly as hostnames. I cannot see an equivalent RFC 952/1123 hostname check before those names enter HostsDB.
The same implementation then pre-builds A/AAAA/PTR records. On a hosts-file lookup hit, SDNS sets:
Authoritative: true
writes the response, then calls:
ch.Cancel()
so a hosts-file hit becomes the resolver's authoritative answer rather than merely influencing normal resolution.
This is reasonable when the configured file contains only DNS data intended for publication.
A system /etc/hosts is often broader than that.
For example, mine can contain:
Entry type
Example
Intended use
DHCP LAN host
harmonyhub.home.arpa
Publish
Local zone record
ns.home.arpa -> 192.168.1.1
Publish
Resolver bootstrap pin
dns1.nextdns.io -> 45.90.28.0
Router-local use
Router hostname
vyos -> 127.0.1.1
Router-local use
Malformed DHCP-derived name
-.home.arpa
Reject
localhost is deliberately not included as an example of a bad answer here: RFC 6761 gives localhost. special loopback semantics, including special handling by caching DNS servers.
The validation problem
SDNS's own generated configuration currently describes hostsfile as:
Serves entries from hosts file (RFC 952/1123 format)
However, an entry such as:
192.168.1.20 -.home.arpa
passes the existing IP check and the hostname is subsequently accepted.
I am not claiming that -.home.arpa cannot be represented as a DNS owner name. Generic DNS names and host names are not identical concepts.
The narrower issue is that -.home.arpa does not satisfy the RFC 952/1123 host-name rules which SDNS says this importer uses.
RFC 952 permits letters, digits and hyphens but requires a name to start with a letter and not end in -; RFC 1123 relaxes the first-character rule to allow a digit. A label consisting of - therefore remains invalid as a host name.
Repeated malformed entries make this particularly visible:
SDNS reuses an existing HostEntry for the repeated primary name and appends the addresses, so this can become an authoritative multi-A answer:
-.home.arpa. A 192.168.1.20
-.home.arpa. A 192.168.1.21
-.home.arpa. A 192.168.1.22
The address aggregation is useful behaviour for valid names. The problem is that the malformed host name was admitted to HostsDB first.
How it reaches /etc/hosts on VyOS
Current VyOS DHCP handling reads the lease hostname, strips a trailing dot, and only creates a MAC-derived fallback when the hostname is empty:
if [ -z"$client_name" ];then
...
fi
It then obtains the DHCP domain-name and appends it where necessary before submitting the resulting name to vyos-hostsd-client.
Therefore a non-empty value such as:
-
does not use the empty-name fallback.
With:
domain-name = home.arpa
it can become:
-.home.arpa
I do not know from this code path which client or earlier component originally supplied -, and I do not think SDNS needs to know.
VyOS could also validate this earlier. But hostsfile can consume files produced by DHCP, scripts, configuration management, or humans, so checking SDNS's own import contract still seems useful.
The separate publication-scope problem
Even perfectly valid entries may not belong in client-facing DNS.
For example:
127.0.1.1 vyos
can be useful to the router itself. Returned to another LAN machine, 127.0.1.1 refers to that client's loopback network, not the router.
Likewise SDNS documents that hostname-based DoH forwarders are resolved once at startup using the system resolver and then pinned for process lifetime.
In my deployment this makes a local entry such as:
45.90.28.0 dns1.nextdns.io
useful for bootstrap:
SDNS startup
|
system resolver
|
/etc/hosts
|
bootstrap address
But with:
hostsfile = "/etc/hosts"
the same row can also become an authoritative answer to LAN clients.
SDNS does not require me to bootstrap this way; that is deployment-specific. The point is simply that:
mapping useful to local operating system
does not necessarily mean:
mapping intended for DNS publication
Existing DNS-server precedent
I looked at other DNS implementations mainly to avoid inventing unfamiliar terminology.
Implementation
Relevant behaviour
CoreDNS
hosts FILE [ZONES...]; ZONES explicitly defines zones the hosts plugin is authoritative for
BIND 9
check-names checks syntax/character rules, with hostname rules derived from RFC 952/1123
PowerDNS Recursor
Separates /etc/hosts path from whether it is published using export-etc-hosts, which defaults off
dnsmasq
DHCP --domain defines the domain DHCP clients may legally claim, specifically preventing clients from claiming unrelated public names
CoreDNS is particularly close to the proposed zone behaviour:
hosts [FILE [ZONES...]]
Its documentation says ZONES are the zones for which the plugin should be authoritative. It even gives an example loading one hosts file while only serving selected zones.
Current CoreDNS source applies that test while importing each name:
Only accepted names are added to forward and automatic reverse maps.
BIND provides useful precedent for the other proposed name. Its long-standing check-names option restricts syntax of applicable names, and its documentation explicitly derives legal hostname rules from RFC 952/1123.
PowerDNS exposes another version of the same trust boundary: specifying an /etc/hosts file and exporting it through DNS are separate decisions, controlled by etc-hosts-file and export-etc-hosts.
dnsmasq handles a related boundary earlier, at DHCP ingestion: configured --domain determines which domain DHCP clients may claim, specifically to prevent an untrusted LAN host from claiming an unrelated domain and capturing traffic.
Suggested option names
Based on those precedents, I think these are reasonably self-explanatory and fit SDNS's existing flat configuration style:
because "validate" could mean the file, addresses, permissions, duplicates, or names. check-names already has established DNS terminology through BIND.
I would favour skipping and logging the malformed name rather than rejecting the entire hosts file. One bad DHCP lease should not remove every valid local record.
SDNS already supports wildcard hosts-file entries, so strict checking would need to preserve supported forms such as:
*.home.arpa
while validating the hostname portion separately.
With:
hostsfilezones = ["home.arpa."]
zone matching should be DNS-label aware:
home.arpa. include
printer.home.arpa. include
a.b.home.arpa. include
vyos. exclude
dns1.nextdns.io. exclude
nothome.arpa. exclude
evilhome.arpa. exclude
home.arpa.example. exclude
home.arpa. is particularly suitable for my deployment because RFC 8375 defines it for locally significant naming within residential homenets and requires those queries to be resolved locally rather than forwarded outside the homenet.
I would keep both settings independent:
# Validate names but publish every namespace in the filehostsfilechecknames = true
or:
# Preserve current name acceptance but restrict publication scopehostsfilezones = ["home.arpa."]
would continue accepting all current names and namespaces.
That matters because DNS owner names are broader than RFC 952/1123 host names, and some users may intentionally rely on names that a strict hostname check would reject.
Strict checking would therefore affect only users who explicitly request it.
to give hostsfile an explicit validation and publication boundary?
For my case this would solve both issues cleanly:
-.home.arpa
would not silently become an authoritative multi-A answer when strict hostname checking is enabled, while valid but router-local entries such as:
vyos
dns1.nextdns.io
could remain in /etc/hosts without being published through SDNS when only home.arpa. is selected.
The concepts also have established precedent rather than being SDNS-specific: BIND uses check-names, CoreDNS gives its hosts plugin explicit authoritative ZONES, PowerDNS makes /etc/hosts export explicit, and dnsmasq constrains DHCP-generated names to an intended local domain.
For a dedicated hosts file, current behaviour can remain unchanged.
For a mixed-purpose system /etc/hosts, these options would provide a clean boundary between OS-local naming state and DNS data intentionally published to clients.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Would you consider adding two optional controls to
hostsfile:with current behaviour preserved when neither is configured?
My use case is VyOS, where
/etc/hostsis useful as a dynamic source of DHCP-generated LAN records, but the same file also contains entries intended for the router itself rather than its DNS clients.I think there are two separate issues:
Current behaviour
Current SDNS
hostsfileparsing validates the first field usingnet.ParseIP(), but after thatparseLine()returns the remaining fields directly as hostnames. I cannot see an equivalent RFC 952/1123 hostname check before those names enterHostsDB.The same implementation then pre-builds A/AAAA/PTR records. On a hosts-file lookup hit, SDNS sets:
Authoritative: truewrites the response, then calls:
so a hosts-file hit becomes the resolver's authoritative answer rather than merely influencing normal resolution.
This is reasonable when the configured file contains only DNS data intended for publication.
A system
/etc/hostsis often broader than that.For example, mine can contain:
harmonyhub.home.arpans.home.arpa -> 192.168.1.1dns1.nextdns.io -> 45.90.28.0vyos -> 127.0.1.1-.home.arpalocalhostis deliberately not included as an example of a bad answer here: RFC 6761 giveslocalhost.special loopback semantics, including special handling by caching DNS servers.The validation problem
SDNS's own generated configuration currently describes
hostsfileas:However, an entry such as:
passes the existing IP check and the hostname is subsequently accepted.
I am not claiming that
-.home.arpacannot be represented as a DNS owner name. Generic DNS names and host names are not identical concepts.The narrower issue is that
-.home.arpadoes not satisfy the RFC 952/1123 host-name rules which SDNS says this importer uses.RFC 952 permits letters, digits and hyphens but requires a name to start with a letter and not end in
-; RFC 1123 relaxes the first-character rule to allow a digit. A label consisting of-therefore remains invalid as a host name.Repeated malformed entries make this particularly visible:
SDNS reuses an existing
HostEntryfor the repeated primary name and appends the addresses, so this can become an authoritative multi-A answer:The address aggregation is useful behaviour for valid names. The problem is that the malformed host name was admitted to
HostsDBfirst.How it reaches
/etc/hostson VyOSCurrent VyOS DHCP handling reads the lease hostname, strips a trailing dot, and only creates a MAC-derived fallback when the hostname is empty:
It then obtains the DHCP
domain-nameand appends it where necessary before submitting the resulting name tovyos-hostsd-client.Therefore a non-empty value such as:
does not use the empty-name fallback.
With:
it can become:
I do not know from this code path which client or earlier component originally supplied
-, and I do not think SDNS needs to know.VyOS could also validate this earlier. But
hostsfilecan consume files produced by DHCP, scripts, configuration management, or humans, so checking SDNS's own import contract still seems useful.The separate publication-scope problem
Even perfectly valid entries may not belong in client-facing DNS.
For example:
can be useful to the router itself. Returned to another LAN machine,
127.0.1.1refers to that client's loopback network, not the router.Likewise SDNS documents that hostname-based DoH forwarders are resolved once at startup using the system resolver and then pinned for process lifetime.
In my deployment this makes a local entry such as:
useful for bootstrap:
But with:
the same row can also become an authoritative answer to LAN clients.
SDNS does not require me to bootstrap this way; that is deployment-specific. The point is simply that:
does not necessarily mean:
Existing DNS-server precedent
I looked at other DNS implementations mainly to avoid inventing unfamiliar terminology.
hosts FILE [ZONES...];ZONESexplicitly defines zones the hosts plugin is authoritative forcheck-nameschecks syntax/character rules, with hostname rules derived from RFC 952/1123/etc/hostspath from whether it is published usingexport-etc-hosts, which defaults off--domaindefines the domain DHCP clients may legally claim, specifically preventing clients from claiming unrelated public namesCoreDNS is particularly close to the proposed zone behaviour:
Its documentation says
ZONESare the zones for which the plugin should be authoritative. It even gives an example loading one hosts file while only serving selected zones.Current CoreDNS source applies that test while importing each name:
Only accepted names are added to forward and automatic reverse maps.
BIND provides useful precedent for the other proposed name. Its long-standing
check-namesoption restricts syntax of applicable names, and its documentation explicitly derives legal hostname rules from RFC 952/1123.PowerDNS exposes another version of the same trust boundary: specifying an
/etc/hostsfile and exporting it through DNS are separate decisions, controlled byetc-hosts-fileandexport-etc-hosts.dnsmasq handles a related boundary earlier, at DHCP ingestion: configured
--domaindetermines which domain DHCP clients may claim, specifically to prevent an untrusted LAN host from claiming an unrelated domain and capturing traffic.Suggested option names
Based on those precedents, I think these are reasonably self-explanatory and fit SDNS's existing flat configuration style:
I prefer
hostsfilechecknamesover:because "validate" could mean the file, addresses, permissions, duplicates, or names.
check-namesalready has established DNS terminology through BIND.Likewise I prefer
hostsfilezonesover:because
zonedescribes the DNS namespace being published and has direct precedent in CoreDNS's comparable hosts plugin.Suggested behaviour
With:
normal imported hostnames would be checked before insertion:
I would favour skipping and logging the malformed name rather than rejecting the entire hosts file. One bad DHCP lease should not remove every valid local record.
SDNS already supports wildcard hosts-file entries, so strict checking would need to preserve supported forms such as:
while validating the hostname portion separately.
With:
zone matching should be DNS-label aware:
home.arpa.is particularly suitable for my deployment because RFC 8375 defines it for locally significant naming within residential homenets and requires those queries to be resolved locally rather than forwarded outside the homenet.I would keep both settings independent:
or:
or, for my deployment:
Result:
home.arpa.harmonyhub.home.arpans.home.arpadns1.nextdns.iovyos-.home.arpaImplementation
Both checks seem best applied while loading the hosts database:
That keeps query hot path unchanged and prevents rejected data from entering either forward or reverse maps.
Aliases should receive the same checks individually, and rejected/out-of-zone names should not generate PTR data either.
A log such as:
would probably be sufficient initially.
Compatibility
Both options could default to current behaviour:
would continue accepting all current names and namespaces.
That matters because DNS owner names are broader than RFC 952/1123 host names, and some users may intentionally rely on names that a strict hostname check would reject.
Strict checking would therefore affect only users who explicitly request it.
Overall request
Would you consider adding optional:
to give
hostsfilean explicit validation and publication boundary?For my case this would solve both issues cleanly:
would not silently become an authoritative multi-A answer when strict hostname checking is enabled, while valid but router-local entries such as:
could remain in
/etc/hostswithout being published through SDNS when onlyhome.arpa.is selected.The concepts also have established precedent rather than being SDNS-specific: BIND uses
check-names, CoreDNS gives its hosts plugin explicit authoritativeZONES, PowerDNS makes/etc/hostsexport explicit, and dnsmasq constrains DHCP-generated names to an intended local domain.For a dedicated hosts file, current behaviour can remain unchanged.
For a mixed-purpose system
/etc/hosts, these options would provide a clean boundary between OS-local naming state and DNS data intentionally published to clients.All reactions