首發於個人博客:www.ahonn.me/post/57javascript
做爲 Node.js 的內置模塊之一,dns 模塊平常的使用率並不高。但在某些狀況下 dns 模塊倒是很是有用的,例如在須要經過 Node.js 來判斷本地網絡是否暢通;或者在某些高併發的狀況下,能夠手動經過 dns 模塊進行查詢並緩存以後,再進行請求發送。html
因此 dns 模塊仍是有必要好好了解了解的,畢竟說不定何時就用上了呢?java
做爲一個合格的 dns 模塊,必然是須要具有 DNS 解析的功能了。在 dns 模塊中,用於解析的函數分爲兩種,一種是經過使用底層操做系統工具進行本地域名解析,且無需進行網絡通訊。而另外一個則是經過鏈接 DNS 服務器進行域名解析。node
本地解析顧名思義就是不進行網絡請求來進行解析,通常用來查看本地請求某個域名時,對應的 IP 地址是什麼。dns 模塊中經過 dns.lookup()
方法來進行本地域名解析,解析的過程相似於 ping
。緩存
const dns = require('dns');
dns.lookup('ahonn.me', (err, address, family) => {
if (err) {
throw err;
}
console.log('address: %s, family: IPv%s', address, family);
});
// address: 151.101.100.133, family: IPv4
複製代碼
能夠經過函數的第二個參數 options 來進行解析的設置,例如可以傳入 { all: true }
,來獲取全部的解析結果(包括 IPv4 與 IPv6)。服務器
除了 dns.lookup()
以外,dns 模塊中的其餘函數都是經過網絡進行 DNS 解析。其中最主要的一個方法就是: dsn.resolve()
。網絡
const dns = require('dns');
dns.resolve('ahonn.me', (err, records) => {
if (err) {
throw err;
}
console.log(records);
});
// [ '151.101.100.133' ]
複製代碼
該方法經過二個參數能夠指定解析的資源記錄類型,默認爲 ’A’,即返回 IPv4 地址。若是想返回全部的資源紀錄類型的值,能夠經過 dns.resolveAny()
來獲取。併發
const dns = require('dns');
dns.resolveAny('ahonn.me', (err, records) => {
if (err) {
throw err;
}
console.log(records);
});
/* [ { address: '151.101.100.133', ttl: 369, type: 'A' }, { value: 'dns10.hichina.com', type: 'NS' }, { value: 'dns9.hichina.com', type: 'NS' }, { entries: [ 'google-site-verification=j5dWC85DkoAfUR50W00ewfii3X9ouH55HnyBP6oZxGE' ], type: 'TXT' }, { nsname: 'dns9.hichina.com', hostmaster: 'hostmaster.hichina.com', serial: 2015090709, refresh: 3600, retry: 1200, expire: 3600, minttl: 360, type: 'SOA' }] */
複製代碼
與此同時,模塊還提供了一些與資源記錄類型綁定的函數,用於單獨獲取某資源記錄類型的值。例如 dns.resolve4()
,dns.resolve6()
與dns.resolveCname()
等。函數
通常狀況下咱們所說的 DNS 解析指的是正向解析,即經過域名查詢 IP 地址。那麼既然有正向解析就必然有反向解析了(rDNS)。dns 模塊中一樣提供了方法來進行反向查詢,經過 IP 地址查找對應的域名。高併發
dns.resolve('google.com', (err, addresses) => {
if (err) {
throw err;
}
addresses.map(ip => {
dns.reverse(ip, (err, hostnames) => {
if (err) {
throw err;
}
console.log(ip, hostnames);
});
})
});
複製代碼
TIPS: 在命令行中咱們能夠經過
nslookup -qt=ptr <IP>
來查看該 IP 地址反向解析的結果信息。
還須要注意的是大多數 IP 地址都沒有作反向域名解析,設置反向解析須要找對應的服務器 IP 提供商進行設置。如何爲服務器 IP 地址添加反向解析可參考這篇文章:爲服務器IP添加反向DNS解析 | 祁勁鬆的博客👨💻。
反向解析主要應用到郵件服務器中來阻攔垃圾郵件,若郵件發送者的 IP 地址沒有設置反向解析則將其視爲垃圾郵件。
默認狀況下 DNS 服務器的 IP 地址是由網關進行分配的,但咱們也能夠設置爲咱們想使用的 IP 地址。比較有名的是國內通用的 114.114.114.114 以及 Google 的 8.8.8.8。
Dns 模塊能夠經過 dns.setServers()來設置模塊使用哪些 DNS 服務器進行解析。例如咱們將 dns 模塊使用的 DNS 服務器設置爲 8.8.8.8。
const dns = require('dns');
dns.setServers(['8.8.8.8']);
dns.resolove('ahonn.me', (err, records) => {
if (err) {
throw err;
}
console.log(records);
});
複製代碼
另外咱們也能夠經過 dns.Resolver()進行獨立的設置 DNS 服務器 IP 地址,這樣就不會影響 dns 模塊的默認 DNS 服務器配置。 dns.Resolver() 的實例擁有與 dns 模塊相同的 lookup, resolve等方法。
const { Resolver } = require('dns');
const resolver = new Resolver();
resolver.setServers(['8.8.8.8']);
reslover.reslove('ahonn.me', (err, records) => {
if (err) {
throw err;
}
console.log(records);
});
複製代碼
經過 dns 模塊中的反向解析能夠判斷是否爲垃圾郵件以外,正向解析能夠定時向指定的 DNS 服務發送請求進行 DNS 解析,用來確認當前是否鏈接到網絡(網絡斷開的狀況下必然是沒有辦法經過網絡進行 DNS 解析)。
const { Resolver } = require('dns');
function internetAvailable() {
const resolver = new Resolver();
resolver.setServers(['8.8.8.8']);
reslover.reslove('google.com', (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
}
複製代碼