使用 PHP 获取名称服务器?

Using PHP to get nameservers?

我正在尝试获取 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 仅在域解析时才有效。如果有名称服务器,但它没有解析,它不会 return 名称服务器。

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

It looks like dns_get_record only works if a domain resolves.

取决于您如何使用函数(您实际上并没有共享代码的任何部分),以及您将什么定义为“解决”。

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

所示

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

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

像这样的高级调用会执行完整的分辨率,因此最高 child。在上述情况下,根据设计,它必须回复存在 DNS 解析错误。

如果您真的需要获取名称服务器(在 registry/parent 端),无论整个情况有多糟糕,这意味着您基本上必须自己重做递归名称服务器通常进行的所有迭代代表您,这意味着能够将特定的 DNS 数据包发送到特定的名称服务器(dns_get_record 不允许)。基本上你从根开始,然后在到达 child 时沿着树向下走,如果你想让注册管理机构发布名称服务器,你要么在那里停下来,要么回溯一个档次,以防它们自己没有正确回复.

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

我强烈建议在深入了解 DNS 的工作原理、区域划分的含义、NS 记录的工作原理、名称中的点不一定是什么之前,不要尝试做任何类似的事情区域切割,您需要采用什么保护措施,例如超时、重试(UDP 与 TCP)、向更快的名称服务器融合等等。

你没有分享很多关于你的约束、目标设置的信息,所以很难在最合适的解决方案中给你建议,希望以上能给你提示。

例如,您可以有快捷方式,如果您说“我所有的域都是 .com 和 .net”,那么例如您总是直接查询 Verisign(这两个域名的注册表)就足够了TLD) 权威名称服务器来查找授权。

绝对不要 shell 输出 运行 命令,如 dig,这在所有方面都是一个坏主意:

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

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

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

另外在另一个单独的注释中:

I'm trying to get the nameservers of multiple domains in PHP [..] which is greatly slowing down the process.

您没有分享您的设置细节,但以防万一这样,并行性显然是提高性能的第一步。每个域的每个 DNS 查询(大部分)都与其他域无关,因此您可以同时触发它们,以 10 个、100 个或更多为一组,具体取决于您的设置。您当然需要适当的设计和支持功能,即“异步 DNS 库”,它能够触发多个 DNS 查询并在结果出现时以某种方式回调您自己的代码。这样您就可以扩展,并且没有域 broken/long 分辨率应该阻止整个过程。