dns_get_record

(PHP 5, PHP 7, PHP 8)

dns_get_record获取与主机名关联的 DNS 资源记录

说明

dns_get_record(
    字符串 $hostname,
    整数 $type = DNS_ANY,
    数组 &$authoritative_name_servers = null,
    数组 &$additional_records = null,
    布尔值 $raw = false
): 数组|false

获取与给定 $hostname 关联的 DNS 资源记录。

参数

hostname

hostname 应该是一个有效的 DNS 主机名,例如 "www.example.com"。可以使用 in-addr.arpa 符号生成反向查找,但对于大多数反向查找,gethostbyaddr() 更适合。

注意:

根据 DNS 标准,电子邮件地址以 user.host 格式给出(例如:hostmaster.example.com 而不是 [email protected]),请确保检查此值并在使用诸如 mail() 之类的函数之前进行必要的修改。

type

默认情况下,dns_get_record() 将搜索与 hostname 关联的任何资源记录。要限制查询,请指定可选的 type 参数。可以是以下任何一个:DNS_ADNS_CNAMEDNS_HINFODNS_CAADNS_MXDNS_NSDNS_PTRDNS_SOADNS_TXTDNS_AAAADNS_SRVDNS_NAPTRDNS_A6DNS_ALLDNS_ANY

注意:

由于不同平台之间的 libresolv 性能差异,DNS_ANY 并不总是会返回所有记录,较慢的 DNS_ALL 会更可靠地收集所有记录。

注意:

Windows:不支持 DNS_CAA。未实现对 DNS_A6 的支持。

authoritative_name_servers

通过引用传递,如果给出,将填充 权威域名服务器 的资源记录。

additional_records

通过引用传递,如果给出,将填充任何 附加记录

raw

type 将被解释为原始 DNS 类型 ID(不能使用 DNS_* 常量)。返回值将包含一个 data 键,需要手动解析。

返回值

此函数返回一个包含关联数组的数组,或者在失败时返回 false。每个关联数组都至少包含以下键

基本 DNS 属性
属性 含义
host DNS 命名空间中与其他关联数据相关的记录。
class dns_get_record() 仅返回 Internet 类记录,因此此参数将始终返回 IN
type 包含记录类型的字符串。其他属性也会包含在结果数组中,具体取决于 type 的值。请参见下面的表格。
ttl 此记录的剩余 "生存时间"。这将不等于记录的原始 ttl,而将等于原始 ttl 减去从查询权威域名服务器开始到现在的经过时间。

根据 'type' 的不同,关联数组中的其他键
类型 额外列
A ip: 以点分十进制表示法表示的 IPv4 地址。
MX pri: 邮件交换器的优先级。较低的数字表示更高的优先级。 target: 邮件交换器的 FQDN。另请参见 dns_get_mx()
CNAME target: 记录别名的 DNS 命名空间中的位置的 FQDN。
NS target: 对此主机名具有权威性的名称服务器的 FQDN。
PTR target: 此记录指向的 DNS 命名空间中的位置。
TXT txt: 与此记录关联的任意字符串数据。
HINFO cpu: 指定此记录引用的机器的 CPU 的 IANA 编号。 os: 指定此记录引用的机器的操作系统的 IANA 编号。有关这些值的含义,请参见 IANA 的 » Operating System Names
CAA flags: 一字节位域;当前仅定义位 0,表示“关键”;其他位保留,应忽略。 tag: CAA 标签名称(字母数字 ASCII 字符串)。 value: CAA 标签值(二进制字符串,可以使用子格式)。有关更多信息,请参见:» RFC 6844
SOA mname: 资源记录来源机器的 FQDN。 rname: 此域的管理联系人的电子邮件地址。 serial: 此域请求版本的序列号。 refresh: 辅助名称服务器在更新此域的远程副本时应使用的刷新间隔(秒)。 retry: 刷新失败后等待再次尝试的时间(秒)。 expire: 辅助 DNS 服务器在没有成功刷新之前应保留区域数据的远程副本的最长时间(秒),然后丢弃。 minimum-ttl: 客户端在请求服务器上的新解析之前可以继续使用 DNS 解析的最小时间(秒)。可以由各个资源记录覆盖。
AAAA ipv6: IPv6 地址
A6 masklen: 从 chain 指定的目标继承的长度(以位为单位)。 ipv6: 此特定记录的地址,要与 chain 合并。 chain: 要与 ipv6 数据合并的父记录。
SRV pri: (优先级)应首先使用最低的优先级。 weight: 排名,用于随机加权选择哪个具有相同优先级的 targetstargetport: 可以找到请求服务的 hostname 和端口。有关更多信息,请参见:» RFC 2782
NAPTR orderpref: 等效于上面的 priweightflagsservicesregexreplacement: » RFC 2915 中定义的参数。

