DNS
源代码: 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: 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
新增于: v8.3.0
用于 DNS 请求的独立解析器。
创建新的解析器将使用默认服务器设置。使用 resolver.setServers()
设置解析器使用的服务器不会影响其他解析器:
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) => {
// ...
})
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.getServers()
resolver.resolve()
resolver.resolve4()
resolver.resolve6()
resolver.resolveAny()
resolver.resolveCaa()
resolver.resolveCname()
resolver.resolveMx()
resolver.resolveNaptr()
resolver.resolveNs()
resolver.resolvePtr()
resolver.resolveSoa()
resolver.resolveSrv()
resolver.resolveTxt()
resolver.reverse()
resolver.setServers()
Resolver([options])
[历史]
版本 | 变更 |
---|---|
v16.7.0, v14.18.0 | options 对象现在接受 tries 选项。 |
v12.18.3 | 构造函数现在接受 options 对象。唯一支持的选项是 timeout 。 |
v8.3.0 | v8.3.0 版本中添加 |
创建一个新的解析器。
resolver.cancel()
v8.3.0 版本中添加
取消此解析器发出的所有未完成的 DNS 查询。相应的回调将使用代码 ECANCELLED
的错误被调用。
resolver.setLocalAddress([ipv4][, ipv6])
新增于:v15.1.0, v14.17.0
解析器实例将从指定的 IP 地址发送其请求。这允许程序在多宿主系统上使用时指定出站接口。
如果未指定 v4 或 v6 地址,则将其设置为默认值,操作系统将自动选择本地地址。
解析器在向 IPv4 DNS 服务器发出请求时将使用 v4 本地地址,在向 IPv6 DNS 服务器发出请求时将使用 v6 本地地址。解析请求的 rrtype
对使用的本地地址没有影响。
dns.getServers()
新增于:v0.11.3
- 返回值: <string[]>
返回一个 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)
[历史]
版本 | 变更 |
---|---|
v22.1.0, v20.13.0 | verbatim 选项已被弃用,推荐使用新的 order 选项。 |
v18.4.0 | 为与 node:net 保持兼容性,当传递选项对象时,family 选项可以是字符串 'IPv4' 或字符串 'IPv6' 。 |
v18.0.0 | 将无效的回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK 。 |
v17.0.0 | verbatim 选项现在默认为 true 。 |
v8.5.0 | 现在支持 verbatim 选项。 |
v1.2.0 | 现在支持 all 选项。 |
v0.1.90 | 新增于:v0.1.90 |
hostname
<字符串>family
<整数> | <字符串> 记录族。必须是4
、6
或0
。为了向后兼容,'IPv4'
和'IPv6'
分别解释为4
和6
。值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
<函数>
将主机名(例如 'nodejs.org'
)解析为找到的第一个 A(IPv4)或 AAAA(IPv6)记录。所有 option
属性都是可选的。如果 options
是一个整数,则它必须是 4
或 6
——如果没有提供 options
,则如果找到 IPv4 或 IPv6 地址,或两者兼有,则返回这些地址。
当 all
选项设置为 true
时,callback
的参数变为 (err, addresses)
,其中 addresses
是一个包含 address
和 family
属性的对象数组。
发生错误时,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
// 当 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}]
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
,则它返回一个包含 address
和 family
属性的 Object
的 Promise
。
支持的 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
实现将给定的 address
和 port
解析为主机名和服务。
如果 address
不是有效的 IP 地址,则会抛出 TypeError
。port
将被强制转换为数字。如果它不是合法的端口,则会抛出 TypeError
。
发生错误时,err
是一个 Error
对象,其中 err.code
是错误代码。
import dns from 'node:dns'
dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
console.log(hostname, service)
// 打印:localhost ssh
})
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
用于包含 hostname
和 service
属性的 Object
。
dns.resolve(hostname[, rrtype], callback)
[历史记录]
版本 | 变更 |
---|---|
v18.0.0 | 将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK 。 |
v0.1.27 | v0.1.27 版本中添加 |
使用 DNS 协议将主机名(例如 'nodejs.org'
)解析为资源记录数组。callback
函数的参数为 (err, records)
。成功时,records
将是一个资源记录数组。单个结果的类型和结构根据 rrtype
而变化:
rrtype | records 包含 | 结果类型 | 简写方法 |
---|---|---|---|
'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.code
是 DNS 错误代码 之一。
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 |
hostname
<字符串> 要解析的主机名。options
<对象>ttl
<布尔值> 获取每个记录的生存时间 (TTL) 值。设置为true
时,回调函数接收的是一个{ address: '1.2.3.4', ttl: 60 }
对象数组,而不是字符串数组,TTL 以秒为单位表示。
callback
<函数>
使用 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.16 | v0.1.16 版本中添加 |
hostname
<字符串> 要解析的主机名。options
<对象>ttl
<布尔值> 获取每个记录的生存时间 (TTL) 值。当为true
时,回调函数接收一个{ address: '0:1:2:3:4:5:6:7', ttl: 60 }
对象数组,而不是字符串数组,TTL 以秒为单位表示。
callback
<函数>
使用 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
对象示例:
;[
{ 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 协议解析 hostname
的 CNAME
记录。传递给 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 协议解析 hostname
的 CAA
记录。传递给 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.27 | v0.1.27 版本添加 |
使用 DNS 协议解析 hostname
的邮件交换记录(MX
记录)。传递给 callback
函数的 addresses
参数将包含一个对象数组,每个对象都包含 priority
和 exchange
属性(例如 [{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
{
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
{
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.27 | v0.1.27 版本中添加 |
使用 DNS 协议解析 hostname
的服务记录(SRV
记录)。传递给 callback
函数的 addresses
参数将是一个包含以下属性的对象数组:
priority
weight
port
name
{
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
ip
<string>callback
<Function>err
<Error>hostnames
<string[]>
执行反向 DNS 查询,将 IPv4 或 IPv6 地址解析为主机名数组。
发生错误时,err
为一个 Error
对象,其中 err.code
为 DNS 错误代码 之一。
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
servers
<string[]> RFC 5952 格式的地址数组
设置执行 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
[历史]
版本 | 变更 |
---|---|
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').promises
或 require('node:dns/promises')
访问此 API。
类:dnsPromises.Resolver
新增于:v10.6.0
用于 DNS 请求的独立解析器。
创建新的解析器使用默认服务器设置。使用 resolver.setServers()
设置解析器使用的服务器不会影响其他解析器:
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')
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.getServers()
resolver.resolve()
resolver.resolve4()
resolver.resolve6()
resolver.resolveAny()
resolver.resolveCaa()
resolver.resolveCname()
resolver.resolveMx()
resolver.resolveNaptr()
resolver.resolveNs()
resolver.resolvePtr()
resolver.resolveSoa()
resolver.resolveSrv()
resolver.resolveTxt()
resolver.reverse()
resolver.setServers()
resolver.cancel()
新增于:v15.3.0, v14.17.0
取消此解析器发起的全部未完成的 DNS 查询。相应的 Promise 将被 ECANCELLED
代码的错误所拒绝。
dnsPromises.getServers()
新增于:v10.6.0
- 返回值: <string[]>
返回一个 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])
[历史]
版本 | 变更 |
---|---|
v22.1.0, v20.13.0 | verbatim 选项现已弃用,建议使用新的 order 选项。 |
v10.6.0 | 新增于:v10.6.0 |
hostname
<string>options
<integer> | <Object>family
<integer> 记录族。必须为4
、6
或0
。值为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
是一个整数,则它必须是 4
或 6
– 如果未提供 options
,则如果找到,则返回 IPv4 或 IPv6 地址,或两者。
使用 all
选项设置为 true
时,Promise
将以 addresses
为具有属性 address
和 family
的对象数组来解析。
发生错误时,Promise
将被一个 Error
对象拒绝,其中 err.code
是错误代码。请记住,err.code
不仅在主机名不存在时设置为 'ENOTFOUND'
,而且在其他查找失败的情况下(例如没有可用的文件描述符)也会设置为 '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)
新增于:v10.6.0
使用操作系统底层的 getnameinfo
实现将给定的 address
和 port
解析为主机名和服务名。
如果 address
不是有效的 IP 地址,则会抛出 TypeError
。port
将被强制转换为数字。如果它不是合法的端口,则会抛出 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) // 输出:localhost ssh
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
使用 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() |
'TXT' | 文本记录 | <string[]> | dnsPromises.resolveTxt() |
发生错误时,Promise
将被一个 Error
对象拒绝,其中 err.code
是 DNS 错误代码 之一。
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
hostname
<string>
使用 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' } |
以下是结果对象的示例:
;[
{ 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
hostname
<string>
使用 DNS 协议解析 hostname
的 CAA
记录。成功后,Promise
将解析为一个对象数组,其中包含 hostname
可用的认证机构授权记录(例如 [{critical: 0, iodef: 'mailto:[email protected]'},{critical: 128, issue: 'pki.example.com'}]
)。
dnsPromises.resolveCname(hostname)
新增于:v10.6.0
hostname
<string>
使用 DNS 协议解析 hostname
的 CNAME
记录。成功后,Promise
将解析为一个数组,其中包含 hostname
可用的规范名称记录(例如 ['bar.example.com']
)。
dnsPromises.resolveMx(hostname)
新增于:v10.6.0
hostname
<string>
使用 DNS 协议解析 hostname
的邮件交换记录(MX
记录)。成功后,Promise
将解析为一个对象数组,每个对象包含 priority
和 exchange
属性(例如 [{priority: 10, exchange: 'mx.example.com'}, ...]
)。
dnsPromises.resolveNaptr(hostname)
Added in: v10.6.0
hostname
<string>
使用 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)
Added in: v10.6.0
hostname
<string>
使用 DNS 协议解析 hostname
的域名服务器记录(NS
记录)。成功时,Promise
将解析为 hostname
可用的域名服务器记录数组(例如 ['ns1.example.com', 'ns2.example.com']
)。
dnsPromises.resolvePtr(hostname)
新增于:v10.6.0
hostname
<string>
使用 DNS 协议解析主机名的指针记录(PTR
记录)。成功时,Promise
将解析为包含回复记录的字符串数组。
dnsPromises.resolveSoa(hostname)
新增于:v10.6.0
hostname
<string>
使用 DNS 协议解析主机名的起始授权记录(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)
新增于:v10.6.0
hostname
<string>
使用 DNS 协议解析主机名的服务记录(SRV
记录)。成功时,Promise
将解析为包含以下属性的对象数组:
priority
weight
port
name
{
priority: 10,
weight: 5,
port: 21223,
name: 'service.example.com'
}
dnsPromises.resolveTxt(hostname)
新增于: v10.6.0
hostname
<string>
使用 DNS 协议解析 hostname
的文本查询 (TXT
记录)。成功时,Promise
将解析为一个二维数组,其中包含 hostname
可用的文本记录(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]
)。每个子数组包含一条记录的 TXT 片段。根据用例的不同,这些片段可以连接在一起,也可以单独处理。
dnsPromises.reverse(ip)
新增于: v10.6.0
ip
<string>
执行反向 DNS 查询,将 IPv4 或 IPv6 地址解析为主机名数组。
发生错误时,Promise
将被一个 Error
对象拒绝,其中 err.code
是 DNS 错误代码 之一。
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
servers
<string[]> RFC 5952 格式的地址数组
设置执行 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()
的调用是异步的,但它是在 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
中的配置。