DNS#

稳定性:2 - 稳定

源代码: lib/dns.js

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

虽然以域名系统 (DNS)命名,但它并不总是使用 DNS 协议进行查找。 dns.lookup() 使用操作系统工具来执行名称解析。 它可能不需要执行任何网络通信。 要以与同一系统上的其他应用程序相同的方式执行名称解析,请使用 dns.lookup()

import dns from 'node:dns';

dns.lookup('example.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6const dns = require('node:dns');

dns.lookup('example.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

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

import dns from '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)}`);
    });
  });
});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() 设置用于解析器的服务器不会影响其他解析器

import { Resolver } from '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) => {
  // ...
});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 地址,具体取决于系统的 DNS 解析器。 默认值: 0
    • hints <number> 一个或多个支持的 getaddrinfo 标志。 可以通过按位 OR 运算它们的值来传递多个标志。
    • all <boolean> 当为 true 时,回调返回数组中的所有已解析地址。 否则,返回单个地址。 默认值: false
    • order <string> 当为 verbatim 时,返回未经排序的已解析地址。当为 ipv4first 时,已解析地址将按照 IPv4 地址排在 IPv6 地址之前的顺序排序。当为 ipv6first 时,已解析地址将按照 IPv6 地址排在 IPv4 地址之前的顺序排序。默认值: verbatim(地址不重新排序)。可以使用 dns.setDefaultResultOrder()--dns-result-order 配置默认值。
    • verbatim <boolean> 当为 true 时,回调函数接收 IPv4 和 IPv6 地址的顺序与 DNS 解析器返回的顺序相同。当为 false 时,IPv4 地址将排在 IPv6 地址之前。此选项将被弃用,转而使用 order。当两者都指定时,order 具有更高的优先级。新代码应仅使用 order默认值: 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 – 如果未提供 options,则如果找到,则返回 IPv4 或 IPv6 地址,或两者都返回。

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

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

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

用法示例

import dns from 'node:dns';
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.org', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, family));
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

// When options.all is true, the result will be an Array.
options.all = true;
dns.lookup('example.org', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]const dns = require('node:dns');
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.org', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, family));
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

// When options.all is true, the result will be an Array.
options.all = true;
dns.lookup('example.org', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]

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

支持的 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 是错误代码。

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

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

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()
'TLSA'证书关联<Object>dns.resolveTlsa()
'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()
'TLSA'请参阅 dns.resolveTlsa()
'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:pki@example.com'}, {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
  • weight
  • port
  • name
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dns.resolveTlsa(hostname, callback)#

使用 DNS 协议来解析 hostname 的证书关联(TLSA 记录)。 传递给 callback 函数的 records 参数是具有以下属性的对象数组

  • certUsage
  • selector
  • match
  • data
{
  certUsage: 3,
  selector: 1,
  match: 1,
  data: [ArrayBuffer]
} 

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''ipv6first''verbatim'

设置 dns.lookup()dnsPromises.lookup()order 的默认值。 该值可以是

  • ipv4first:将默认 order 设置为 ipv4first
  • ipv6first:将默认 order 设置为 ipv6first
  • verbatim:将默认 order 设置为 verbatim

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

dns.getDefaultResultOrder()#

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

  • ipv4first:对于默认设置为 ipv4firstorder
  • ipv6first:对于默认设置为 ipv6firstorder
  • verbatim:对于默认设置为 verbatimorder

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 服务器。

DNS promises API#

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

类: dnsPromises.Resolver#

用于 DNS 请求的独立解析器。

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

import { Resolver } from '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.
const addresses = await resolver.resolve4('example.org');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 查询。 相应的 promise 将被拒绝,并显示代码为 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 地址之一或两者,具体取决于系统的 DNS 解析器。 **默认:** 0
    • hints <number> 一个或多个支持的 getaddrinfo 标志。 可以通过按位 OR 运算它们的值来传递多个标志。
    • all <boolean> 当为 true 时,将使用数组中的所有地址来解析 Promise。 否则,返回单个地址。 **默认:** false
    • order <string>verbatim 时,Promise 会以 DNS 解析器返回 IPv4 和 IPv6 地址的顺序解析它们。当 ipv4first 时,IPv4 地址会排在 IPv6 地址之前。当 ipv6first 时,IPv6 地址会排在 IPv4 地址之前。默认值: verbatim(地址不会重新排序)。默认值可以使用 dns.setDefaultResultOrder()--dns-result-order 进行配置。新代码应该使用 { order: 'verbatim' }
    • verbatim <boolean>true 时,Promise 会以 DNS 解析器返回 IPv4 和 IPv6 地址的顺序解析它们。当 false 时,IPv4 地址会排在 IPv6 地址之前。此选项将被弃用,转而使用 order。当同时指定两者时,order 具有更高的优先级。新代码应该只使用 order默认值: 目前是 false(地址会被重新排序),但预计在不久的将来会发生变化。默认值可以使用 dns.setDefaultResultOrder()--dns-result-order 进行配置。

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

如果将 all 选项设置为 true,则 Promise 将使用 addresses 解析,addresses 是一个对象数组,包含 addressfamily 属性。

如果发生错误,Promise 将被一个 Error 对象拒绝,其中 err.code 是错误代码。请记住,只有当主机名不存在时,err.code 才会被设置为 'ENOTFOUND',当查找因其他方式(如没有可用的文件描述符)失败时也会如此。

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

用法示例

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

await dnsPromises.lookup('example.org', options).then((result) => {
  console.log('address: %j family: IPv%s', result.address, result.family);
  // address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6
});

// When options.all is true, the result will be an Array.
options.all = true;
await dnsPromises.lookup('example.org', options).then((result) => {
  console.log('addresses: %j', result);
  // addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]
});const dns = require('node:dns');
const dnsPromises = dns.promises;
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};

