NodeJs 第十三章(DNS模块)

279 阅读6分钟

引言

在 Node.js 中,dns 模块提供了与域名系统(DNS)相关的功能,允许开发者将域名解析为 IP 地址,或者将 IP 地址反向解析为域名。该模块包含两种类型的函数:一种是使用底层操作系统的设施进行域名解析,不进行任何网络通信;另一种是通过网络进行 DNS 查询。

DNS

DNS 模块的基本用法

要使用 DNS 模块,首先需要在 Node.js 中引入该模块:

const dns = require('dns');

解析域名

DNS 模块提供了 dns.resolve() 方法用于解析域名,可以将域名解析为 IP 地址。例如,我们可以通过以下代码将 www.baidu.com 解析为 IP 地址:

dns.resolve('www.baidu.com', (err, addresses) => {
  if (err) {
    console.error(err);
  } else {
    console.log('IP 地址:', addresses);
  }
});

反向解析 IP 地址

除了解析域名,DNS 模块还提供了 dns.reverse() 方法用于反向解析 IP 地址,可以将 IP 地址解析为域名。例如,我们可以通过以下代码将 8.8.8.8 反向解析为域名:

dns.reverse('8.8.8.8', (err, hostnames) => {
  if (err) {
    console.error(err);
  } else {
    console.log('域名:', hostnames);
  }
});

DNS 模块的高级用法

除了基本的域名解析和反向解析功能,DNS 模块还提供了一些高级的用法,例如:

设置 DNS 服务器

可以使用 dns.setServers() 方法设置自定义的 DNS 服务器,以便在解析域名时使用指定的 DNS 服务器。例如,我们可以通过以下代码设置 Google 的 DNS 服务器:

dns.setServers(['8.8.8.8', '8.8.4.4']);

image.png

获取所有记录类型

可以使用 dns.resolveAny() 方法获取指定域名的所有记录类型,返回一个包含所有记录类型的数组。例如,我们可以通过以下代码获取 www.example.com 的所有记录类型:

dns.resolveAny('www.example.com', (err, records) => {
  if (err) {
    console.error(err);
  } else {
    console.log('所有记录类型:', records);
  }
});

// 所有记录类型: [ { value: 'www.example.com-v4.edgesuite.net', type: 'CNAME' } ]

异步解析域名

异步方法不会阻塞事件循环,因此更适合于需要快速响应的应用场景。我们可以通过调用 dns.lookup() 方法来异步解析域名。

const dns = require('dns');

// 异步解析域名
dns.lookup('www.example.com', (err, address, family) => {
    console.log(`IP 地址: ${address}`);
});

在这个例子中,我们调用了 dns.lookup() 方法来获取域名 www.example.com 对应的 IP 地址。当查询完成后,回调函数会被触发,并输出解析得到的 IP 地址。

同步解析域名

如果你的应用程序更倾向于顺序执行且不介意等待 DNS 查询完成,可以考虑使用同步方法。Node.js 提供了 dns.lookupSync() 方法来满足这种需求。

const dns = require('dns');

try {
    const address = dns.lookupSync('www.example.com');
    console.log(`IP 地址: ${address}`);
} catch (error) {
    console.error(`发生错误: ${error.message}`);
}

此示例展示了如何使用 dns.lookupSync() 方法同步地获取域名的 IP 地址。如果 DNS 查询过程中出现任何问题,会抛出异常,我们在 try...catch 结构中处理这些可能发生的错误。

DNS 查询选项

除了基本的域名解析外,dns.lookup() 方法还允许传递额外的选项参数来定制查询行为。例如,你可以指定是否需要 IPv4 或 IPv6 地址,或者设置超时时间等。

const dns = require('dns');

// 设置查询选项
const options = {
    all: true,
    hints: dns.ADDRCONFIG,
    families: 4
};

// 使用选项进行异步解析
dns.lookup('www.example.com', options, (err, addresses, family) => {
    if (err) throw err;
    addresses.forEach((address) => {
        console.log(`IP 地址: ${address.address}`);
    });
});

在这个例子中,我们通过设置 options 对象来定制 DNS 查询。all 选项如果设为 true,则返回所有找到的地址;hints 选项允许指定查询类型(如只查询 IPv4 地址),而 families 则明确指定要查询的地址族(IPv4 或 IPv6)。

错误处理

在使用 dns 模块的方法时,需要注意处理可能出现的错误。错误对象通常包含 codemessage 属性,code 表示错误的类型,如 'ENOTFOUND' 表示域名未找到,'ESERVFAIL' 表示 DNS 服务器失败等。

const dns = require('dns');

dns.resolve('nonexistentdomain.com', 'A', (err, records) => {
    if (err) {
        if (err.code === 'ENOTFOUND') {
            console.log('域名未找到');
        } else {
            console.error('查询失败:', err);
        }
    } else {
        console.log('查询结果:', records);
    }
});

