Skip to content

DNS

[稳定版: 2 - 稳定版]

稳定版: 2 稳定性: 2 - 稳定版

源代码: lib/dns.js

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

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

js
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
js
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 查询,绕过其他名称解析工具。

js
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)}`)
    })
  })
})
js
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

新增于: v8.3.0

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

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

js
import { Resolver } from 'node:dns'
const resolver = new Resolver()
resolver.setServers(['4.4.4.4'])

// 此请求将使用 4.4.4.4 服务器,独立于全局设置。
resolver.resolve4('example.org', (err, addresses) => {
  // ...
})
js
const { Resolver } = require('node:dns')
const resolver = new Resolver()
resolver.setServers(['4.4.4.4'])

// 此请求将使用 4.4.4.4 服务器,独立于全局设置。
resolver.resolve4('example.org', (err, addresses) => {
  // ...
})

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

Resolver([options])

[历史]

版本变更
v16.7.0, v14.18.0options 对象现在接受 tries 选项。
v12.18.3构造函数现在接受 options 对象。唯一支持的选项是 timeout
v8.3.0v8.3.0 版本中添加

创建一个新的解析器。

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

resolver.cancel()

v8.3.0 版本中添加

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

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

新增于:v15.1.0, v14.17.0

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

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

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

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

dns.getServers()

新增于:v0.11.3

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

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

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

[历史]

版本变更
v22.1.0, v20.13.0verbatim 选项已被弃用,推荐使用新的 order 选项。
v18.4.0为与 node:net 保持兼容性,当传递选项对象时,family 选项可以是字符串 'IPv4' 或字符串 'IPv6'
v18.0.0将无效的回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v17.0.0verbatim 选项现在默认为 true
v8.5.0现在支持 verbatim 选项。
v1.2.0现在支持 all 选项。
v0.1.90新增于:v0.1.90
  • hostname <字符串>

  • options <整数> | <对象>

    • family <整数> | <字符串> 记录族。必须是 460。为了向后兼容,'IPv4''IPv6' 分别解释为 46。值 0 表示返回 IPv4 或 IPv6 地址中的任何一个。如果将值 0{ all: true } 一起使用(见下文),则根据系统的 DNS 解析器返回 IPv4 和 IPv6 地址中的一个或两个。默认值: 0
    • hints <数字> 一个或多个支持的 getaddrinfo 标志。可以通过按位 OR 运算组合多个标志的值。
    • all <布尔值> 当为 true 时,回调函数返回一个包含所有解析地址的数组。否则,返回单个地址。默认值: false
    • order <字符串> 当为 verbatim 时,返回的解析地址未排序。当为 ipv4first 时,解析地址按将 IPv4 地址放在 IPv6 地址之前的顺序排序。当为 ipv6first 时,解析地址按将 IPv6 地址放在 IPv4 地址之前的顺序排序。默认值: verbatim(地址不重新排序)。默认值可以使用 dns.setDefaultResultOrder()--dns-result-order 进行配置。
    • verbatim <布尔值> 当为 true 时,回调函数接收到的 IPv4 和 IPv6 地址按照 DNS 解析器返回它们的顺序排列。当为 false 时,IPv4 地址放在 IPv6 地址之前。此选项将被弃用,推荐使用 order。如果同时指定两者,则 order 具有更高的优先级。新的代码应该只使用 order默认值: true(地址不重新排序)。默认值可以使用 dns.setDefaultResultOrder()--dns-result-order 进行配置。
  • callback <函数>

    • err <错误>
    • address <字符串> IPv4 或 IPv6 地址的字符串表示形式。
    • family <整数> 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() 之前,请花一些时间查阅实现注意事项部分

示例用法:

js
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

// 当 options.all 为 true 时,结果将是一个数组。
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}]
js
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

// 当 options.all 为 true 时,结果将是一个数组。
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 标志

[历史]

版本变更
v13.13.0, v12.17.0添加了对 dns.ALL 标志的支持。

以下标志可以作为提示传递给 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)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.11.14添加于:v0.11.14

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

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

发生错误时,err 是一个 Error 对象,其中 err.code 是错误代码。

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

如果此方法作为其 util.promisify() 版本调用,则它返回一个 Promise,该 Promise 用于包含 hostnameservice 属性的 Object

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

[历史记录]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.1.27v0.1.27 版本中添加

使用 DNS 协议将主机名(例如 'nodejs.org')解析为资源记录数组。callback 函数的参数为 (err, records)。成功时,records 将是一个资源记录数组。单个结果的类型和结构根据 rrtype 而变化:

rrtyperecords 包含结果类型简写方法
'A'IPv4 地址(默认)<字符串>dns.resolve4()
'AAAA'IPv6 地址<字符串>dns.resolve6()
'ANY'任何记录<对象>dns.resolveAny()
'CAA'CA 授权记录<对象>dns.resolveCaa()
'CNAME'正规名称记录<字符串>dns.resolveCname()
'MX'邮件交换记录<对象>dns.resolveMx()
'NAPTR'名称授权指针记录<对象>dns.resolveNaptr()
'NS'域名服务器记录<字符串>dns.resolveNs()
'PTR'指针记录<字符串>dns.resolvePtr()
'SOA'起始授权记录<对象>dns.resolveSoa()
'SRV'服务记录<对象>dns.resolveSrv()
'TXT'文本记录<字符串数组>dns.resolveTxt()

发生错误时,err 是一个 Error 对象,其中 err.codeDNS 错误代码 之一。

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

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v7.2.0此方法现在支持传递 options,特别是 options.ttl
v0.1.16添加于:v0.1.16

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

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

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v7.2.0此方法现在支持传递 options,特别是 options.ttl
v0.1.16v0.1.16 版本中添加

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

dns.resolveAny(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK

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

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

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

js
;[
  { 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)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.3.2添加于:v0.3.2

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

dns.resolveCaa(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v15.0.0, v14.17.0添加于:v15.0.0, v14.17.0

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

dns.resolveMx(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.1.27v0.1.27 版本添加

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

dns.resolveNaptr(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.9.12新增于:v0.9.12

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

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

dns.resolveNs(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.1.90添加于:v0.1.90

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

dns.resolvePtr(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v6.0.0添加于: v6.0.0

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

dns.resolveSoa(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.11.10添加于: v0.11.10

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

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

dns.resolveSrv(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.1.27v0.1.27 版本中添加

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

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

dns.resolveTxt(hostname, callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v0.1.27添加于:v0.1.27

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

dns.reverse(ip, callback)

新增于: v0.1.16

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

发生错误时,err 为一个 Error 对象,其中 err.codeDNS 错误代码 之一。

dns.setDefaultResultOrder(order)

[历史]

版本变更
v22.1.0, v20.13.0现在支持 ipv6first 值。
v17.0.0将默认值更改为 verbatim
v16.4.0, v14.18.0新增于: v16.4.0, v14.18.0
  • 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()

[历史]

版本变更
v22.1.0, v20.13.0现在支持 ipv6first 值。
v20.1.0, v18.17.0新增于:v20.1.0, v18.17.0

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

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

dns.setServers(servers)

新增于:v0.11.3

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

js
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

[历史]

版本变更
v15.0.0作为 require('dns/promises') 公开。
v11.14.0, v10.17.0此 API 不再是实验性的。
v10.6.0新增于:v10.6.0

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

类:dnsPromises.Resolver

新增于:v10.6.0

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

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

js
import { Resolver } from 'node:dns/promises'
const resolver = new Resolver()
resolver.setServers(['4.4.4.4'])

// 此请求将使用 4.4.4.4 服务器,独立于全局设置。
const addresses = await resolver.resolve4('example.org')
js
const { Resolver } = require('node:dns').promises
const resolver = new Resolver()
resolver.setServers(['4.4.4.4'])

// 此请求将使用 4.4.4.4 服务器,独立于全局设置。
resolver.resolve4('example.org').then(addresses => {
  // ...
})

// 或者,可以使用 async-await 风格编写相同的代码。
;(async function () {
  const addresses = await resolver.resolve4('example.org')
})()

dnsPromises API 提供以下方法:

resolver.cancel()

新增于:v15.3.0, v14.17.0

取消此解析器发起的全部未完成的 DNS 查询。相应的 Promise 将被 ECANCELLED 代码的错误所拒绝。

dnsPromises.getServers()

新增于:v10.6.0

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

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

dnsPromises.lookup(hostname[, options])

[历史]

版本变更
v22.1.0, v20.13.0verbatim 选项现已弃用,建议使用新的 order 选项。
v10.6.0新增于:v10.6.0
  • hostname <string>
  • options <integer> | <Object>
    • family <integer> 记录族。必须为 460。值为 0 表示返回 IPv4 或 IPv6 地址。如果将值 0{ all: true } 一起使用(见下文),则根据系统的 DNS 解析器返回 IPv4 和 IPv6 地址中的一个或两者。默认值: 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 为具有属性 addressfamily 的对象数组来解析。

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

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

示例用法:

js
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}]
})
js
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)

新增于:v10.6.0

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

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

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

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

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

dnsPromises.resolve(hostname[, rrtype])

新增于: v10.6.0

  • 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])

新增于:v10.6.0

  • 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])

新增于:v10.6.0

  • 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)

新增于:v10.6.0

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

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

以下是结果对象的示例:

js
;[
  { 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)

新增于:v15.0.0, v14.17.0

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

dnsPromises.resolveCname(hostname)

新增于:v10.6.0

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

dnsPromises.resolveMx(hostname)

新增于:v10.6.0

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

dnsPromises.resolveNaptr(hostname)

Added in: v10.6.0

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

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

dnsPromises.resolveNs(hostname)

Added in: v10.6.0

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

dnsPromises.resolvePtr(hostname)

新增于:v10.6.0

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

dnsPromises.resolveSoa(hostname)

新增于:v10.6.0

使用 DNS 协议解析主机名的起始授权记录(SOA 记录)。成功时,Promise 将解析为包含以下属性的对象:

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

dnsPromises.resolveSrv(hostname)

新增于:v10.6.0

使用 DNS 协议解析主机名的服务记录(SRV 记录)。成功时,Promise 将解析为包含以下属性的对象数组:

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

dnsPromises.resolveTxt(hostname)

新增于: v10.6.0

使用 DNS 协议解析 hostname 的文本查询 (TXT 记录)。成功时,Promise 将解析为一个二维数组,其中包含 hostname 可用的文本记录(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每个子数组包含一条记录的 TXT 片段。根据用例的不同,这些片段可以连接在一起,也可以单独处理。

dnsPromises.reverse(ip)

新增于: v10.6.0

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

发生错误时,Promise 将被一个 Error 对象拒绝,其中 err.codeDNS 错误代码 之一。

dnsPromises.setDefaultResultOrder(order)

[历史记录]

版本变更
v22.1.0, v20.13.0现在支持 ipv6first 值。
v17.0.0默认值更改为 verbatim
v16.4.0, v14.18.0新增于: v16.4.0, v14.18.0
  • 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()

新增于:v20.1.0, v18.17.0

获取 dnsOrder 的值。

dnsPromises.setServers(servers)

新增于:v10.6.0

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

js
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() 的调用是异步的,但它是在 libuv 的线程池上作为对 getaddrinfo(3) 的同步调用实现的。这可能会对某些应用程序产生令人惊讶的负面性能影响,有关更多信息,请参阅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 中的配置。