使用 PHP 获取名称服务器?

时间:2021-07-06 18:17:20

标签: php dns

我正在尝试在 PHP 中获取多个域的名称服务器,但对于某些域我不断收到此错误:

PHP Warning:  dns_get_record(): A temporary server error occurred

例如,域 fightthesmears.com 给出了该错误,这大大减慢了进程。

该域确实设置了名称服务器:

Name Server: ns-78.awsdns-09.com
Name Server: ns-1526.awsdns-62.org
Name Server: ns-693.awsdns-22.net
Name Server: ns-1900.awsdns-45.co.uk

看起来 dns_get_record 仅在域解析时才有效。如果有域名服务器,但没有解析,则不会返回域名服务器。

有没有更快、更可靠的方法来使用 PHP 获取域名服务器?

1 个答案:

答案 0 :(得分:0)

<块引用>

看起来 dns_get_record 只有在域解析时才有效。

取决于您如何使用该函数(您实际上并未共享代码的任何部分),以及您定义的“解析”。

您用作示例的特定域处于蹩脚的委托状态,如https://dnsviz.net/d/fightthesmears.com/YOS1HA/dnssec/

因此,任何单个 DNS 调用都会迭代地解析从根节点到子节点的每个节点,这些节点会回复“REFUSED”,因此整个域似乎无法解析。

首先,如果您确实需要查询名称服务器,您必须在 DNS_NS 中正确使用 dns_get_record 类型。但这还不够。

像这样的高级别调用可以实现完整分辨率,这取决于孩子。在上述情况下,根据设计,它必须回复存在 DNS 解析错误。

如果您真的需要获取域名服务器(在注册中心/父端),无论整个情况有多严重,这意味着您基本上必须重做递归域名服务器通常代表您进行的所有迭代,这意味着能够将特定的 DNS 数据包发送到特定的名称服务器(dns_get_record 不允许)。基本上,您从根开始,然后在到达子节点时沿着树走下去,如果您想让注册管理机构发布名称服务器,以防它们本身无法正确回复,您可以停在那里或回溯一个档次。

基本上就是所谓的“寻找区域切割”。例如,您可以在 RFC 7816 附录 A 中找到此类算法。

我强烈建议在完全掌握 DNS 的工作原理、区域切割的含义、NS 记录的工作原理、名称中的点不一定是区域之前不要尝试这样做切,您需要采用哪些保护措施,例如超时、重试(UDP 与 TCP)、向更快的名称服务器收敛等。

您没有分享很多关于您的限制、目标设置的信息,因此很难为您提供最合适的解决方案,希望以上内容能给您一些提示。

例如,您可以设置快捷方式,如果您说“我的所有域都是 .com 和 .net”,那么例如它可能足以让您始终直接查询 Verisign(这两个 TLD 的注册机构)权威域名服务器来查找代表团。

绝对不要去运行像 dig 这样的命令,这在所有方面都是一个坏主意:

  • 在维护/部署方面,您现在必须将 dig 安装在您希望软件运行的系统上,这是一种假设,可能不正确且不受您的控制,
  • 在性能方面,你会受到很大的打击(特别是如果不小心的话,经常可以看到从 PHP 到 shell,然后从 shell 到 dig 的 fork;每个 fork 都可能代价高昂)< /li>
  • 在安全方面,您将面临大量关于引用、转义、参数扩展等问题,基本上是各种 XRF 类型的攻击,
  • 在编程方面,运行 dig(发送 DNS 查询)是没有意义的,因为任何相关的编程语言作为至少一个能够发送 DNS 数据包的 DNS 库(因为在基础上有没有什么特别的或比较不比 TLS 更复杂让我们说:DNS 在 TCP 和 UDP 套接字中使用端口 53 上的二进制数据包,所以这只是解析和构​​建它们的问题,而不是核心协议部分的火箭科学) ;当然 dig 是供人类消费的,所以尝试以任何方式解析其输出绝对是不明智的(应该避免任何这样做的库,因为它保证在升级 {{1 }},保证在任何时候都会在各种 dig 边缘情况下以非有趣和无法描述的方式中断 - 例如 IDN 处理在 dig 版本之间发生变化 - 并且基本上避免编写一些“简单的" 用于 DNS 协议的二进制编码/解码器,因为它应该完成并依赖于一个错误的假设,即解析人工定制的输出 - 这就是 dig 给出的 - 使用正则表达式是一切的解决方案。

引用 whois 输出时的另一个单独点,实际上有两点:

  • 理论上,whois 和 DNS 是分开的;您应该在两者中看到相同的数据(关于名称服务器),但可能无法保证;所以理论上最好从 DNS 中获取名称服务器数据...但在某些情况下 whois 可能是一个足够好的解决方法,如果您认为它受到注册管理机构的严重速率限制,并且格式变化很大(您不是告诉我们您关注哪些 TLD),这就引出了第二点:
  • 对于此类情况,请使用 RDAP,而不是 whois;它是它的哲学继承者;它提供了相同的数据(甚至更多),但有一个很大的好处:答案是结构化的,因为它是 JSON,与使用自由格式文本的 whois 相反。

另外一个单独的注释:

<块引用>

我试图在 PHP [..] 中获取多个域的名称服务器,这大大减慢了进程。

您不会分享设置的详细信息,但在这种情况下,并行化显然是提高性能的第一步。每个域的每个 DNS 查询(大部分)都与其他域无关,因此您可以同时触发它们,批量为 10、100 或更多,具体取决于您的设置。您当然需要适当的设计和支持功能,即“异步 DNS 库”,它能够触发多个 DNS 查询并在结果到来时以某种方式回调您自己的代码。这样您就可以进行扩展,并且没有域损坏/长解析应该阻止整个过程。