Consider the following scenario:
example.com
is hosted on CloudFlare and it's signed by CloudFlare DNSSEC. Everything works as expected for example.com
.
Inside the company we have some internal privates zones, for Active Directory and a Unix Domain: ad.example.com
and unix.example.com
.
Since I cannot enable opt-out for those zones on example.com
I just enabled DNSSEC for the internal zones. On unix.example.com
everything appears to be working as expected. But on ad.example.com
nothing works.
Basically the chain of trust is broken on the internal nameservers:
Jul 2 20:36:14 idm1 named-pkcs11[4345]: broken trust chain resolving 'wpad.ad.example.com/A/IN': 172.21.1.2#53
Jul 2 20:36:17 idm1 named-pkcs11[4345]: validating dc1.ad.example.com/A: bad cache hit (dc1.ad.example.com/DS)
Jul 2 20:36:17 idm1 named-pkcs11[4345]: broken trust chain resolving 'dc1.ad.example.com/A/IN': 172.21.1.2#53
Jul 2 20:37:18 idm1 named-pkcs11[4345]: validating ad.example.com/SOA: got insecure response; parent indicates it should be secure
Jul 2 20:37:18 idm1 named-pkcs11[4345]: no valid RRSIG resolving 'dc1.ad.example.com/DS/IN': 172.21.1.2#53
Jul 2 20:37:18 idm1 named-pkcs11[4345]: validating ad.example.com/SOA: got insecure response; parent indicates it should be secure
Jul 2 20:37:18 idm1 named-pkcs11[4345]: no valid RRSIG resolving 'dc1.ad.example.com/DS/IN': 172.21.1.3#53
Jul 2 20:37:18 idm1 named-pkcs11[4345]: no valid DS resolving 'dc1.ad.example.com/A/IN': 172.21.1.2#53
Jul 2 20:37:18 idm1 named-pkcs11[4345]: validating dc1.ad.example.com/A: bad cache hit (dc1.ad.example.com/DS)
Jul 2 20:37:18 idm1 named-pkcs11[4345]: broken trust chain resolving 'dc1.ad.example.com/A/IN': 172.21.1.3#53
I'm aware that I need to add DS records on the parent zone, so I added two entries on CloudFlare for ad.example.com
and one for unix.example.com
.
The DS entries where generated from a Linux machine with the following commands:
For unix.example.com
:
dig unix.example.com. DNSKEY @172.21.1.5 > dnskey-unix.txt
dnssec-dsfromkey -f dnskey-unix.txt -2 unix.example.com
Then I added the following DS register on CloudFlare:
unix.example.com. IN DS 54355 8 2 3658D593EF31ED0E9D2369DF09D63F9B48FB5CD25A1AA336A2E4EE0AF55150AE
For ad.example.com
:
dig ad.example.com. DNSKEY @172.21.1.2 > dnskey-ad.txt
dnssec-dsfromkey -f dnskey-ad.txt -2 ad.example.com
The same for unix.example.com
, I've added the following on CloudFlare
ad.example.com. IN DS 63807 13 2 32D219185C727AE506B5565D522728D1B3A8677F737B07EC3BFEC2092B96F737
ad.example.com. IN DS 39922 13 2 000525D1A95F86820CA668D91E952BCCFA7000A5364A3E30AC43D3ACCDB62DAD
Since AD uses two separate zones I generated the DS entries for _msdcs.ad.example.com
too:
dig _msdcs.ad.example.com. DNSKEY @172.21.1.2 > dnskey-ad-msdcs.txt
dnssec-dsfromkey -f dnskey-ad-msdcs.txt -2 _msdcs.ad.example.com
And added the results to it's parent zone: ad.example.com
:
_msdcs.ad.example.com. IN DS 19659 13 2 9F1D143D601B976F05EAB6C1C14C998537B80511349B7BDEB0CFFE2A0882DAF3
_msdcs.ad.example.com. IN DS 14682 13 2 4B72A44979E24321724D870E17E85D7099260132A1645F236511F4FC545B98E8
And that's it. I tough this implementation would be correct, but this is not what's happening. For machines on the unix.example.com
domain it's OK:
[root@idm1 ~]# dig +dnssec A idm1.unix.example.com
; <<>> DiG 9.11.13-RedHat-9.11.13-3.el8 <<>> +dnssec A idm1.unix.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21833
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 3
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
; COOKIE: 203752b5a85d2bb2c796f55b5efe71f71401f1abaf39c190 (good)
;; QUESTION SECTION:
;idm1.unix.example.com. IN A
;; ANSWER SECTION:
idm1.unix.example.com. 1200 IN A 172.21.1.5
idm1.unix.example.com. 1200 IN RRSIG A 8 5 1200 20200724170015 20200702220913 24543 unix.example.com. kVOJD49rzVaQLtLBdxyUTU2E+1CQscSClWjs7RgGj0nMAg/6Va1GEw0j jlDl2s1FOKxbJCN7g50UT+MjgTPkgQozwUPOBYeaKB6npTrROwZH3vBG yT346elPNP7x5fRO41ATUrf22PauCvo73+1+iTmTsizxVwda8u88H5Ld CD4+laE9GphuHdc2usITGaKze4UBwA81ExN2UpwOJYPhyHFzOAF3oBg8 XCPoJxQhgHNmkCAmTZCmWeD+kPkyaMSv9clF/23lZ9YJ+cICHtCzWWTM yEC7988sAk2MVIzptF0OYQ+TzsVDxcM8TPlhZNZAz+SE3hVPalY31TUc bm+DiQ==
;; AUTHORITY SECTION:
unix.example.com. 86400 IN NS idm2.unix.example.com.
unix.example.com. 86400 IN NS idm1.unix.example.com.
unix.example.com. 86400 IN RRSIG NS 8 4 86400 20200728184956 20200702220913 24543 unix.example.com. iVLmN9NkjI08NPMObfhDFh2csUnMkEmFTi0UhphhedbL2wFc1MsP37gS lwSXK8gjPiopC1gbfRj9d0BwG6fJCrc9+1DUnUMKDqqpsr2/U3prOJWs 70l+4m1S6OI5vemhGMZuSzfPW7hGnPCY3xzYnzMJ3atvPwBJzG5tx2Rd V59sYgJBc7LDZxhGJxxtc5V2cNbCo6q51zoDV8OeDMaBK5n6shhnbpOq 3mlTC757vYxzwl8akvWDvQtgTJhZKuye+PSBn3dyqIcoSr6ZG/Ymm23n l89DzpvNVwRw0xtw7lmvQWsj0w1RefPwKG9sytGjCNw9CZ30IIeqvE+o hPP3Gw==
;; ADDITIONAL SECTION:
idm2.unix.example.com. 1200 IN A 172.21.1.6
idm2.unix.example.com. 1200 IN RRSIG A 8 5 1200 20200718050002 20200702220913 24543 unix.example.com. RSKi/wms8XQevqzqY/EnvApSKY4cMvTwZtPImyngb8EJ/ONBfljkZDrj YTIh36fg8UnDE4WeaDjhrLAEV0/7T5f1udC/Eje0i7ezH7F301/8qaQ9 1BHWOoK+viwisa5w4ywZMq6mTcZCGs+RpgudIcczkW4RlmW/zpRnqYjq f/U4a5GEXV64s7Nc7ZfMxvssM9r1QknX3XC8yWKPlgjCRn/be03bhA+z UNfNpBU1684q1/hTJ0f+d0BFtb1ZNkZ2TIceXCDIum8UQCEsH6XLjtYI x4TnKUtG7WVL65xKc7SecZY1v/Ew9hMtnmF42+9rV95Rj2vGdA+QJF98 8H1xJw==
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jul 02 20:47:03 -03 2020
;; MSG SIZE rcvd: 1079
But not for machines on ad.example.com
:
[root@idm1 ~]# dig +dnssec A dc1.ad.example.com
; <<>> DiG 9.11.13-RedHat-9.11.13-3.el8 <<>> +dnssec A dc1.ad.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 9918
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
; COOKIE: 2c9efcfef9cb965cfc1898755efe7260ec5a94eb75e18a03 (good)
;; QUESTION SECTION:
;dc1.ad.example.com. IN A
;; Query time: 2 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jul 02 20:48:48 -03 2020
;; MSG SIZE rcvd: 83
Another relevant information; the name servers on the Unix domain are configured as forward only to the zones on AD, and vice-versa.
Questions:
- I'm not sure if I can set DNSSEC this way.
- On CloudFlare there's obviously no NS entries for the internal zones, they should not be visible from outside, although there's the DS entires for
ad.example.com
andunix.example.com
; is this supported?
Thanks!
EDIT: I figured additional information with the help of @PatrickMevzek in the comments.
Windows DNS Server wasn't validating DNSSEC. I had to manually enable it with command:
DnsCmd.exe /Config /enablednssec 1
Fetched the Root Trust Anchors after a
Restart-Service DNS
, with the command:DnsCmd.exe /RetrieveRootTrustAnchors
After this two commands on both dc1
and dc2
; Linux's BIND9 was able to resolve the addresses without complaining about broken trust. It wasn't necessary to add the NS entries on CloudFlare.
But I have another issue when trying to validate on Windows DNS Servers; when using delv
with +vtrace
on BIND9 it works as expected:
[root@idm1 ~]# delv +vtrace dc1.ad.example.com.br @172.21.1.5
;; fetch: dc1.ad.example.com.br/A
;; validating dc1.ad.example.com.br/A: starting
;; validating dc1.ad.example.com.br/A: attempting positive response validation
;; fetch: ad.example.com.br/DNSKEY
;; validating ad.example.com.br/DNSKEY: starting
;; validating ad.example.com.br/DNSKEY: attempting positive response validation
;; fetch: ad.example.com.br/DS
;; validating ad.example.com.br/DS: starting
;; validating ad.example.com.br/DS: attempting positive response validation
;; fetch: example.com.br/DNSKEY
;; validating example.com.br/DNSKEY: starting
;; validating example.com.br/DNSKEY: attempting positive response validation
;; fetch: example.com.br/DS
;; validating example.com.br/DS: starting
;; validating example.com.br/DS: attempting positive response validation
;; fetch: com.br/DNSKEY
;; validating com.br/DNSKEY: starting
;; validating com.br/DNSKEY: attempting positive response validation
;; fetch: com.br/DS
;; validating com.br/DS: starting
;; validating com.br/DS: attempting positive response validation
;; fetch: br/DNSKEY
;; validating br/DNSKEY: starting
;; validating br/DNSKEY: attempting positive response validation
;; fetch: br/DS
;; validating br/DS: starting
;; validating br/DS: attempting positive response validation
;; fetch: ./DNSKEY
;; validating ./DNSKEY: starting
;; validating ./DNSKEY: attempting positive response validation
;; validating ./DNSKEY: verify rdataset (keyid=20326): success
;; validating ./DNSKEY: signed by trusted key; marking as secure
;; validating br/DS: in fetch_callback_validator
;; validating br/DS: keyset with trust secure
;; validating br/DS: resuming validate
;; validating br/DS: verify rdataset (keyid=46594): success
;; validating br/DS: marking as secure, noqname proof not needed
;; validating br/DNSKEY: in dsfetched
;; validating br/DNSKEY: dsset with trust secure
;; validating br/DNSKEY: verify rdataset (keyid=2471): success
;; validating br/DNSKEY: marking as secure (DS)
;; validating com.br/DS: in fetch_callback_validator
;; validating com.br/DS: keyset with trust secure
;; validating com.br/DS: resuming validate
;; validating com.br/DS: verify rdataset (keyid=33739): success
;; validating com.br/DS: marking as secure, noqname proof not needed
;; validating com.br/DNSKEY: in dsfetched
;; validating com.br/DNSKEY: dsset with trust secure
;; validating com.br/DNSKEY: verify rdataset (keyid=33095): success
;; validating com.br/DNSKEY: marking as secure (DS)
;; validating example.com.br/DS: in fetch_callback_validator
;; validating example.com.br/DS: keyset with trust secure
;; validating example.com.br/DS: resuming validate
;; validating example.com.br/DS: verify rdataset (keyid=33095): success
;; validating example.com.br/DS: marking as secure, noqname proof not needed
;; validating example.com.br/DNSKEY: in dsfetched
;; validating example.com.br/DNSKEY: dsset with trust secure
;; validating example.com.br/DNSKEY: verify rdataset (keyid=2371): success
;; validating example.com.br/DNSKEY: marking as secure (DS)
;; validating ad.example.com.br/DS: in fetch_callback_validator
;; validating ad.example.com.br/DS: keyset with trust secure
;; validating ad.example.com.br/DS: resuming validate
;; validating ad.example.com.br/DS: verify rdataset (keyid=34505): success
;; validating ad.example.com.br/DS: marking as secure, noqname proof not needed
;; validating ad.example.com.br/DNSKEY: in dsfetched
;; validating ad.example.com.br/DNSKEY: dsset with trust secure
;; validating ad.example.com.br/DNSKEY: no RRSIG matching DS key
;; validating ad.example.com.br/DNSKEY: verify rdataset (keyid=63807): success
;; validating ad.example.com.br/DNSKEY: marking as secure (DS)
;; validating dc1.ad.example.com.br/A: in fetch_callback_validator
;; validating dc1.ad.example.com.br/A: keyset with trust secure
;; validating dc1.ad.example.com.br/A: resuming validate
;; validating dc1.ad.example.com.br/A: verify rdataset (keyid=3675): success
;; validating dc1.ad.example.com.br/A: marking as secure, noqname proof not needed
; fully validated
dc1.ad.example.com.br. 3556 IN A 172.21.1.2
dc1.ad.example.com.br. 3556 IN RRSIG A 8 5 3600 20200713013625 20200703003625 3675 ad.example.com.br. Ov1CyF1c7p7NoYWGx041NG76lXEI3gCMYECklGYSd5pqQDpgHP1P7Tuc 9/6WulDJBaHW0FAvAiclpH1M7xmzsSEHmTamnuMeHDP6zsgXTu7dmRr4 YLwH5lidELNt1wFffNfDFu6/xHuQcxWppgqf8so1zBhz/+TYQKFbvs+/ zOs=
But when I do the same query on Windows DNS Server it fails completely with a broken trust error:
[root@idm1 ~]# delv +vtrace dc1.ad.example.com.br @172.21.1.2
;; fetch: dc1.ad.example.com.br/A
;; validating dc1.ad.example.com.br/A: starting
;; validating dc1.ad.example.com.br/A: attempting positive response validation
;; fetch: ad.example.com.br/DNSKEY
;; validating ad.example.com.br/DNSKEY: starting
;; validating ad.example.com.br/DNSKEY: attempting positive response validation
;; fetch: ad.example.com.br/DS
;; chase DS servers resolving 'ad.example.com.br/DS/IN': 172.21.1.2#53
;; fetch: example.com.br/NS
;; validating example.com.br/NS: starting
;; validating example.com.br/NS: attempting positive response validation
;; fetch: example.com.br/DNSKEY
;; validating example.com.br/DNSKEY: starting
;; validating example.com.br/DNSKEY: attempting positive response validation
;; fetch: example.com.br/DS
;; validating example.com.br/DS: starting
;; validating example.com.br/DS: attempting positive response validation
;; fetch: com.br/DNSKEY
;; validating com.br/DNSKEY: starting
;; validating com.br/DNSKEY: attempting positive response validation
;; fetch: com.br/DS
;; validating com.br/DS: starting
;; validating com.br/DS: attempting positive response validation
;; fetch: br/DNSKEY
;; validating br/DNSKEY: starting
;; validating br/DNSKEY: attempting positive response validation
;; fetch: br/DS
;; validating br/DS: starting
;; validating br/DS: attempting positive response validation
;; fetch: ./DNSKEY
;; validating ./DNSKEY: starting
;; validating ./DNSKEY: attempting positive response validation
;; validating ./DNSKEY: verify rdataset (keyid=20326): success
;; validating ./DNSKEY: signed by trusted key; marking as secure
;; validating br/DS: in fetch_callback_validator
;; validating br/DS: keyset with trust secure
;; validating br/DS: resuming validate
;; validating br/DS: verify rdataset (keyid=46594): success
;; validating br/DS: marking as secure, noqname proof not needed
;; validating br/DNSKEY: in dsfetched
;; validating br/DNSKEY: dsset with trust secure
;; validating br/DNSKEY: verify rdataset (keyid=2471): success
;; validating br/DNSKEY: marking as secure (DS)
;; validating com.br/DS: in fetch_callback_validator
;; validating com.br/DS: keyset with trust secure
;; validating com.br/DS: resuming validate
;; validating com.br/DS: verify rdataset (keyid=33739): success
;; validating com.br/DS: marking as secure, noqname proof not needed
;; validating com.br/DNSKEY: in dsfetched
;; validating com.br/DNSKEY: dsset with trust secure
;; validating com.br/DNSKEY: verify rdataset (keyid=33095): success
;; validating com.br/DNSKEY: marking as secure (DS)
;; validating example.com.br/DS: in fetch_callback_validator
;; validating example.com.br/DS: keyset with trust secure
;; validating example.com.br/DS: resuming validate
;; validating example.com.br/DS: verify rdataset (keyid=33095): success
;; validating example.com.br/DS: marking as secure, noqname proof not needed
;; validating example.com.br/DNSKEY: in dsfetched
;; validating example.com.br/DNSKEY: dsset with trust secure
;; validating example.com.br/DNSKEY: verify rdataset (keyid=2371): success
;; validating example.com.br/DNSKEY: marking as secure (DS)
;; validating example.com.br/NS: in fetch_callback_validator
;; validating example.com.br/NS: keyset with trust secure
;; validating example.com.br/NS: resuming validate
;; validating example.com.br/NS: verify rdataset (keyid=34505): success
;; validating example.com.br/NS: marking as secure, noqname proof not needed
;; validating ad.example.com.br/DNSKEY: in dsfetched
;; validating ad.example.com.br/DNSKEY: falling back to insecurity proof (SERVFAIL)
;; validating ad.example.com.br/DNSKEY: checking existence of DS at 'br'
;; validating ad.example.com.br/DNSKEY: checking existence of DS at 'com.br'
;; validating ad.example.com.br/DNSKEY: checking existence of DS at 'example.com.br'
;; validating ad.example.com.br/DNSKEY: checking existence of DS at 'ad.example.com.br'
;; fetch: ad.example.com.br/DS
;; chase DS servers resolving 'ad.example.com.br/DS/IN': 172.21.1.2#53
;; fetch: example.com.br/NS
;; validating example.com.br/NS: starting
;; validating example.com.br/NS: attempting positive response validation
;; validating example.com.br/NS: keyset with trust secure
;; validating example.com.br/NS: verify rdataset (keyid=34505): success
;; validating example.com.br/NS: marking as secure, noqname proof not needed
;; validating ad.example.com.br/DNSKEY: in dsfetched2: SERVFAIL
;; no valid DS resolving 'ad.example.com.br/DNSKEY/IN': 172.21.1.2#53
;; validating dc1.ad.example.com.br/A: in fetch_callback_validator
;; validating dc1.ad.example.com.br/A: fetch_callback_validator: got SERVFAIL
;; broken trust chain resolving 'dc1.ad.example.com.br/A/IN': 172.21.1.2#53
;; resolution failed: broken trust chain
0 Answers