如何在PHP中验证DNSSEC


How to validate DNSSEC in PHP?

我一直在试图找到一种在PHP(oa1)中验证DNS记录的方法,但没有成功。

我可以使用此库验证整个域,但不能验证单个记录:https://github.com/metaregistrar/php-dnssec-validator

此外,该库只允许验证一小部分TLD。

有没有另一个图书馆可以为我处理这个问题,或者我应该研究其他什么?

我还发现:http://www.phpclasses.org/package/9031-PHP-Validate-DNSSEC-keys-and-calculate-the-DS-record.html

但我不知道如何在验证功能中使用密钥。

救命!

更新

所以,我最终使用了这个。。。

exec('host -t RRSIG ' . $domain, $output);

返回RRSIG,或不返回RRSIG时,麻烦最小。

PHP引擎支持一组固定的DNS记录类型,所有这些类型都由dns_get_recordtype参数定义。您可以通过查找实现DNS查询的引擎代码来仔细检查此列表。

不幸的是,DNSSEC记录都不在该预定义列表中。因此,您需要依赖库或外部工具。

我会使用Net_DNS2,因为它支持许多DNSSEC RR。示例:

$google = new 'Net_DNS2_Resolver(['nameservers' => ['8.8.8.8', '8.8.4.4']]);
$google->dnssec = true;
try {
    $result = $google->query('kyhwana.org', 'SSHFP');
} catch('Net_DNS2_Exception $ex) {
    die($ex->getMessage());
}
foreach ($result->answer as $answer) {
    if ($answer instanceof 'Net_DNS2_RR_SSHFP) {
        printf(
            '%s %d %s %s %d %d %s' . PHP_EOL,
            $answer->name,
            $answer->ttl,
            $answer->class,
            $answer->type,
            $answer->algorithm,
            $answer->fp_type,
            $answer->fingerprint
        );
    } else if ($answer instanceof 'Net_DNS2_RR_RRSIG) {
        printf('Signed by %s: %s' . PHP_EOL, $answer->signname, $answer->signature);
    }
}

此外:如果您的域使用ECDSA算法或SHA-256指纹(如上面的示例),那么您需要最新的Net_DNS2代码来修复问题#39。

我还没有实现代码,但在我看来,使用php来验证签名本身是一个错误。在强制使用DNSSEC的本地服务器上使用类似unbound的本地递归解析程序。

然后在php中使用PEAR模块Net_DNS2查找感兴趣域的RRSIG记录。结果应该告诉你该记录的责任区域。

在该区域中查找DNSKEY记录。如果存在,则查找DS记录。

DS记录将来自父区域(例如,异常电子邮件),如果存在,则表示该区域存在DNSSEC。

如果该区域存在DNSSEC,那么如果本地递归名称服务器强制使用DNSSEC,则该区域的所有结果都是有效的。

我相信Net_DNS2使用

r = new Net_DNS2_Resolver(array('nameservers' => array('127.0.0,1')));
r->dnssec = true;

如果DNSSEC处于活动状态(由来自父区域的DS记录指示),则Net_DNS2也将验证结果。但是使用递归解析器(最好是在Web服务器上)来强制DNSSEC可能是最安全的。

确保递归解析器没有监听公共接口,这样它就不会被用于反射放大攻击。

有着相同的目标(在PHP中验证DNSSEC),我最终得到了:

exec("drill -k root.keys -TDQ $domain SOA | grep -v '^;;'", $output);

这是在执行完整自上而下的DNSSEC验证。

你需要根密钥,你可以检索:

unbound-anchor # NB: on FreeBSD, use local-unbound-anchor for "base" version

或者";手动":

dig . dnskey > root.keys

要确认记录已完全DNSSEC验证,请检查exec输出的最后一行:

  • [S] self-sig OK这不令人满意,可能父区域中没有填充区域键
  • [B] 伪造的
  • [T] trusted这意味着一切都很好