资源记录类型常量

这些常量用于指定 dns.resolve() 等方法要查询的 DNS 资源记录类型。

dns.A

  • 含义:表示 IPv4 地址记录。当你查询一个域名的 A 记录时,会得到该域名对应的 IPv4 地址。
const dns = require('dns');
dns.resolve('www.example.com', dns.A, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('IPv4 地址记录:', records);
    }
});

dns.AAAA

  • 含义:表示 IPv6 地址记录。用于查询域名对应的 IPv6 地址。
  • 示例
const dns = require('dns');
dns.resolve('www.example.com', dns.AAAA, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('IPv6 地址记录:', records);
    }
});

dns.MX

  • 含义:表示邮件交换记录。用于指定负责接收该域名电子邮件的邮件服务器。
const dns = require('dns');
dns.resolve('example.com', dns.MX, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('邮件交换记录:', records);
    }
});

dns.CNAME

  • 含义:表示规范名称记录。用于将一个域名指向另一个域名,常用于创建别名。
const dns = require('dns');
dns.resolve('www.alias.example.com', dns.CNAME, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('规范名称记录:', records);
    }
});

dns.NS

  • 含义:表示名称服务器记录。用于指定负责该域名的 DNS 服务器。
const dns = require('dns');
dns.resolve('example.com', dns.NS, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('名称服务器记录:', records);
    }
});

dns.TXT

  • 含义:表示文本记录。常用于存储与域名相关的任意文本信息,如 SPF 记录、DKIM 记录等。
const dns = require('dns');
dns.resolve('example.com', dns.TXT, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('文本记录:', records);
    }
});
dns.SRV
  • 含义:表示服务记录。用于指定特定服务的服务器位置,如 SIP 服务器、LDAP 服务器等。
const dns = require('dns');
dns.resolve('_sip._tcp.example.com', dns.SRV, (err, records) => {
    if (err) {
        console.error('查询失败:', err);
    } else {
        console.log('服务记录:', records);
    }
});

dns.lookup()hints 标志常量

dns.ADDRCONFIG
  • 含义:表示只返回与本地系统配置的 IP 地址族相匹配的解析结果。例如,如果本地系统只配置了 IPv4 地址,那么只会返回 IPv4 地址的解析结果。
const dns = require('dns');
dns.lookup('www.example.com', { hints: dns.ADDRCONFIG }, (err, address, family) => {
    if (err) {
        console.error('解析失败:', err);
    } else {
        console.log(`IP 地址: ${address}`);
        console.log(`地址族: IPv${family}`);
    }
});
dns.V4MAPPED
  • 含义:当查询 IPv6 地址时,如果没有找到 IPv6 地址记录,会尝试返回 IPv4 地址的映射结果。
const dns = require('dns');
dns.lookup('www.example.com', { family: 6, hints: dns.V4MAPPED }, (err, address, family) => {
    if (err) {
        console.error('解析失败:', err);
    } else {
        console.log(`IP 地址: ${address}`);
        console.log(`地址族: IPv${family}`);
    }
});

这些常量在使用 dns 模块进行 DNS 查询时非常有用,可以帮助你更精确地指定查询的类型和条件。

APi

Lookup

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

  • hostname:要解析的域名,如 'www.example.com'

  • options(可选):一个对象,包含以下可选属性:

    • family:指定解析的 IP 地址族,值可以是 4(IPv4)、6(IPv6)或 0(表示同时尝试 IPv4 和 IPv6),默认值为 0
    • hints:一个或多个 dns.ADDRCONFIGdns.V4MAPPED 标志的组合,用于指定解析的提示信息。
    • all:如果设置为 true,回调函数将返回一个包含所有解析结果的数组;否则,只返回第一个解析结果。默认值为 false
  • callback:解析完成后的回调函数,接受三个参数:

    • err:如果解析过程中出现错误,该参数将包含错误对象;否则为 null
    • address:解析得到的 IP 地址。
    • family:解析得到的 IP 地址族,值为 46

reslove

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

  • hostname:要解析的域名。

  • rrtype(可选):指定要查询的资源记录类型,默认值为 'A'(IPv4 地址记录)。常见的记录类型包括 'A''AAAA'(IPv6 地址记录)、'MX'(邮件交换记录)、'CNAME'(规范名称记录)等。

  • callback:查询完成后的回调函数,接受两个参数:

    • err:如果查询过程中出现错误,该参数将包含错误对象;否则为 null
    • records:一个包含查询结果的数组。

dns.reverse()

dns.reverse(ip, callback)

  • 作用:将 IP 地址反向解析为域名。

  • 参数

    • ip:要反向解析的 IP 地址。

    • callback:反向解析完成后的回调函数,接受两个参数:

      • err:如果解析过程中出现错误,该参数将包含错误对象;否则为 null
      • hostnames:一个包含反向解析得到的域名的数组。