看懂这篇文章可能需要的前置知识 DNS ,不对称加密,数字摘要,数字签名
DNSSEC(DNS Security Extensions) 域名系统安全扩展。 开启DNSSEC,可有效防止DNS欺骗和缓存污染等攻击。 它是通过数字签名来保证DNS应答报文的真实性和完整性。
一般的 DNS
查询 A 记录 -> 返回 A 记录的值
启用了 DNSSEC 的 DNS
查询 A 记录 -> 返回 A 记录的值和 A 记录的 RRSIG
DNSSEC 大致的验证流程
检查网站对 DNSSEC 的支持
现在的 DNSSEC 至少有 8 种记录类型
下面几个小节主要是描述响应报文里的 Answer 的 RDATA
Algorithm 的列表 https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
rfc 4034 里明确的表示不建议使用 RSA/MD5 作为加密算法
KeyTag 的生成方式
伪代码
unsigned int
keytag (
unsigned char key[], /* the RDATA part of the DNSKEY RR */
unsigned int keysize /* the RDLENGTH */
)
{
unsigned long ac; /* assumed to be 32 bits or larger */
int i; /* loop index */
for ( ac = 0, i = 0; i < keysize; ++i )
ac += (i & 1) ? key[i] : key[i] << 8;
ac += (ac >> 16) & 0xFFFF;
return ac & 0xFFFF;
}
php
$flags = 257;
$protocol = 3;
$algorithm = 13;
$publicKey = 'mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==';
$bin = pack('nCC', $flags, $protocol, $algorithm);
$bin .= base64_decode($publicKey);
$keytag = array_sum(unpack('n*', $bin));
$keytag += ($keytag >> 16) & 0xFFFF;
$keytag = $keytag & 0xFFFF;
Digest 的生成方式
伪代码
digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
php
$domainName = 'nslookup.io.';
$flags = 257;
$protocol = 3;
$algorithm = 13;
$publicKey = 'mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==';
$publicKey = base64_decode($publicKey);
$domainNameBin = '';
foreach (explode('.', $domainName) as $part) {
$domainNameBin .= pack('C', strlen($part));
$domainNameBin .= $part;
}
if (substr($domainName, -1) !== '.') {
$domainNameBin .= pack('C', 0);
}
$rdata = pack('nCC', $flags, $protocol, $algorithm);
$rdata .= $publicKey;
$data = $domainNameBin . $rdata;
$digest_algo = 'sha256';
$digest = openssl_digest($data, $digest_algo);
Windows 的 nslookup 不支持 DNSSEC 的记录查询。
PowerShell 的 cmdlet Resolve-DnsName 支持 DNSSEC 的记录查询。
Resolve-DnsName www.nslookup.io -type A -DnssecOk -server 8.8.8.8
最好还是用 dig 命令来检测 DNSSEC 。
dig @8.8.8.8 www.nslookup.io +dnssec