![为什么权威名称服务器不对其自己的结果进行 DNSSEC 验证?](https://linux22.com/image/772527/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9D%83%E5%A8%81%E5%90%8D%E7%A7%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8D%E5%AF%B9%E5%85%B6%E8%87%AA%E5%B7%B1%E7%9A%84%E7%BB%93%E6%9E%9C%E8%BF%9B%E8%A1%8C%20DNSSEC%20%E9%AA%8C%E8%AF%81%EF%BC%9F.png)
如果我向名称服务器查询一条具有权威性的记录,则答案似乎未通过 DNSSEC 验证:
$ dig cloudflare.com @ns3.cloudflare.com
; <<>> DiG 9.16.22-Debian <<>> cloudflare.com @ns3.cloudflare.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28361
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;cloudflare.com. IN A
;; ANSWER SECTION:
cloudflare.com. 300 IN A 104.16.133.229
cloudflare.com. 300 IN A 104.16.132.229
;; Query time: 3 msec
;; SERVER: 162.159.0.33#53(162.159.0.33)
;; WHEN: Sat Nov 20 15:29:00 CET 2021
;; MSG SIZE rcvd: 75
没有返回“ad”标志,因此答案未通过 DNSSEC 验证。如果我向非权威服务器询问相同的查询,则会返回“ad”标志:
$ dig cloudflare.com @1.1.1.1
; <<>> DiG 9.16.22-Debian <<>> cloudflare.com @1.1.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23361
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;cloudflare.com. IN A
;; ANSWER SECTION:
cloudflare.com. 145 IN A 104.16.132.229
cloudflare.com. 145 IN A 104.16.133.229
;; Query time: 3 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Sat Nov 20 15:35:35 CET 2021
;; MSG SIZE rcvd: 75
你能告诉我吗:
- 这是一个正确且定义明确的行为吗?
- 没有进行验证的原因是什么?
- 我可以通过
ISC bind9
配置来改变这种行为吗?怎么做?
(如果这种行为是故意的,就永远不应该将名称服务器配置为使用其自己的名称服务器软件来解析,因为对于某些客户端软件来说,答案是否得到验证是有区别的:我想知道为什么记录不能从名称服务器本身SSHFP
进行工作)。ssh -o VerifyHostKeyDNS <host>
答案1
为什么权威名称服务器不对其自己的结果进行 DNSSEC 验证?
因为它不能,除非它本身就是一个递归名称服务器,否则就很糟糕。
要完全验证 DNSSEC,您需要从根开始并遍历DS
/DNSKEY
记录的整个链接,而您咨询的权威解析器并不是对所有这些都具有权威性,只是对链接下的部分具有权威性。
例如,参见 RFC 4033 第 6 节“解析器考虑”:
安全感知解析器必须能够使用至少强制实施的算法执行验证数字签名所需的加密功能。安全感知解析器还必须能够形成从新学习区域到身份验证密钥的身份验证链,如上所述。此过程可能需要对中间 DNS 区域进行额外查询,以获取必要的 DNSKEY、DS 和 RRSIG 记录。安全感知解析器应配置至少一个信任锚作为起点,它将从该点尝试建立身份验证链。
以及 RFC 4035,第 3.2.3 节“递归名称服务器”下的“AD 位”:
安全感知递归名称服务器的名称服务器端不得在响应中设置 AD 位,除非名称服务器认为响应的 Answer 和 Authority 部分中的所有 RRset 都是真实的。当且仅当解析器端认为 Answer 部分中的所有 RRset 和 Authority 部分中的任何相关否定响应 RR 都是真实的时,名称服务器端才应设置 AD 位。解析器端必须遵循第 5 节中描述的过程来确定相关 RR 是否真实。但是,为了向后兼容,当响应包含未签名的 CNAME RR 时,如果这些 CNAME RR 明显可以从真实的 DNAME RR 合成,并且根据 [RFC2672] 中描述的合成规则,该 DNAME RR 也包含在响应中,则递归名称服务器可以设置 AD 位。
至于:
答案是否得到验证很重要
当然可以,这就是 DNSSEC 的全部目的。但最终客户端在正常操作过程中不会直接咨询权威名称服务器。他们使用递归名称服务器,该服务器依次遍历各种不同的权威名称服务器以获取最终答复,并且如果配置为这样做,它可以验证 DNSSEC。
我想知道为什么 SSHFP 记录无法从名称服务器本身执行 ssh -o VerifyHostKeyDNS
您在此处遇到的任何问题都与上述任何问题都无关。ssh
应该使用配置的任何操作系统级别解析器来获取数据。
看https://github.com/openssh/libopenssh/blob/05dfdd5f54d9a1bae5544141a7ee65baa3313ecd/ssh/dns.c#L191该函数内部verify_host_key_dns
:
result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
DNS_RDATATYPE_SSHFP, 0, &fingerprints);
if (result) {
verbose("DNS lookup error: %s", dns_result_totext(result));
return -1;
}
if (fingerprints->rri_flags & RRSET_VALIDATED) {
*flags |= DNS_VERIFY_SECURE;
debug("found %d secure fingerprints in DNS",
fingerprints->rri_nrdatas);
} else {
debug("found %d insecure fingerprints in DNS",
fingerprints->rri_nrdatas);
}
并getrrsetbyname
定义在https://github.com/openssh/openssh-portable/blob/2dc328023f60212cd29504fc05d849133ae47355/openbsd-compat/getrrsetbyname.c并且基本上是一个包装器,res_query
它是用于执行 DNS 查询的低级 libc 绑定。
我发现https://weberblog.net/sshfp-authenticate-ssh-fingerprints-via-dnssec/关于是否经过ssh
验证的(DNSSEC)记录之间的行为的一些细节。SSHFP