变更日志

版本 说明
7.0.16, 7.1.2 添加了对 CAA 记录类型的支持。

示例

示例 #1 使用 dns_get_record()

<?php
$result
= dns_get_record("php.net");
print_r($result);
?>

上面的例子将输出类似于

Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => MX
            [pri] => 5
            [target] => pair2.php.net
            [class] => IN
            [ttl] => 6765
        )

    [1] => Array
        (
            [host] => php.net
            [type] => A
            [ip] => 64.246.30.37
            [class] => IN
            [ttl] => 8125
        )

)

示例 #2 使用 dns_get_record() 和 DNS_ANY

由于在解析 MX 记录后,通常需要获得邮件服务器的 IP 地址,dns_get_record() 也会返回一个关联记录的数组,位于 additional_records 中。 authoritative_name_servers 也将被返回,其中包含权威域名服务器的列表。

<?php
/* 请求 php.net 的“ANY”记录,
并创建 $authns 和 $addtl 数组
包含域名服务器列表和
任何与它们相关的附加记录
*/
$result = dns_get_record("php.net", DNS_ANY, $authns, $addtl);
echo
"Result = ";
print_r($result);
echo
"Auth NS = ";
print_r($authns);
echo
"Additional = ";
print_r($addtl);
?>

上面的例子将输出类似于

Result = Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => MX
            [pri] => 5
            [target] => pair2.php.net
            [class] => IN
            [ttl] => 6765
        )

    [1] => Array
        (
            [host] => php.net
            [type] => A
            [ip] => 64.246.30.37
            [class] => IN
            [ttl] => 8125
        )

)
Auth NS = Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => remote1.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [1] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => remote2.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [2] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => ns1.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [3] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => ns2.easydns.com
            [class] => IN
            [ttl] => 10722
        )

)
Additional = Array
(
    [0] => Array
        (
            [host] => pair2.php.net
            [type] => A
            [ip] => 216.92.131.5
            [class] => IN
            [ttl] => 6766
        )

    [1] => Array
        (
            [host] => remote1.easydns.com
            [type] => A
            [ip] => 64.39.29.212
            [class] => IN
            [ttl] => 100384
        )

    [2] => Array
        (
            [host] => remote2.easydns.com
            [type] => A
            [ip] => 212.100.224.80
            [class] => IN
            [ttl] => 81241
        )

    [3] => Array
        (
            [host] => ns1.easydns.com
            [type] => A
            [ip] => 216.220.40.243
            [class] => IN
            [ttl] => 81241
        )

    [4] => Array
        (
            [host] => ns2.easydns.com
            [type] => A
            [ip] => 216.220.40.244
            [class] => IN
            [ttl] => 81241
        )

)

另见

添加注释

用户贡献的注释 9 个注释

28
tobias at herkula dot info
9 年前
此方法没有错误处理,它只是输出“false”,并且无法检查 NXDOMAIN、SERVFAIL、TIMEOUT 或任何其他错误...
15
dylan at pow7 dot com
15 年前
一次获取多个类型,如下所示
<?php
$dnsr
= dns_get_record('php.net', DNS_A + DNS_NS);
print_r($dnsr);
?>

使用 DNS_ALL 在某些域中失败,而 DNS_ANY 在这些域中有效。我注意到该函数在 DNS_PTR 记录上卡住,导致它返回 FALSE 并出现以下错误
PHP 警告:dns_get_record():res_nsend() 在 .... 中失败

这将获取除 DNS_PTR 之外的所有记录
<?php
$dnsr
= dns_get_record('php.net', DNS_ALL - DNS_PTR);
print_r($dnsr);
?>
13
PHP Joe
11 年前
虽然这非常适用于一般的 DNS 查询,但如果你想对指定的 DNS 服务器进行直接 DNS 查询(而不是使用操作系统解析),请尝试使用 PHPDNS:http://www.purplepixie.org/phpdns/

