DNS#

稳定性:2 - 稳定

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: IPv6
const 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
  • maxTimeout <integer> 最大重试超时时间(毫秒)。默认值: 0(禁用)。

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()#

返回当前配置用于 DNS 解析的 IP 地址字符串数组,格式符合 RFC 5952。如果使用了自定义端口,字符串将包含端口部分。

[
  '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 } 一起使用(见下文),则根据系统的 DNS 解析器,返回 IPv4 和 IPv6 地址中的一个或两个。默认值: 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 时,回调按 DNS 解析器返回的顺序接收 IPv4 和 IPv6 地址。当为 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 很可能是操作系统使用的名称解析服务中存在 bug 的标志。

将主机名(例如 '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'

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 属性的对象 Promise

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

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

rrtype records 包含 结果类型 简写方法
'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
    'CAA' 参考 dns.resolveCaa()
    'CNAME' value
    'MX' 参考 dns.resolveMx()
    'NAPTR' 参考 dns.resolveNaptr()
    'NS' value
    'PTR' value
    '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 threads) 时,主线程中的 dns.setDefaultResultOrder() 不会影响工作线程中的默认 DNS 顺序。

    dns.getDefaultResultOrder()#

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

    • ipv4first: order 默认为 ipv4first
    • ipv6first: order 默认为 ipv6first
    • verbatim: order 默认为 verbatim

    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 Promise API#

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

    类: 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()#

    返回当前配置用于 DNS 解析的 IP 地址字符串数组,格式符合 RFC 5952。如果使用了自定义端口,字符串将包含端口部分。

    [
      '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 } 一起使用(见下文),则根据系统的 DNS 解析器,返回 IPv4 和 IPv6 地址中的一个或两个。默认值: 0
      • hints <number> 一个或多个 受支持的 getaddrinfo 标志。可以通过对它们的值进行按位 OR 运算来传递多个标志。
      • all <boolean> 如果为 truePromise 将以所有地址的数组形式解析。否则,返回单个地址。默认值: 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 将以包含 addressfamily 属性的对象数组形式的 addresses 解析。

    发生错误时,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 ssh
    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

    rrtype records 包含 结果类型 简写方法
    '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
    'CAA' 参考 dnsPromises.resolveCaa()
    'CNAME' value
    'MX' 参考 dnsPromises.resolveMx()
    'NAPTR' 参考 dnsPromises.resolveNaptr()
    'NS' value
    'PTR' value
    '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.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 的线程池。

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

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