【问题标题】:How to validate DNSSEC in PHP?如何在 PHP 中验证 DNSSEC?
【发布时间】:2015-03-19 14:34:11
【问题描述】:

我一直在尝试找出一种方法来验证 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 或缺少它。

【问题讨论】:

  • 这个功能不起作用? php.net/manual/en/function.checkdnsrr.php.
  • 哦,也许吧!我根本没有找到这个功能。让我看看。
  • 哎呀,该函数返回一个布尔值,但这个函数可能更有用:php.net/manual/en/function.dns-get-record.php
  • 哈哈,我就是这么写的。我已经在用那个来读取 TXT 记录了,效果很好。但是,我现在似乎无法找出 DNSSEC 记录将存储在什么目录下。也许这就是“IN”类型?
  • 所以我最终使用 exec() 和 'host' 命令。像魅力一样工作 :) 感谢您的帮助!

标签: php


【解决方案1】:

PHP 引擎有一组它支持的固定 DNS 记录类型,全部由 typedns_get_record 的参数定义。您可以通过查看实现 DNS 查询的 engine code 来仔细检查此列表。

很遗憾,该预定义列表中没有任何 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 代码来修复Issue #39

【讨论】:

  • 你忘记了最重要的一行 - use pear\net_dns2; - 花了很长时间才弄明白
【解决方案2】:

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

然后在带有 PEAR 模块 Net_DNS2 的 php 中查找感兴趣域的 RRSIG 记录。结果应该告诉您负责该记录的区域。

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

DS 记录将来自父区域(例如,.email 代表 deviant.email),如果存在则表明该区域存在 DNSSEC。

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

我相信 Net_DNS2 使用

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

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

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

【讨论】:

    【解决方案3】:

    出于相同的目标(在 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] 信任 这意味着一切正常!

    【讨论】:

      猜你喜欢
      • 2019-10-13
      • 1970-01-01
      • 2022-08-03
      • 2017-08-20
      • 2010-12-17
      • 2011-07-30
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多