你可以对名称服务器进行直接(TCP 或 UDP)低级查询,并随意递归。这对于测试特定服务器以及遍历递归解析非常有用。
11
NaturalBornCamper
7 年前
你可能和我遇到了同样的问题,即测试一个不存在的域名会搜索相对于你执行的域名的子域名,例如

// 使用有效域名进行测试
var_dump( dns_get_record('google.com', DNS_A) );
/* 工作,返回
数组
(
[host] => google.com
[class] => IN
[ttl] => 299
[type] => A
[ip] => 172.217.12.142
)
*/

// 在我们的网站上测试无效域名 (example.com)
var_dump( dns_get_record('invalidtestingname.com', DNS_A) );
/* 不起作用,假装它是子域名
数组
(
[host] => invalidtestingname.com.example.com
[class] => IN
[ttl] => 299
[type] => A
[ip] => xxx.xxx.xxx.xxx
)
*/

如果有人遇到这个问题,请在域名末尾添加一个“点”,例如,而不是
dns_get_record('invalidtestingname.com', DNS_A);
请执行以下操作
dns_get_record('invalidtestingname.com.', DNS_A);
3
heinjan at eendrachtstraat dot nl
7 年前
请注意,防火墙和反恶意软件检测(根据公司策略甚至阻止)DNS_ANY 请求。
在这种情况下,此函数的使用将失败。
这是因为 DNS_ANY 请求可以被用于创建“放大 (D)DOS 攻击”:你发送一个 DNS_ANY 请求,并获得大量信息,因此即使是小的请求也会导致巨大的网络负载。

我建议使用更明确的名称请求,而不是使用 DNS_ANY。
2
ohcc at 163 dot com
6 年前
当我在 Windows 操作系统上使用 DNS_ALL 作为 dns_get_record() 的第二个参数调用时,PHP 会发出一个警告,消息为“警告:dns_get_record():类型 '251721779' 在 blah.php 的第 blah 行不支持”,而 DNS_ANY 始终有效。
1
bohwaz
1 年前
遗憾的是,此方法不允许使用任意名称服务器。

如果你需要使用特定 DNS 服务器发出请求,你需要使用 Pear/Net_DNS2 或 libdns(https://github.com/DaveRandom/LibDNS)。

如果你想要更短、更轻的东西,你也可以使用这个 150 行函数:https://gist.github.com/bohwaz/ddc61c4f7e031c3221a89981e70b830c
-10
karl at influ dot io
11 年前
下面有 7 年前的评论提到 BSD 和 MacOSX,我只是想跟进,以防有些人看到并认为它在 MacOSX 上不起作用。

软件

系统软件概述

系统版本:OS X 10.8.3 (12D78)
内核版本:Darwin 12.3.0
启动卷:Macintosh HD
启动模式:正常
计算机名称:Karl 的 iMac
用户名:Karl Kloppenborg (karl)
安全虚拟内存:已启用
自启动以来的时间:10 天 20:24
--------------

# php -a
php > print_r(dns_get_record('google.com', DNS_MX));

数组
(
[0] => 数组
(
[host] => google.com
[type] => MX
[pri] => 10
[target] => aspmx.l.google.com
[class] => IN
[ttl] => 749
)

[1] => 数组
(
[host] => google.com
[type] => MX
[pri] => 30
[target] => alt2.aspmx.l.google.com
[class] => IN
[ttl] => 749
)

[2] => 数组
(
[host] => google.com
[type] => MX
[pri] => 50
[target] => alt4.aspmx.l.google.com
[class] => IN
[ttl] => 749
)

[3] => 数组
(
[host] => google.com
[type] => MX
[pri] => 40
[target] => alt3.aspmx.l.google.com
[class] => IN
[ttl] => 749
)

[4] => 数组
(
[host] => google.com
[type] => MX
[pri] => 20
[target] => alt1.aspmx.l.google.com
[class] => IN
[ttl] => 749
)

)
-19
Emil
6 年前
嗨,
如果我在 directadmin 中添加了域名,而域名中存在包含 dns_get_record 的脚本,它会给我本地值,即使该域名尚未真正委派到此服务器.. 为什么?
To Top