dnsPromises.lookup('example.org', options).then((result) => {
  console.log('address: %j family: IPv%s', result.address, result.family);
  // address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6
});

// When options.all is true, the result will be an Array.
options.all = true;
dnsPromises.lookup('example.org', options).then((result) => {
  console.log('addresses: %j', result);
  // addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]
});

dnsPromises.lookupService(address, port)#

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

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

如果发生错误,Promise 将被一个 Error 对象拒绝,其中 err.code 是错误代码。

import dnsPromises from 'node:dns/promises';
const result = await dnsPromises.lookupService('127.0.0.1', 22);

console.log(result.hostname, result.service); // Prints: localhost sshconst 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()
'TLSA'证书关联<Object>dnsPromises.resolveTlsa()
'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()
'TLSA'参考 dnsPromises.resolveTlsa()
'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:pki@example.com'},{critical: 128, issue: 'pki.example.com'}])。

dnsPromises.resolveCname(hostname)#

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

dnsPromises.resolveMx(hostname)#

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

dnsPromises.resolveNaptr(hostname)#

使用 DNS 协议解析 hostname 的基于正则表达式的记录(NAPTR 记录)。成功后,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 协议解析 hostname 的名称服务器记录(NS 记录)。成功后,Promise 将使用 hostname 可用的名称服务器记录数组解析 (例如 ['ns1.example.com', 'ns2.example.com'])。

dnsPromises.resolvePtr(hostname)#

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

dnsPromises.resolveSoa(hostname)#

使用 DNS 协议解析 hostname 的起始授权记录(SOA 记录)。成功后,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 协议解析 hostname 的服务记录(SRV 记录)。成功后,Promise 将使用具有以下属性的对象数组解析

  • priority
  • weight
  • port
  • name
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dnsPromises.resolveTlsa(hostname)#

使用 DNS 协议解析 hostname 的证书关联记录(TLSA 记录)。成功后,Promise 将使用具有这些属性的对象数组解析

  • certUsage
  • selector
  • match
  • data
{
  certUsage: 3,
  selector: 1,
  match: 1,
  data: [ArrayBuffer]
} 

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''ipv6first''verbatim'

设置 dns.lookup()dnsPromises.lookup()order 的默认值。 该值可以是

  • ipv4first:将默认 order 设置为 ipv4first
  • ipv6first:将默认 order 设置为 ipv6first
  • verbatim:将默认 order 设置为 verbatim

默认值为 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 查询都可以返回以下错误码之一

  • 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 操作系统上,可以通过更改 nsswitch.conf(5) 和/或 resolv.conf(5) 中的设置来修改 dns.lookup() 函数的行为,但更改这些文件将更改运行在同一操作系统上的所有其他程序的行为。

虽然从 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 的线程池。

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

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