DNS#

稳定性:2 - 稳定

源代码: lib/dns.js

node:dns 模块启用名称解析。例如,使用它来查找主机名的 IP 地址。

尽管以 域名系统 (DNS) 命名,但它并不总是使用 DNS 协议进行查找。 dns.lookup() 使用操作系统设施来执行名称解析。它可能不需要执行任何网络通信。要像同一系统上的其他应用程序一样执行名称解析,请使用 dns.lookup()

const dns = require('node:dns');

dns.lookup('example.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "93.184.216.34" family: IPv4 

node:dns 模块中的所有其他函数都连接到实际的 DNS 服务器来执行名称解析。它们将始终使用网络来执行 DNS 查询。这些函数不使用 dns.lookup() 使用的相同配置文件集(例如 /etc/hosts)。使用这些函数始终执行 DNS 查询,绕过其他名称解析设施。

const dns = require('node:dns');

dns.resolve4('archive.org', (err, addresses) => {
  if (err) throw err;

  console.log(`addresses: ${JSON.stringify(addresses)}`);

  addresses.forEach((a) => {
    dns.reverse(a, (err, hostnames) => {
      if (err) {
        throw err;
      }
      console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`);
    });
  });
}); 

有关更多信息,请参阅 实现注意事项部分

类:dns.Resolver#

DNS 请求的独立解析器。

创建新的解析器会使用默认服务器设置。使用 resolver.setServers() 为解析器设置所用的服务器不会影响其他解析器

const { Resolver } = require('node:dns');
const resolver = new Resolver();
resolver.setServers(['4.4.4.4']);

// This request will use the server at 4.4.4.4, independent of global settings.
resolver.resolve4('example.org', (err, addresses) => {
  // ...
}); 

node:dns 模块中的以下方法可用

Resolver([options])#

创建新的解析器。

  • options <Object>
    • timeout <integer> 查询超时(毫秒),或 -1 以使用默认超时。
    • tries <integer> 在放弃之前,解析器尝试联系每个名称服务器的次数。默认值:4

resolver.cancel()#

取消此解析器发出的所有未完成的 DNS 查询。相应的回调将使用代码 ECANCELLED 调用错误。

resolver.setLocalAddress([ipv4][, ipv6])#

  • ipv4 <string> IPv4 地址的字符串表示形式。默认值:'0.0.0.0'
  • ipv6 <string> IPv6 地址的字符串表示形式。默认值:'::0'

解析器实例将从指定的 IP 地址发送其请求。这允许程序在多宿主机系统上使用时指定出站接口。

如果未指定 v4 或 v6 地址,则将其设置为默认值,并且操作系统将自动选择一个本地地址。

解析器在向 IPv4 DNS 服务器发出请求时将使用 v4 本地地址,在向 IPv6 DNS 服务器发出请求时将使用 v6 本地地址。解析请求的 rrtype 不会影响所使用的本地地址。

dns.getServers()#

返回一个 IP 地址字符串数组,根据 RFC 5952 进行格式化,这些字符串目前已配置用于 DNS 解析。如果使用自定义端口,则字符串将包含一个端口部分。

[
  '8.8.8.8',
  '2001:4860:4860::8888',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
] 

dns.lookup(hostname[, options], callback)#

  • hostname <string>
  • options <integer> | <Object>
    • family <integer> | <string> 记录族。必须为 460。出于向后兼容性的原因,'IPv4''IPv6' 分别解释为 46。值 0 表示返回 IPv4 或 IPv6 地址。如果值 0{ all: true } (见下文) 一起使用,则返回 IPv4 和 IPv6 地址。默认值:0
    • hints <number> 一个或多个 受支持的 getaddrinfo 标志。可以通过按位 OR 运算其值来传递多个标志。
    • all <boolean> 当为 true 时,回调在数组中返回所有已解析的地址。否则,返回单个地址。默认值:false
    • verbatim <boolean>true 时,回调按 DNS 解析器返回的顺序接收 IPv4 和 IPv6 地址。当 false 时,IPv4 地址排在 IPv6 地址之前。默认值: true(地址不重新排序)。可以使用 dns.setDefaultResultOrder()--dns-result-order 配置默认值。
  • callback <Function>
    • err <Error>
    • address <string> IPv4 或 IPv6 地址的字符串表示形式。
    • family <integer> 46,表示 address 的族,如果地址不是 IPv4 或 IPv6 地址,则表示 00 可能表示操作系统使用的名称解析服务中的错误。

将主机名(例如 'nodejs.org')解析为第一个找到的 A(IPv4)或 AAAA(IPv6)记录。所有 option 属性都是可选的。如果 options 是一个整数,那么它必须是 46 - 如果 options0 或未提供,则如果找到,将同时返回 IPv4 和 IPv6 地址。

all 选项设置为 true 时,callback 的参数更改为 (err, addresses),其中 addresses 是一个对象数组,具有 addressfamily 属性。

如果出错,err 是一个 Error 对象,其中 err.code 是错误代码。请记住,err.code 不仅在主机名不存在时设置为 'ENOTFOUND',而且在查找以其他方式失败时(例如没有可用的文件描述符)也会设置为 'ENOTFOUND'

dns.lookup() 不一定与 DNS 协议有任何关系。该实现使用一个操作系统工具,该工具可以将名称与地址相关联,反之亦然。此实现可能会对任何 Node.js 程序的行为产生细微但重要的影响。在使用 dns.lookup() 之前,请花一些时间查阅 实现注意事项部分

示例用法

const dns = require('node:dns');
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.com', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, family));
// address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6

// When options.all is true, the result will be an Array.
options.all = true;
dns.lookup('example.com', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}] 

如果此方法被调用为其 util.promisify() 版本,并且 all 未设置为 true,则它会返回一个 Promise,用于具有 addressfamily 属性的 Object

受支持的 getaddrinfo 标志#

以下标志可作为提示传递给 dns.lookup()

  • dns.ADDRCONFIG:将返回的地址类型限制为系统上配置的非环回地址类型。例如,仅当当前系统至少配置了一个 IPv4 地址时才返回 IPv4 地址。
  • dns.V4MAPPED:如果指定了 IPv6 系列,但未找到任何 IPv6 地址,则返回 IPv4 映射的 IPv6 地址。某些操作系统(例如 FreeBSD 10.1)不支持此功能。
  • dns.ALL:如果指定了 dns.V4MAPPED,则返回已解析的 IPv6 地址以及 IPv4 映射的 IPv6 地址。

dns.lookupService(address, port, callback)#

使用操作系统底层的 getnameinfo 实现将给定的 addressport 解析为主机名和服务。

如果 address 不是有效的 IP 地址,将抛出 TypeErrorport 将强制转换为数字。如果它不是合法的端口,将抛出 TypeError

如果出现错误,err 是一个 Error 对象,其中 err.code 是错误代码。

const dns = require('node:dns');
dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
  console.log(hostname, service);
  // Prints: localhost ssh
}); 

如果此方法被调用为其 util.promisify() 版本,它将返回一个 Promise,用于具有 hostnameservice 属性的 Object

dns.resolve(hostname[, rrtype], callback)#

使用 DNS 协议将主机名(例如 'nodejs.org')解析为资源记录数组。callback 函数具有参数 (err, records)。成功时,records 将是资源记录数组。各个结果的类型和结构因 rrtype 而异

rrtyperecords 包含结果类型速记方法
'A'IPv4 地址(默认)<string>dns.resolve4()
'AAAA'IPv6 地址<string>dns.resolve6()
'ANY'任何记录<Object>dns.resolveAny()
'CAA'CA 授权记录<Object>dns.resolveCaa()
'CNAME'规范名称记录<string>dns.resolveCname()
'MX'邮件交换记录<Object>dns.resolveMx()
'NAPTR'名称授权指针记录<Object>dns.resolveNaptr()
'NS'名称服务器记录<string>dns.resolveNs()
'PTR'指针记录<string>dns.resolvePtr()
'SOA'授权开始记录<Object>dns.resolveSoa()
'SRV'服务记录<Object>dns.resolveSrv()
'TXT'文本记录<string[]>dns.resolveTxt()

如果出错,err 是一个 Error 对象,其中 err.codeDNS 错误代码 之一。

dns.resolve4(hostname[, options], callback)#

  • hostname <string> 要解析的主机名。
  • options <Object>
    • ttl <boolean> 检索每条记录的生存时间 (TTL) 值。当 true 时,回调接收一个 { address: '1.2.3.4', ttl: 60 } 对象数组,而不是一个字符串数组,TTL 以秒为单位表示。
  • callback <Function>

使用 DNS 协议为 hostname 解析 IPv4 地址(A 记录)。传递给 callback 函数的 addresses 参数将包含一个 IPv4 地址数组(例如 ['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dns.resolve6(hostname[, options], callback)#

  • hostname <string> 要解析的主机名。
  • options <Object>
    • ttl <boolean> 检索每条记录的生存时间 (TTL) 值。当 true 时,回调接收一个 { address: '0:1:2:3:4:5:6:7', ttl: 60 } 对象数组,而不是一个字符串数组,TTL 以秒为单位表示。
  • callback <Function>

使用 DNS 协议为 hostname 解析 IPv6 地址(AAAA 记录)。传递给 callback 函数的 addresses 参数将包含一个 IPv6 地址数组。

dns.resolveAny(hostname, callback)#

使用 DNS 协议解析所有记录(也称为 ANY* 查询)。传递给 callback 函数的 ret 参数将是一个包含各种类型记录的数组。每个对象都有一个属性 type,表示当前记录的类型。根据 type,对象上将存在其他属性

类型属性
'A'address/ttl
'AAAA'address/ttl
'CNAME'
'MX'参见 dns.resolveMx()
'NAPTR'参见 dns.resolveNaptr()
'NS'
'PTR'
'SOA'参见 dns.resolveSoa()
'SRV'参见 dns.resolveSrv()
'TXT'此类型的记录包含一个名为 entries 的数组属性,该属性引用 dns.resolveTxt(),例如 { entries: ['...'], type: 'TXT' }

以下是传递给回调的 ret 对象的一个示例

[ { type: 'A', address: '127.0.0.1', ttl: 299 },
  { type: 'CNAME', value: 'example.com' },
  { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
  { type: 'NS', value: 'ns1.example.com' },
  { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
  { type: 'SOA',
    nsname: 'ns1.example.com',
    hostmaster: 'admin.example.com',
    serial: 156696742,
    refresh: 900,
    retry: 900,
    expire: 1800,
    minttl: 60 } ] 

DNS 服务器操作员可以选择不响应 ANY 查询。最好调用单个方法,如 dns.resolve4()dns.resolveMx() 等。有关更多详细信息,请参见 RFC 8482

dns.resolveCname(hostname, callback)#

使用 DNS 协议解析 hostnameCNAME 记录。传递给 callback 函数的 addresses 参数将包含一个可用于 hostname 的规范名称记录数组(例如 ['bar.example.com'])。

dns.resolveCaa(hostname, callback)#

使用 DNS 协议解析 hostnameCAA 记录。传递给 callback 函数的 addresses 参数将包含一个可用于 hostname 的认证机构授权记录数组(例如 [{critical: 0, iodef: 'mailto:[email protected]'}, {critical: 128, issue: 'pki.example.com'}])。

dns.resolveMx(hostname, callback)#

使用 DNS 协议解析 hostname 的邮件交换记录 (MX 记录)。传递给 callback 函数的 addresses 参数将包含一个对象数组,其中包含 priorityexchange 属性(例如 [{priority: 10, exchange: 'mx.example.com'}, ...])。

dns.resolveNaptr(hostname, callback)#

使用 DNS 协议解析 hostname 的基于正则表达式的记录 (NAPTR 记录)。传递给 callback 函数的 addresses 参数将包含一个对象数组,其中包含以下属性

  • flags
  • service
  • regexp
  • replacement
  • order
  • preference
{
  flags: 's',
  service: 'SIP+D2U',
  regexp: '',
  replacement: '_sip._udp.example.com',
  order: 30,
  preference: 100
} 

dns.resolveNs(hostname, callback)#

使用 DNS 协议解析 hostname 的名称服务器记录 (NS 记录)。传递给 callback 函数的 addresses 参数将包含一个名称服务器记录数组,这些记录可用于 hostname(例如 ['ns1.example.com', 'ns2.example.com'])。

dns.resolvePtr(hostname, callback)#

使用 DNS 协议解析 hostname 的指针记录 (PTR 记录)。传递给 callback 函数的 addresses 参数将是一个字符串数组,其中包含回复记录。

dns.resolveSoa(hostname, callback)#

使用 DNS 协议解析 hostname 的授权开始记录 (SOA 记录)。传递给 callback 函数的 address 参数将是一个对象,其中包含以下属性

  • nsname
  • hostmaster
  • serial
  • refresh
  • retry
  • expire
  • minttl
{
  nsname: 'ns.example.com',
  hostmaster: 'root.example.com',
  serial: 2013101809,
  refresh: 10000,
  retry: 2400,
  expire: 604800,
  minttl: 3600
} 

dns.resolveSrv(hostname, callback)#

使用 DNS 协议解析 hostname 的服务记录 (SRV 记录)。传递给 callback 函数的 addresses 参数将是一个对象数组,其中包含以下属性

  • 优先级
  • 权重
  • 端口
  • 名称
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dns.resolveTxt(hostname, callback)#

使用 DNS 协议解析 hostname 的文本查询(TXT 记录)。传递给 callback 函数的 records 参数是 hostname 可用文本记录的二维数组(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每个子数组包含一条记录的 TXT 块。根据用例,这些块可以连接在一起或分别处理。

dns.reverse(ip, callback)#

执行反向 DNS 查询,将 IPv4 或 IPv6 地址解析为主机名数组。

如果出错,err 是一个 Error 对象,其中 err.codeDNS 错误代码 之一。

dns.setDefaultResultOrder(order)#

  • order <string> 必须是 'ipv4first''verbatim'

dns.lookup()dnsPromises.lookup() 中设置 verbatim 的默认值为 true。该值可以是

  • ipv4first:将默认 verbatim 设置为 false
  • verbatim:将默认 verbatim 设置为 true

默认值为 verbatim,并且 dns.setDefaultResultOrder() 的优先级高于 --dns-result-order。使用 工作线程 时,主线程中的 dns.setDefaultResultOrder() 不会影响工作线程中的默认 dns 顺序。

dns.getDefaultResultOrder()#

获取 dns.lookup()dnsPromises.lookup()verbatim 的默认值。该值可以是

  • ipv4first:对于 verbatim,默认为 false
  • verbatim:对于 verbatim,默认为 true

dns.setServers(servers)#

在执行 DNS 解析时设置要使用的服务器的 IP 地址和端口。servers 参数是 RFC 5952 格式地址的数组。如果端口是 IANA 默认 DNS 端口 (53),则可以省略。

dns.setServers([
  '8.8.8.8',
  '[2001:4860:4860::8888]',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
]); 

如果提供了无效的地址,则会抛出一个错误。

在 DNS 查询进行期间,不得调用 dns.setServers() 方法。

dns.setServers() 方法仅影响 dns.resolve()dns.resolve*()dns.reverse()(具体来说影响 dns.lookup())。

此方法的工作方式与 resolve.conf 非常相似。也就是说,如果尝试使用提供的第一个服务器进行解析导致 NOTFOUND 错误,则 resolve() 方法不会尝试使用随后提供的服务器进行解析。只有在较早的服务器超时或导致其他错误时,才会使用备用 DNS 服务器。

DNS 承诺 API#

dns.promises API 提供了一组替代的异步 DNS 方法,这些方法返回 Promise 对象,而不是使用回调。可以通过 require('node:dns').promisesrequire('node:dns/promises') 访问该 API。

类:dnsPromises.Resolver#

DNS 请求的独立解析器。

创建新的解析器会使用默认服务器设置。使用 resolver.setServers() 为解析器设置所使用的服务器不会影响其他解析器

const { Resolver } = require('node:dns').promises;
const resolver = new Resolver();
resolver.setServers(['4.4.4.4']);

// This request will use the server at 4.4.4.4, independent of global settings.
resolver.resolve4('example.org').then((addresses) => {
  // ...
});

// Alternatively, the same code can be written using async-await style.
(async function() {
  const addresses = await resolver.resolve4('example.org');
})(); 

dnsPromises API 中提供以下方法

resolver.cancel()#

取消此解析器发出的所有未完成的 DNS 查询。相应的承诺将被拒绝,并显示代码为 ECANCELLED 的错误。

dnsPromises.getServers()#

返回一个 IP 地址字符串数组,根据 RFC 5952 进行格式化,这些字符串目前已配置用于 DNS 解析。如果使用自定义端口,则字符串将包含一个端口部分。

[
  '8.8.8.8',
  '2001:4860:4860::8888',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
] 

dnsPromises.lookup(hostname[, options])#

  • hostname <string>
  • options <integer> | <Object>
    • family <integer> 记录族。必须为 460。值 0 表示返回 IPv4 或 IPv6 地址。如果将值 0{ all: true }(见下文)一起使用,则会同时返回 IPv4 和 IPv6 地址。默认值:0
    • hints <number> 一个或多个 受支持的 getaddrinfo 标志。可以通过按位 OR 运算其值来传递多个标志。
    • all <boolean> 当为 true 时,Promise 会使用数组中的所有地址进行解析。否则,返回单个地址。默认值:false
    • verbatim <boolean> 当为 true 时,Promise 会使用 DNS 解析器返回的顺序来解析 IPv4 和 IPv6 地址。当为 false 时,IPv4 地址会排在 IPv6 地址之前。默认值:目前为 false(地址会重新排序),但预计在不久的将来会发生更改。可以使用 dns.setDefaultResultOrder()--dns-result-order 来配置默认值。新代码应使用 { verbatim: true }

将主机名(例如 'nodejs.org')解析为第一个找到的 A(IPv4)或 AAAA(IPv6)记录。所有 option 属性都是可选的。如果 options 是一个整数,则它必须是 46 - 如果未提供 options,则如果找到,则会同时返回 IPv4 和 IPv6 地址。

all 选项设置为 true 时,Promise 会使用 addresses(一个包含 addressfamily 属性的对象数组)进行解析。

出错时,Promise 会使用一个 Error 对象(其中 err.code 是错误代码)进行拒绝。请记住,err.code 不仅会在主机名不存在时设置为 'ENOTFOUND',还会在查找以其他方式失败(例如没有可用的文件描述符)时设置为 'ENOTFOUND'

dnsPromises.lookup() 不一定与 DNS 协议有任何关系。该实现使用一个操作系统工具,该工具可以将名称与地址相关联,反之亦然。此实现可能会对任何 Node.js 程序的行为产生细微但重要的影响。在使用 dnsPromises.lookup() 之前,请花一些时间查阅 实现注意事项部分

示例用法

const dns = require('node:dns');
const dnsPromises = dns.promises;
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};

dnsPromises.lookup('example.com', options).then((result) => {
  console.log('address: %j family: IPv%s', result.address, result.family);
  // address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6
});

// When options.all is true, the result will be an Array.
options.all = true;
dnsPromises.lookup('example.com', options).then((result) => {
  console.log('addresses: %j', result);
  // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}]
}); 

dnsPromises.lookupService(address, port)#

使用操作系统底层的 getnameinfo 实现将给定的 addressport 解析为主机名和服务。

如果 address 不是有效的 IP 地址,将抛出 TypeErrorport 将强制转换为数字。如果它不是合法的端口,将抛出 TypeError

如果出错,Promise 会被拒绝,并返回一个 Error 对象,其中 err.code 是错误代码。

const dnsPromises = require('node:dns').promises;
dnsPromises.lookupService('127.0.0.1', 22).then((result) => {
  console.log(result.hostname, result.service);
  // Prints: localhost ssh
}); 

dnsPromises.resolve(hostname[, rrtype])#

  • hostname <string> 要解析的主机名。
  • rrtype <string> 资源记录类型。默认值:'A'

使用 DNS 协议将主机名(例如 'nodejs.org')解析为资源记录数组。如果成功,Promise 会使用资源记录数组进行解析。各个结果的类型和结构会根据 rrtype 而异

rrtyperecords 包含结果类型速记方法
'A'IPv4 地址(默认)<string>dnsPromises.resolve4()
'AAAA'IPv6 地址<string>dnsPromises.resolve6()
'ANY'任何记录<Object>dnsPromises.resolveAny()
'CAA'CA 授权记录<Object>dnsPromises.resolveCaa()
'CNAME'规范名称记录<string>dnsPromises.resolveCname()
'MX'邮件交换记录<Object>dnsPromises.resolveMx()
'NAPTR'名称授权指针记录<Object>dnsPromises.resolveNaptr()
'NS'名称服务器记录<string>dnsPromises.resolveNs()
'PTR'指针记录<string>dnsPromises.resolvePtr()
'SOA'授权开始记录<Object>dnsPromises.resolveSoa()
'SRV'服务记录<Object>dnsPromises.resolveSrv()
'TXT'文本记录<string[]>dnsPromises.resolveTxt()

如果出错,Promise 会被拒绝,并返回一个 Error 对象,其中 err.codeDNS 错误代码 之一。

dnsPromises.resolve4(hostname[, options])#

  • hostname <string> 要解析的主机名。
  • options <Object>
    • ttl <boolean> 检索每条记录的生存时间 (TTL) 值。当 true 时,Promise 会使用 { address: '1.2.3.4', ttl: 60 } 对象数组(而不是字符串数组)进行解析,TTL 以秒为单位表示。

使用 DNS 协议为 hostname 解析 IPv4 地址(A 记录)。如果成功,Promise 会使用 IPv4 地址数组进行解析(例如 ['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dnsPromises.resolve6(hostname[, options])#

  • hostname <string> 要解析的主机名。
  • options <Object>
    • ttl <boolean> 检索每条记录的生存时间 (TTL) 值。当 true 时,Promise 会使用 { address: '0:1:2:3:4:5:6:7', ttl: 60 } 对象数组(而不是字符串数组)进行解析,TTL 以秒为单位表示。

使用 DNS 协议为 hostname 解析 IPv6 地址(AAAA 记录)。如果成功,Promise 会使用 IPv6 地址数组进行解析。

dnsPromises.resolveAny(hostname)#

使用 DNS 协议解析所有记录(也称为 ANY* 查询)。成功后,Promise 将解析为包含各种类型记录的数组。每个对象都有一个 type 属性,表示当前记录的类型。并且根据 type,对象上将存在其他属性

类型属性
'A'address/ttl
'AAAA'address/ttl
'CNAME'
'MX'请参阅 dnsPromises.resolveMx()
'NAPTR'请参阅 dnsPromises.resolveNaptr()
'NS'
'PTR'
'SOA'请参阅 dnsPromises.resolveSoa()
'SRV'请参阅 dnsPromises.resolveSrv()
'TXT'此类型的记录包含一个名为 entries 的数组属性,该属性引用 dnsPromises.resolveTxt(),例如 { entries: ['...'], type: 'TXT' }

以下是结果对象的示例

[ { type: 'A', address: '127.0.0.1', ttl: 299 },
  { type: 'CNAME', value: 'example.com' },
  { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
  { type: 'NS', value: 'ns1.example.com' },
  { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
  { type: 'SOA',
    nsname: 'ns1.example.com',
    hostmaster: 'admin.example.com',
    serial: 156696742,
    refresh: 900,
    retry: 900,
    expire: 1800,
    minttl: 60 } ] 

dnsPromises.resolveCaa(hostname)#

使用 DNS 协议解析 hostnameCAA 记录。成功后,Promise 将解析为一个对象数组,其中包含可用于 hostname 的可用认证机构授权记录(例如 [{critical: 0, iodef: 'mailto:[email protected]'},{critical: 128, issue: 'pki.example.com'}])。

dnsPromises.resolveCname(hostname)#

使用 DNS 协议解析 hostnameCNAME 记录。成功后,Promise 将解析为一个规范名称记录数组,该数组可用于 hostname(例如 ['bar.example.com'])。

dnsPromises.resolveMx(hostname)#

使用 DNS 协议解析邮件交换记录(MX 记录),用于 hostname。成功后,Promise 将使用包含 priorityexchange 属性的对象数组进行解析(例如 [{priority: 10, exchange: 'mx.example.com'}, ...])。

dnsPromises.resolveNaptr(hostname)#

使用 DNS 协议解析基于正则表达式的记录(NAPTR 记录),用于 hostname。成功后,Promise 将使用具有以下属性的对象数组进行解析

  • flags
  • service
  • regexp
  • replacement
  • order
  • preference
{
  flags: 's',
  service: 'SIP+D2U',
  regexp: '',
  replacement: '_sip._udp.example.com',
  order: 30,
  preference: 100
} 

dnsPromises.resolveNs(hostname)#

使用 DNS 协议解析名称服务器记录(NS 记录),用于 hostname。成功后,Promise 将使用可用于 hostname 的名称服务器记录数组进行解析(例如 ['ns1.example.com', 'ns2.example.com'])。

dnsPromises.resolvePtr(hostname)#

使用 DNS 协议解析指针记录(PTR 记录),用于 hostname。成功后,Promise 将使用包含回复记录的字符串数组进行解析。

dnsPromises.resolveSoa(hostname)#

使用 DNS 协议解析授权开始记录(SOA 记录),用于 hostname。成功后,Promise 将使用具有以下属性的对象进行解析

  • nsname
  • hostmaster
  • serial
  • refresh
  • retry
  • expire
  • minttl
{
  nsname: 'ns.example.com',
  hostmaster: 'root.example.com',
  serial: 2013101809,
  refresh: 10000,
  retry: 2400,
  expire: 604800,
  minttl: 3600
} 

dnsPromises.resolveSrv(hostname)#

使用 DNS 协议解析服务记录(SRV 记录),用于 hostname。成功后,Promise 将使用具有以下属性的对象数组进行解析

  • 优先级
  • 权重
  • 端口
  • 名称
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dnsPromises.resolveTxt(hostname)#

使用 DNS 协议解析 hostname 的文本查询(TXT 记录)。如果成功,则 Promise 会使用 hostname 可用的文本记录的二维数组解析(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每个子数组包含一条记录的 TXT 块。根据用例,这些块可以连接在一起或分别处理。

dnsPromises.reverse(ip)#

执行反向 DNS 查询,将 IPv4 或 IPv6 地址解析为主机名数组。

如果出错,Promise 会被拒绝,并返回一个 Error 对象,其中 err.codeDNS 错误代码 之一。

dnsPromises.setDefaultResultOrder(order)#

  • order <string> 必须是 'ipv4first''verbatim'

dns.lookup()dnsPromises.lookup() 中设置 verbatim 的默认值为 true。该值可以是

  • ipv4first:将默认 verbatim 设置为 false
  • verbatim:将默认 verbatim 设置为 true

默认值为 verbatim,并且 dnsPromises.setDefaultResultOrder() 的优先级高于 --dns-result-order。使用 工作线程 时,主线程的 dnsPromises.setDefaultResultOrder() 不会影响工作线程中的默认 dns 顺序。

dnsPromises.getDefaultResultOrder()#

获取 dnsOrder 的值。

dnsPromises.setServers(servers)#

在执行 DNS 解析时设置要使用的服务器的 IP 地址和端口。servers 参数是 RFC 5952 格式地址的数组。如果端口是 IANA 默认 DNS 端口 (53),则可以省略。

dnsPromises.setServers([
  '8.8.8.8',
  '[2001:4860:4860::8888]',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
]); 

如果提供了无效的地址,则会抛出一个错误。

在 DNS 查询进行时,不得调用 dnsPromises.setServers() 方法。

此方法的工作方式与 resolve.conf 非常相似。也就是说,如果尝试使用提供的第一个服务器进行解析导致 NOTFOUND 错误,则 resolve() 方法不会尝试使用随后提供的服务器进行解析。只有在较早的服务器超时或导致其他错误时,才会使用备用 DNS 服务器。

错误代码#

每个 DNS 查询都可以返回以下错误代码之一

  • dns.NODATA:DNS 服务器返回的答案没有数据。
  • dns.FORMERR:DNS 服务器声称查询格式错误。
  • dns.SERVFAIL:DNS 服务器返回常规故障。
  • dns.NOTFOUND:找不到域名。
  • dns.NOTIMP:DNS 服务器未实现所请求的操作。
  • dns.REFUSED:DNS 服务器拒绝查询。
  • dns.BADQUERY:DNS 查询格式错误。
  • dns.BADNAME:主机名格式错误。
  • dns.BADFAMILY:不支持的地址族。
  • dns.BADRESP:DNS 答复格式错误。
  • dns.CONNREFUSED:无法联系 DNS 服务器。
  • dns.TIMEOUT:联系 DNS 服务器时超时。
  • dns.EOF:文件结尾。
  • dns.FILE:读取文件时出错。
  • dns.NOMEM:内存不足。
  • dns.DESTRUCTION:通道正在销毁。
  • dns.BADSTR:格式错误的字符串。
  • dns.BADFLAGS:指定了非法标志。
  • dns.NONAME:给定的主机名不是数字。
  • dns.BADHINTS:指定了非法提示标志。
  • dns.NOTINITIALIZED:尚未执行 c-ares 库初始化。
  • dns.LOADIPHLPAPI:加载 iphlpapi.dll 时出错。
  • dns.ADDRGETNETWORKPARAMS:找不到 GetNetworkParams 函数。
  • dns.CANCELLED:DNS 查询已取消。

dnsPromises API 还导出了上述错误代码,例如 dnsPromises.NODATA

实现注意事项#

尽管 dns.lookup() 和各种 dns.resolve*()/dns.reverse() 函数具有将网络名称与网络地址(或反之亦然)关联的相同目标,但它们的行为却截然不同。这些差异可能会对 Node.js 程序的行为产生微妙但重大的影响。

dns.lookup()#

在底层,dns.lookup() 使用与大多数其他程序相同的操作系统设施。例如,dns.lookup() 几乎总是会以与 ping 命令相同的方式解析给定的名称。在大多数类 POSIX 操作系统上,dns.lookup() 函数的行为可以通过更改 nsswitch.conf(5) 和/或 resolv.conf(5) 中的设置来修改,但更改这些文件将更改在同一操作系统上运行的所有其他程序的行为。

虽然从 JavaScript 的角度来看对 dns.lookup() 的调用是异步的,但它被实现为对 getaddrinfo(3) 的同步调用,该调用在 libuv 的线程池上运行。这可能会对某些应用程序产生令人惊讶的负面性能影响,有关更多信息,请参阅 UV_THREADPOOL_SIZE 文档。

各种网络 API 会在内部调用 dns.lookup() 来解析主机名。如果这是一个问题,请考虑使用 dns.resolve() 将主机名解析为地址,并使用地址而不是主机名。此外,某些网络 API(例如 socket.connect()dgram.createSocket())允许替换默认解析器 dns.lookup()

dns.resolve()dns.resolve*()dns.reverse()#

这些函数的实现与 dns.lookup() 有很大不同。它们不使用 getaddrinfo(3),并且始终在网络上执行 DNS 查询。此网络通信始终异步完成,并且不使用 libuv 的线程池。

因此,这些函数不会对 libuv 的线程池上发生的其他处理产生与 dns.lookup() 相同的负面影响。

它们不使用 dns.lookup() 使用的相同配置文件集。例如,它们不使用 /etc/hosts 中的配置。