Node.jsでDNSを制覇!dnsPromises.resolve()のエラーと解決策

2025-05-27

Node.jsにおけるdnsPromises.resolve()は、DNSプロトコルを使用してホスト名(例: example.com)に対応する様々な種類のリソースレコードを取得するためのPromiseベースのメソッドです。

通常のdns.resolve()がコールバック関数を受け取るのに対し、dnsPromises.resolve()はES6のPromiseを返すため、async/await構文と組み合わせてよりモダンで読みやすい非同期処理を記述できます。

dnsPromises.resolve()の主な特徴と使い方

  1. Promiseを返す: 成功時には解決されたPromiseがリソースレコードの配列を返し、失敗時にはエラーがrejectされます。
  2. DNSプロトコルを使用: システムのhostsファイルなどではなく、純粋なDNSサーバーに対して問い合わせを行います。これにより、実際のDNSレコードを正確に取得できます。
  3. レコードタイプを指定可能: 取得したいリソースレコードのタイプ(例: Aレコード、AAAAレコード、MXレコードなど)を指定できます。

構文

dnsPromises.resolve(hostname[, rrtype]);
  • rrtype (オプション): 取得したいリソースレコードのタイプを指定します。指定しない場合、デフォルトでAレコード(IPv4アドレス)が解決されます。
  • hostname: 解決したいホスト名(例: 'www.google.com'

rrtypeの例

rrtypeには様々なDNSレコードタイプを指定できます。いくつか例を挙げます。

  • 'ANY': 利用可能なすべてのレコード
  • 'CAA': 証明書発行機関承認レコード (Certification Authority Authorization records)
  • 'SOA': 権限の開始レコード (Start of Authority record)
  • 'PTR': ポインタレコード (Pointer records) (通常、逆引きDNSルックアップに使用)
  • 'CNAME': 正規名レコード (Canonical Name records)
  • 'SRV': サービスロケータレコード (Service locator records)
  • 'TXT': テキストレコード
  • 'NS': ネームサーバーレコード (Name Server records)
  • 'MX': メール交換レコード (Mail Exchange records)
  • 'AAAA': IPv6アドレス
  • 'A' (デフォルト): IPv4アドレス

使用例

Aレコード (IPv4アドレス) の取得

const dnsPromises = require('dns').promises;

async function resolveIPv4Address() {
  try {
    const addresses = await dnsPromises.resolve('nodejs.org', 'A');
    console.log('IPv4アドレス:', addresses);
  } catch (error) {
    console.error('DNS解決エラー:', error);
  }
}

resolveIPv4Address();

MXレコード (メールサーバー情報) の取得

const dnsPromises = require('dns').promises;

async function resolveMxRecords() {
  try {
    const mxRecords = await dnsPromises.resolve('google.com', 'MX');
    console.log('MXレコード:', mxRecords);
    // 例: [{ priority: 10, exchange: 'alt1.aspmx.l.google.com' }, ...]
  } catch (error) {
    console.error('DNS解決エラー:', error);
  }
}

resolveMxRecords();

エラーハンドリング

DNS解決が失敗した場合(例: ホスト名が存在しない、DNSサーバーに到達できないなど)は、Promiseがrejectされ、catchブロックでエラーを捕捉できます。

const dnsPromises = require('dns').promises;

async function resolveNonExistentDomain() {
  try {
    const records = await dnsPromises.resolve('nonexistent-domain-12345.com');
    console.log('レコード:', records);
  } catch (error) {
    console.error('エラーが発生しました:', error.code, error.hostname);
    // 例: エラーが発生しました: ENOTFOUND nonexistent-domain-12345.com
  }
}

resolveNonExistentDomain();

Node.jsにはdns.lookup()という似た機能がありますが、これらは用途が異なります。

  • dnsPromises.resolve(): DNSプロトコルのみを使用し、指定されたDNSレコードタイプを解決します。システムのhostsファイルやOSのキャッシュは使用しません。主に、特定のDNSレコードタイプ(MX, NSなど)の情報を取得したい場合や、純粋なDNS解決の結果が必要な場合に用います。


ENOTFOUND (No such host)

最も一般的なエラーの一つです。指定されたホスト名に対するDNSレコードが見つからない場合に発生します。

原因

  • ファイアウォール/セキュリティグループ
    DNSクエリがブロックされている。
  • インターネット接続がない
    サーバーがインターネットに接続されていない。
  • DNSサーバーの問題
    設定されているDNSサーバーがダウンしている、または正しく機能していない。
  • ドメインがまだ伝播していない
    新しく登録したドメインやDNSレコードが、まだ世界中のDNSサーバーに伝播しきっていない。
  • ドメイン名の誤り
    スペルミス、存在しないドメイン名を指定している。

トラブルシューティング

  • ファイアウォールの確認
    サーバーのファイアウォール(iptables、Windows Defender Firewallなど)や、クラウドプロバイダーのセキュリティグループ(AWS Security Group, Azure Network Security Groupなど)でDNSトラフィック(UDPポート53)が許可されているか確認してください。
  • ネットワーク接続の確認
    サーバーがインターネットに接続されていることを確認してください。
  • DNSサーバーの変更
    Node.jsのdns.setServers()を使用して、一時的にGoogle Public DNS (8.8.8.8, 8.8.4.4) やCloudflare DNS (1.1.1.1, 1.0.0.1) などの信頼性の高いDNSサーバーに変更して試してみてください。
    const dnsPromises = require('dns').promises;
    dnsPromises.setServers(['8.8.8.8', '8.8.4.4']); // Google Public DNS
    // または
    // dnsPromises.setServers(['1.1.1.1', '1.0.0.1']); // Cloudflare DNS
    
    async function resolveWithCustomDns() {
      try {
        const addresses = await dnsPromises.resolve('example.com');
        console.log('解決成功:', addresses);
      } catch (error) {
        console.error('解決失敗:', error);
      }
    }
    resolveWithCustomDns();
    
  • nslookupまたはdigコマンドで確認
    特定のDNSレコードタイプで問題が発生している場合、nslookupdigで直接確認できます。
    nslookup -type=A example.com
    dig example.com A
    
    これで解決できない場合は、Node.jsの問題ではなく、DNS設定またはネットワークの問題の可能性が高いです。
  • pingコマンドで確認
    解決しようとしているホスト名が、OSレベルで解決できるかpingコマンドで試してみてください。
    ping example.com
    
  • ドメイン名の確認
    指定したホスト名が正しいか再確認してください。簡単なタイプミスでもこのエラーが発生します。

ETIMEOUT (Query timed out)

DNSクエリがタイムアウトした場合に発生します。これは、DNSサーバーからの応答が設定された時間内に得られなかったことを意味します。

原因

  • 不適切なDNSサーバー設定
    存在しない、または到達できないDNSサーバーが設定されている。
  • ファイアウォールによるフィルタリング
    DNSクエリが途中でフィルタリングされ、応答が返ってこない。
  • ネットワークの遅延/混雑
    DNSサーバーへのネットワーク経路が遅延しているか、混雑している。
  • DNSサーバーの応答が遅い/ダウンしている
    設定されているDNSサーバーのパフォーマンスが悪い、または一時的に利用できない。

トラブルシューティング

  • ファイアウォールの確認
    ファイアウォールがDNS応答をブロックしていないか確認してください。
  • タイムアウト値の調整
    Node.jsのdnsPromises.Resolverクラスを使用すると、クエリのタイムアウト値を調整できますが、これは根本的な解決策ではなく、DNSサーバーやネットワークの問題を隠蔽する可能性があります。しかし、一時的な対策としては有効です。
    const dns = require('dns');
    const resolver = new dns.promises.Resolver();
    resolver.setServers(['8.8.8.8']); // カスタムDNSサーバーを設定
    
    // デフォルトのタイムアウトは5秒 (5000ms)
    // resolver.setTimeout(10000); // 例: 10秒に設定 (ただし、このメソッドは存在しません)
    // dnsPromises.resolve()自体には直接タイムアウトを設定するオプションはありません。
    // setServers()で設定されたサーバーに対するリゾルバ全体のタイムアウトは内部的に管理されます。
    // 通常、OSのDNSリゾルバ設定に依存します。
    
    // より制御が必要な場合は、自前のタイムアウト実装を検討する必要があります。
    // 例えば、Promise.race() を使うなど。
    async function resolveWithTimeout(hostname, rrtype, timeoutMs) {
      const dnsPromise = dnsPromises.resolve(hostname, rrtype);
      const timeoutPromise = new Promise((_, reject) =>
        setTimeout(() => reject(new Error('DNS resolution timed out')), timeoutMs)
      );
      return Promise.race([dnsPromise, timeoutPromise]);
    }
    
    async function testTimeout() {
      try {
        const addresses = await resolveWithTimeout('slow-dns-host.com', 'A', 2000); // 2秒でタイムアウト
        console.log('解決成功:', addresses);
      } catch (error) {
        console.error('解決失敗:', error.message);
      }
    }
    testTimeout();
    
  • ネットワークの確認
    サーバーからDNSサーバーへのネットワーク接続が安定しているか確認してください。レイテンシが高い場合は、問題が解決するまで待つか、別のDNSサーバーを試す必要があります。
  • DNSサーバーの変更
    上記のENOTFOUNDと同様に、信頼性の高いPublic DNSに変更して試してみてください。

EREFUSED (Query refused by DNS server)

DNSサーバーがクエリを拒否した場合に発生します。

原因

  • 不正なクエリ
    クエリの形式が不正であるか、DNSサーバーが処理できないリソースレコードタイプを指定している。
  • アクセス制限
    DNSサーバーが、特定のIPアドレスからのクエリを拒否するように設定されている。
  • DNSサーバーが権限を持っていない
    指定されたDNSサーバーが、クエリされたドメインの解決権限を持っていない場合。

トラブルシューティング

  • リソースレコードタイプの確認
    指定しているrrtypeがそのホスト名でサポートされているか確認してください。例えば、ウェブサイトにMXレコードが存在しないのにMXレコードを要求すると、ENODATA(後述)ではなくEREFUSEDや他のエラーになることがあります。
  • DNSサーバーの設定確認
    自前のDNSサーバーを使用している場合、その設定が正しいか、クエリを許可しているか確認してください。
  • DNSサーバーの変更
    信頼性の高いPublic DNSに変更して試してください。これにより、現在のDNSサーバーがそのドメインに対して権限を持っていない場合に解決できる可能性があります。

ESERVFAIL (DNS server returned server failed)

DNSサーバーが内部エラーを報告した場合に発生します。サーバー自体が問題なく動作しているように見えても、特定のクエリに対して内部的な問題を抱えている可能性があります。

原因

  • サーバー負荷
    DNSサーバーが高負荷状態にある。
  • DNSサーバーの内部エラー
    DNSサーバーが一時的に不安定になっているか、内部でエラーが発生している。

トラブルシューティング

  • 別のDNSサーバー
    複数のDNSサーバーを設定している場合、別のサーバーにフォールバックされるのを待つか、明示的に別のサーバーを指定して試してください。
  • 時間を置いて再試行
    一時的なDNSサーバーの問題である可能性があるため、少し時間を置いてから再試行することで解決する場合があります。
  • DNSサーバーの変更
    信頼性の高いPublic DNSに変更して試してみてください。

ENODATA (No data record available for host)

ホスト名は解決できたが、指定されたリソースレコードタイプ(rrtype)に対応するデータが見つからなかった場合に発生します。これは、ENOTFOUNDとは異なり、ホスト自体は存在しているが、特定のレコードがないという状態です。

原因

  • 指定したレコードタイプがない
    ドメインにその種類のDNSレコードが存在しない(例: MXレコードがないドメインのMXレコードを要求)。
  • 要求するレコードタイプが正しいか確認
    意図しないレコードタイプを指定していないかコードを確認してください。
  • レコードタイプの確認
    本当にそのドメインにそのレコードタイプが存在するか確認してください。nslookupdigで確認できます。
    dig example.com MX // example.comにMXレコードが存在するか確認
    
  • UNHANDLED_PROMISE_REJECTION (Unhandled promise rejection)
    dnsPromises.resolve()が返したPromiseがrejectされたにもかかわらず、.catch()でエラーが捕捉されていない場合に発生します。これは、DNS解決エラーそのものではなく、非同期コードのエラーハンドリングの問題です。
    • トラブルシューティング
      awaitを使用している場合はtry...catchブロックで囲むか、.then().catch()を使用している場合は.catch()を必ず記述してください。
  • EINVAL (Invalid argument)
    dnsPromises.resolve()に無効な引数を渡した場合。例えば、ホスト名に無効な文字が含まれている場合など。
    • トラブルシューティング
      ホスト名やrrtypeの引数がNode.jsのドキュメントに沿っているか確認してください。
  • EPROTONOSUPPORT
    指定されたプロトコルがサポートされていない場合。これは通常、dnsPromises.resolve()自体ではあまり発生しませんが、DNSリゾルバの低レベルな設定で発生する可能性があります。
  • Node.jsのバージョン
    使用しているNode.jsのバージョンが古い場合、既知のバグが含まれている可能性があります。最新の安定版にアップデートすることを検討してください。
  • DNSキャッシュのクリア
    ローカルのDNSキャッシュが古い情報を保持している場合、問題が発生することがあります。OSのDNSキャッシュをクリアしてみてください(Linux: sudo systemctl restart systemd-resolved または sudo /etc/init.d/nscd restart、Windows: ipconfig /flushdns、macOS: sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder)。
  • DNSサーバーの監視
    頻繁にDNS解決エラーが発生する場合は、使用しているDNSサーバーが安定しているか、定期的に監視することを検討してください。
  • ネットワーク設定の確認
    サーバーのネットワークインターフェース、ゲートウェイ、DNS設定などを再確認してください。


dnsPromises.resolve()の基本

dnsPromises.resolve()を使用するには、まずdnsモジュールからpromisesプロパティをインポートする必要があります。

const dnsPromises = require('dns').promises;

これにより、dnsPromisesオブジェクトを通じてPromiseベースのDNS解決メソッドにアクセスできるようになります。

例1: Aレコード (IPv4アドレス) の取得

最も基本的な使用例で、指定したホスト名に対応するIPv4アドレス(Aレコード)を取得します。rrtypeを省略すると、デフォルトでAレコードが解決されます。

const dnsPromises = require('dns').promises;

async function resolveArecords(hostname) {
  try {
    const addresses = await dnsPromises.resolve(hostname); // rrtypeを省略すると'A'がデフォルト
    console.log(`--- ${hostname} のAレコード ---`);
    if (addresses.length > 0) {
      addresses.forEach(addr => console.log(`IPv4アドレス: ${addr}`));
    } else {
      console.log('Aレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`Aレコード解決エラー (${hostname}):`, error.message);
    if (error.code === 'ENOTFOUND') {
      console.error('ホスト名が見つからないか、存在しません。');
    } else if (error.code === 'ETIMEOUT') {
      console.error('DNSクエリがタイムアウトしました。');
    }
  }
}

resolveArecords('google.com');
resolveArecords('nodejs.org');
resolveArecords('nonexistent-domain-123456789.com'); // 存在しないドメイン

実行結果例

--- google.com のAレコード ---
IPv4アドレス: 142.250.199.142
IPv4アドレス: 142.250.199.110
// ... 他のIPアドレス ...

--- nodejs.org のAレコード ---
IPv4アドレス: 104.20.22.46
IPv4アドレス: 104.20.23.46

Aレコード解決エラー (nonexistent-domain-123456789.com): ENOTFOUND nonexistent-domain-123456789.com
ホスト名が見つからないか、存在しません。

例2: AAAAレコード (IPv6アドレス) の取得

IPv6アドレス(AAAAレコード)を取得するには、rrtype'AAAA'を指定します。

const dnsPromises = require('dns').promises;

async function resolveAAAArecords(hostname) {
  try {
    const addresses = await dnsPromises.resolve(hostname, 'AAAA');
    console.log(`--- ${hostname} のAAAAレコード ---`);
    if (addresses.length > 0) {
      addresses.forEach(addr => console.log(`IPv6アドレス: ${addr}`));
    } else {
      console.log('AAAAレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`AAAAレコード解決エラー (${hostname}):`, error.message);
    if (error.code === 'ENOTFOUND') {
      console.error('ホスト名が見つからないか、存在しません。');
    } else if (error.code === 'ENODATA') {
      console.error('ホスト名は存在するが、AAAAレコードが見つかりませんでした。');
    }
  }
}

resolveAAAArecords('google.com');
resolveAAAArecords('example.com'); // example.comにはAAAAレコードがない可能性が高い

実行結果例

--- google.com のAAAAレコード ---
IPv6アドレス: 2607:f8b0:4004:812::200e
// ... 他のIPアドレス ...

AAAAレコード解決エラー (example.com): ENODATA example.com
ホスト名は存在するが、AAAAレコードが見つかりませんでした。

例3: MXレコード (メール交換レコード) の取得

ドメインのメールサーバー情報を取得するには、rrtype'MX'を指定します。結果は、priorityexchangeプロパティを持つオブジェクトの配列として返されます。priorityは値が小さいほど優先度が高いことを示します。

const dnsPromises = require('dns').promises;

async function resolveMxRecords(domain) {
  try {
    const mxRecords = await dnsPromises.resolve(domain, 'MX');
    console.log(`--- ${domain} のMXレコード ---`);
    if (mxRecords.length > 0) {
      // 優先度でソートして表示
      mxRecords.sort((a, b) => a.priority - b.priority).forEach(record => {
        console.log(`優先度: ${record.priority}, 交換サーバー: ${record.exchange}`);
      });
    } else {
      console.log('MXレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`MXレコード解決エラー (${domain}):`, error.message);
    if (error.code === 'ENODATA') {
      console.error('ドメインは存在するが、MXレコードが見つかりませんでした。');
    }
  }
}

resolveMxRecords('gmail.com');
resolveMxRecords('nonexistent-domain-123456789.com'); // 存在しないドメイン
resolveMxRecords('example.com'); // MXレコードがない可能性のあるドメイン

実行結果例

--- gmail.com のMXレコード ---
優先度: 5, 交換サーバー: gmail-smtp-in.l.google.com
優先度: 10, 交換サーバー: alt1.gmail-smtp-in.l.google.com
// ... 他のMXレコード ...

MXレコード解決エラー (nonexistent-domain-123456789.com): ENOTFOUND nonexistent-domain-123456789.com
ホスト名が見つからないか、存在しません。

MXレコード解決エラー (example.com): ENODATA example.com
ドメインは存在するが、MXレコードが見つかりませんでした。

例4: NSレコード (ネームサーバーレコード) の取得

ドメインの権威DNSサーバーの情報を取得するには、rrtype'NS'を指定します。

const dnsPromises = require('dns').promises;

async function resolveNsRecords(domain) {
  try {
    const nsRecords = await dnsPromises.resolve(domain, 'NS');
    console.log(`--- ${domain} のNSレコード ---`);
    if (nsRecords.length > 0) {
      nsRecords.forEach(ns => console.log(`ネームサーバー: ${ns}`));
    } else {
      console.log('NSレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`NSレコード解決エラー (${domain}):`, error.message);
  }
}

resolveNsRecords('cloudflare.com');
resolveNsRecords('amazon.com');

実行結果例

--- cloudflare.com のNSレコード ---
ネームサーバー: pat.ns.cloudflare.com
ネームサーバー: lara.ns.cloudflare.com

--- amazon.com のNSレコード ---
ネームサーバー: ns1.p31.dynect.net
ネームサーバー: ns2.p31.dynect.net
// ... 他のNSレコード ...

例5: TXTレコード (テキストレコード) の取得

テキストデータ(SPFレコード、DKIMレコード、DMARCレコード、ドメイン認証など)を取得するには、rrtype'TXT'を指定します。

const dnsPromises = require('dns').promises;

async function resolveTxtRecords(domain) {
  try {
    const txtRecords = await dnsPromises.resolve(domain, 'TXT');
    console.log(`--- ${domain} のTXTレコード ---`);
    if (txtRecords.length > 0) {
      txtRecords.forEach((txtArray, index) => {
        // TXTレコードは文字列の配列として返されることがある
        console.log(`TXTレコード ${index + 1}: "${txtArray.join('')}"`);
      });
    } else {
      console.log('TXTレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`TXTレコード解決エラー (${domain}):`, error.message);
    if (error.code === 'ENODATA') {
      console.error('ドメインは存在するが、TXTレコードが見つかりませんでした。');
    }
  }
}

resolveTxtRecords('google.com'); // SPFレコードなどがある
resolveTxtRecords('microsoft.com');
resolveTxtRecords('example.com'); // TXTレコードがない可能性のあるドメイン

実行結果例

--- google.com のTXTレコード ---
TXTレコード 1: "v=spf1 include:_spf.google.com ~all"
TXTレコード 2: "facebook-domain-verification=22rm5gghj4b9ye355z700r05u3r0m20g"
// ... 他のTXTレコード ...

--- microsoft.com のTXTレコード ---
TXTレコード 1: "MS=ms12345678"
TXTレコード 2: "v=spf1 include:spf.protection.outlook.com -all"
// ...

TXTレコード解決エラー (example.com): ENODATA example.com
ドメインは存在するが、TXTレコードが見つかりませんでした。

例6: CNAMEレコード (正規名レコード) の取得

あるホスト名が別のホスト名のエイリアスである場合に、その正規名を取得するには'CNAME'を指定します。

const dnsPromises = require('dns').promises;

async function resolveCnameRecords(hostname) {
  try {
    const cnameRecords = await dnsPromises.resolve(hostname, 'CNAME');
    console.log(`--- ${hostname} のCNAMEレコード ---`);
    if (cnameRecords.length > 0) {
      cnameRecords.forEach(cname => console.log(`正規名: ${cname}`));
    } else {
      console.log('CNAMEレコードが見つかりませんでした。');
    }
  } catch (error) {
    console.error(`CNAMEレコード解決エラー (${hostname}):`, error.message);
    if (error.code === 'ENODATA') {
      console.error('ホスト名は存在するが、CNAMEレコードが見つかりませんでした。');
    }
  }
}

resolveCnameRecords('www.example.com'); // www.example.comは通常CNAME
resolveCnameRecords('ftp.mozilla.org'); // ftp.mozilla.orgもCNAMEである可能性が高い
resolveCnameRecords('google.com'); // google.com自体はCNAMEではないため、ENODATA

実行結果例

--- www.example.com のCNAMEレコード ---
正規名: example.com.
// ドメインの末尾のドットはFQDNを示します

--- ftp.mozilla.org のCNAMEレコード ---
正規名: ftp.mozilla.org.cdn.cloudflare.net.

CNAMEレコード解決エラー (google.com): ENODATA google.com
ホスト名は存在するが、CNAMEレコードが見つかりませんでした。

例7: dnsPromises.Resolver を使用したカスタムDNSサーバー設定

システムのデフォルトDNSサーバーではなく、特定のDNSサーバー(例えばGoogle Public DNSなど)を使ってDNS解決を行いたい場合は、dnsPromises.Resolverクラスのインスタンスを作成し、setServers()メソッドでサーバーを設定します。

const dnsPromises = require('dns').promises;

async function resolveWithCustomDns() {
  const resolver = new dnsPromises.Resolver();
  resolver.setServers(['8.8.8.8', '8.8.4.4']); // Google Public DNSを設定

  const hostname = 'example.com';
  console.log(`--- カスタムDNSサーバー (${resolver.getServers().join(', ')}) を使用して ${hostname} を解決 ---`);
  try {
    const addresses = await resolver.resolve(hostname, 'A');
    console.log('IPv4アドレス:', addresses);
  } catch (error) {
    console.error(`解決エラー (${hostname}):`, error.message);
  }

  // 別のホストをCloudflare DNSで解決
  const resolverCloudflare = new dnsPromises.Resolver();
  resolverCloudflare.setServers(['1.1.1.1', '1.0.0.1']); // Cloudflare DNSを設定

  const anotherHostname = 'github.com';
  console.log(`\n--- カスタムDNSサーバー (${resolverCloudflare.getServers().join(', ')}) を使用して ${anotherHostname} を解決 ---`);
  try {
    const addresses = await resolverCloudflare.resolve(anotherHostname, 'A');
    console.log('IPv4アドレス:', addresses);
  } catch (error) {
    console.error(`解決エラー (${anotherHostname}):`, error.message);
  }
}

resolveWithCustomDns();

実行結果例

--- カスタムDNSサーバー (8.8.8.8, 8.8.4.4) を使用して example.com を解決 ---
IPv4アドレス: 93.184.216.34

--- カスタムDNSサーバー (1.1.1.1, 1.0.0.1) を使用して github.com を解決 ---
IPv4アドレス: 140.82.113.3

rrtype'ANY'を指定すると、利用可能なすべてのレコードタイプを解決しようとします。しかし、これは非推奨であり、通常は特定のレコードタイプを指定する方が良いです。

const dnsPromises = require('dns').promises;

async function resolveAnyRecords(hostname) {
  try {
    console.log(`--- ${hostname} のANYレコード ---`);
    const records = await dnsPromises.resolve(hostname, 'ANY');
    records.forEach(record => {
      console.log(`タイプ: ${record.type}, データ:`, record.data);
    });
  } catch (error) {
    console.error(`ANYレコード解決エラー (${hostname}):`, error.message);
    if (error.code === 'NODATA') {
      console.error('ホストは存在するが、指定されたタイプのリソースレコードが見つかりませんでした。');
    }
  }
}

resolveAnyRecords('example.com');
// resolveAnyRecords('google.com'); // 大量のデータが出力される可能性があるので注意
--- example.com のANYレコード ---
タイプ: NS, データ: [ 'a.iana-servers.net', 'b.iana-servers.net' ]
タイプ: SOA, データ: {
  nsname: 'a.iana-servers.net',
  hostmaster: 'hostmaster.root-servers.org',
  serial: 2024010300,
  refresh: 3600,
  retry: 1800,
  expire: 604800,
  minttl: 86400
}
タイプ: A, データ: [ '93.184.216.34' ]


dns.resolve() (コールバックベース)

dnsPromises.resolve()の元になったメソッドで、Node.jsの初期から存在するコールバックベースのAPIです。Promiseではなく、コールバック関数を使用して結果を非同期に処理します。

特徴

  • エラーハンドリング
    コールバックの第一引数でエラーを、第二引数で結果を受け取る。
  • 同じDNS解決ロジック
    内部的にはdnsPromises.resolve()とほぼ同じDNS解決ロジックを使用する。
  • レガシーな非同期パターン
    コールバック地獄 (callback hell) に陥りやすく、モダンな非同期処理 (async/await) との相性が悪い。

使用場面

  • Promiseやasync/awaitの導入が難しい環境の場合。
  • 古いNode.jsコードベースとの互換性を保つ必要がある場合。


const dns = require('dns');

function resolveAWithCallback(hostname) {
  dns.resolve(hostname, 'A', (err, addresses) => {
    if (err) {
      console.error(`--- ${hostname} のAレコード解決エラー (コールバック):`, err.message);
      return;
    }
    console.log(`--- ${hostname} のAレコード (コールバック) ---`);
    if (addresses.length > 0) {
      addresses.forEach(addr => console.log(`IPv4アドレス: ${addr}`));
    } else {
      console.log('Aレコードが見つかりませんでした。');
    }
  });
}

resolveAWithCallback('google.com');
resolveAWithCallback('nonexistent-callback-domain.com');

dns.lookup()は、DNSだけでなく、hostsファイルやOSのキャッシュなど、システムの基盤となる名前解決メカニズム(getaddrinfo(3)のようなシステムコール)を使用してIPアドレスを取得します。これは、ホスト名から「接続可能な」IPアドレスを取得する際に適しています。

特徴

  • 結果の重複排除
    resolve()はDNSサーバーが返す全てのIPアドレスを返すのに対し、lookup()は重複を排除して返す場合がある。
  • リソースレコードタイプ指定不可
    resolve()のように、特定のMXレコードやTXTレコードなどのDNSレコードタイプを指定して取得することはできない。
  • 主にIPアドレス取得
    通常はIPアドレス(IPv4またはIPv6)を返す。
  • OSのメカニズムを使用
    hostsファイルやOSのDNSキャッシュ、設定されたDNSサーバーなど、OSが名前解決に使う全ての手段を考慮する。