fix(roles/bind)!: validate DNSSEC and follow the crypto policy (fix #355, fix #356) - #385
Open
NavidSassan wants to merge 3 commits into
Open
NavidSassan wants to merge 3 commits into
NavidSassan wants to merge 3 commits into
Conversation
`disable-empty-zone` takes the name of a built-in empty zone to disable (cfg_type_astring in lib/isccfg/namedconf.c), not a boolean, so `disable-empty-zone yes;` disabled a zone named "yes.", which does not exist. The boolean switch would be `empty-zones-enable`. Verified on Rocky 8, 9 and 10 (bind 9.11.36, 9.16.23, 9.18.33) with the template rendered before and after: with the role's `forward only;` named creates no automatic empty zones either way; without it, both render the same 97/97/98 empty zones and answer `dig -x 10.1.2.3` from 10.IN-ADDR.ARPA, while the control `disable-empty-zone "10.IN-ADDR.ARPA";` drops exactly that zone.
, fix #356) The template hardcoded `dnssec-validation no;` and dropped the crypto-policies include that the named.conf of the bind package carries on RHEL 8, 9 and 10. Rebuild the options block after the packaged file: same statements in the same order (secroots-file, recursing-file, geoip-directory on EL 9+, dnssec-enable yes on EL 8, the include), with the Linuxfabrik options (ACLs, forward only, forwarders, RPZ, version) grouped at the end. allow-query { localhost; } and the loopback-only listen-on are deliberately not taken over. bind__dnssec_validation (default true) renders dnssec-validation. Answers for zones forwarded to or stubbed from internal servers fail validation below a signed parent: host.corp.internal and host.corp.isc.org forwarded to a local named return SERVFAIL on bind 9.11.36, 9.16.23 and 9.18.33. The forward, stub and static-stub zones of bind__zones and the new bind__dnssec_validate_except therefore go into validate-except. BIND 9.11 rejects validate-except (unknown option), so on RHEL 8 the role asserts that nothing needs excluding. The crypto policy's disable-algorithms/disable-ds-digests only feed the validator and trust anchor loading (bin/named/server.c, lib/dns/validator.c, lib/ns/query.c in 9.18.33), so the include takes effect together with validation. Verified with the bind playbook on Rocky 8, 9 and 10 ubi-init containers: named active, local zone NOERROR, forwarded zones NOERROR, dnssec-failed.org SERVFAIL, isc.org with the ad flag, both answered without validation when bind__dnssec_validation is false; the EL 8 host with forward zones stops at the assert; rndc secroots/recursing write to /var/named/data; second run changed=0.
BIND does not create an automatic empty zone (RFC 6303) for a name it
would forward with policy `only` (bin/named/server.c in 9.18.33), and
the global `forward only` plus forwarders covers every name. named
therefore created none of its 97/98 empty zones, and reverse lookups
for private and special-use addresses went to the forwarders: a logging
forwarder received 5.2.42.10.in-addr.arpa, 7.7.168.192.in-addr.arpa and
1.0.16.172.in-addr.arpa on bind 9.11.36, 9.16.23 and 9.18.33, also with
a 1.42.10.in-addr.arpa zone in bind__zones. `empty-zones-enable yes`
does not change that; `forward first` does, but falls back to iterative
resolution when the forwarders fail.
Render a `type forward; forwarders { };` zone for each name of BIND's
empty_zones[] list, which switches forwarding off for that name only and
lets named create the empty zone. resolver.arpa is only in the 9.18
list, 0.in-addr.arpa and the ::1 reverse zone are defined by
named.rfc1912.zones. Skipped are names that bind__zones defines (a
duplicate zone is an error) and the parents of forward and stub zones
in bind__zones, since an empty zone answered 10.99.0.1 with NXDOMAIN
instead of passing it to the forwarders of a 99.10.in-addr.arpa zone.
Verified on Rocky 8, 9 and 10 against a logging forwarder: private
reverse lookups (10/8, 172.17/16, 100.64/10, 169.254/16, fd00::/8,
fe80::/10) answered NXDOMAIN from the empty zones, master zones in
bind__zones answered from their files, a forward zone and its parent
still forwarded, public PTR and A lookups still forwarded, never
resolved iteratively. The bind playbook answers `dig -x 10.1.2.3` from
10.IN-ADDR.ARPA and the second run reports changed=0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The
bindrole validates DNSSEC and follows the system-wide crypto policy, like thenamed.confthe bind package ships on RHEL 8, 9 and 10. Breaking, see below.dnssec-validation yesby default, switchable withbind__dnssec_validation. Answers for zones that named forwards to or stubs from internal servers fail validation below a signed parent (.internal, or a subdomain of a signed public domain), so theforward,stubandstatic-stubzones inbind__zonesgo intovalidate-exceptautomatically; other zones can be listed inbind__dnssec_validate_except. BIND 9.11 on RHEL 8 has novalidate-except, so the role stops there with a clear message if anything needs excluding.include "/etc/crypto-policies/back-ends/bind.config", plussecroots-file,recursing-file,geoip-directory(RHEL 9/10) anddnssec-enable yes(RHEL 8). The template now follows the packaged file's statements and order, with the Linuxfabrik options (ACLs,forward only, forwarders, RPZ,version) grouped at the end.allow-query { localhost; }and the loopback-onlylisten-onare deliberately not taken over.disable-empty-zone yes;, which takes a zone name, not a boolean, and had no effect.forward onlykept named from creating any of them, so these lookups went to the forwarders. The template switches forwarding off for exactly these zones (type forward; forwarders { };), except for zones thatbind__zonesdefines and parents offorward/stubzones inbind__zones.Test
No Molecule scenario exists for
bind; verified with thebindplaybook against Rocky 8, 9 and 10ubi-initcontainers, each with a primary zone and a second named on port 5300 servingcorp.internalandcorp.isc.orgas forward zones:dnssec-failed.orgSERVFAIL,isc.orgwith theadflagbind__dnssec_validation: false: forward zones anddnssec-failed.orgresolvenamed-checkconf -pshows the policy'sdisable-algorithms,rndc secroots/rndc recursingwrite to/var/named/data/, second runchanged=0disable-empty-zoneremoval: identical automatic empty zones before and after on BIND 9.11, 9.16 and 9.18, with a control that drops one zonebind__zonesanswered from their files, a forward zone below172.16.0.0/16and its parent still forwarded, public lookups still forwarded and never resolved iterativelyNot covered: a real RHEL host with SELinux enforcing.
Breaking Changes
named validates DNSSEC, so forged or broken answers for signed zones are answered with
SERVFAIL. Internal zones below a signed domain or TLD that named does not get from aforwardorstubzone inbind__zones(for example viabind__named_conf_raw) have to be listed inbind__dnssec_validate_except, or setbind__dnssec_validation: false. On RHEL 8 with forward or stub zones, setbind__dnssec_validation: false.