【Node.js】dns.setDefaultResultOrderでよくあるエラーと解決策

2025-05-16

どのような働きをするのか?

通常、DNSルックアップを行うと、IPv4アドレスとIPv6アドレスの両方が返される可能性があります。dns.setDefaultResultOrder()を使用すると、これらのアドレスが返される順序を制御できます。

この関数には、以下の3つの引数を指定できます。

  • 'verbatim': DNSサーバーから返された順序をそのまま保持します。Node.js 17以前のデフォルトの挙動であり、現在(Node.js 17以降)のデフォルトもこれです。以前のバージョンでは、'verbatim'でない場合は、IPv4とIPv6のアドレスが再編成されることがありました。
  • 'ipv6first': IPv6アドレスがIPv4アドレスよりも優先して返されるように設定します。
  • 'ipv4first': IPv4アドレスがIPv6アドレスよりも優先して返されるように設定します。つまり、最初にIPv4アドレスがリストされ、その後IPv6アドレスが続きます。

なぜこれが重要なのか?

特定のネットワーク環境やアプリケーションの要件によっては、IPv4またはIPv6のどちらかを優先したい場合があります。例えば、以下のようなケースで役立ちます。

  • パフォーマンスの最適化: 特定の状況では、IPv4またはIPv6のどちらかの方がパフォーマンスが良い場合があり、それを優先するように設定できます。
  • レガシーシステムとの互換性: 特定の古いシステムがIPv6をうまく扱えない場合に、IPv4を優先するように設定することで、互換性の問題を解決できることがあります。
  • IPv4環境への対応: アプリケーションがIPv4ネットワークでしか動作しない場合や、IPv4での接続を優先したい場合に'ipv4first'を設定することで、意図しないIPv6接続の試みを避けることができます。
const dns = require('dns');

// IPv4アドレスを優先するように設定
dns.setDefaultResultOrder('ipv4first');

// 例えば、'example.com'のIPアドレスをルックアップ
dns.lookup('example.com', (err, address, family) => {
  if (err) throw err;
  console.log(`アドレス: ${address}, ファミリー: ${family}`);
});

// デフォルト(verbatim)に戻す
// dns.setDefaultResultOrder('verbatim');
  • Worker Threadsを使用している場合、メインスレッドでsetDefaultResultOrder()を設定しても、Worker内でのDNS順序には影響しません。Worker内で個別に設定する必要があります。
  • --dns-result-orderというコマンドライン引数でも同様の設定が可能ですが、dns.setDefaultResultOrder()は、実行時にプログラム内で動的に設定できるため、より柔軟性があります。setDefaultResultOrderはコマンドライン引数よりも優先されます。
  • この設定は、dns.lookup()dnsPromises.lookup()など、Node.jsのDNSモジュールが内部的に使用するIPアドレスの順序に影響を与えます。


ECONNREFUSED または接続タイムアウト

最も一般的な問題の一つです。特にNode.js 17以降で、'ipv4first'を設定せずにlocalhostに接続しようとすると発生しやすいです。

原因

  • もし、ターゲットとなるサーバーがIPv4アドレス(127.0.0.1)でのみリッスンしている場合、アプリケーションが最初にIPv6アドレスでの接続を試み、その結果ECONNREFUSED(接続拒否)やタイムアウトが発生します。
  • Node.js 17以降のデフォルトの挙動では、DNSルックアップの結果を'verbatim'(OSから返された順序)で返します。多くのOSでは、localhostに対してIPv6アドレス(::1)がIPv4アドレス(127.0.0.1)よりも先に解決されます。

トラブルシューティング

  • サーバーがIPv6をリッスンしているか確認する
    サーバーがIPv6アドレスでもリッスンするように設定されているか確認してください。例えば、Express.jsなどではデフォルトで両方をリッスンすることが多いですが、環境によってはIPv4のみに制限されている場合があります。
  • localhostの代わりに127.0.0.1を直接使用する
    確実なIPv4接続が必要な場合、localhostの代わりに明示的に127.0.0.1を使用します。これは特に開発環境で有効なワークアラウンドです。
    // 'localhost' の代わりに '127.0.0.1' を使用
    http.get('http://127.0.0.1:3000', (res) => {
      // ...
    });
    
  • dns.setDefaultResultOrder('ipv4first')を設定する
    アプリケーションのエントリーポイント(一番最初に実行されるファイル)の早い段階でこの設定を行うことで、IPv4アドレスが優先的に使用されるようになります。
    const dns = require('dns');
    dns.setDefaultResultOrder('ipv4first');
    
    // その後のDNSルックアップやHTTPリクエストなどに影響します
    

設定が反映されない、または予期せぬDNS解決順序

setDefaultResultOrder()を設定したにもかかわらず、期待通りのDNS解決順序にならない場合があります。

原因

  • 特定のDNSモジュールやライブラリの使用
    一部のサードパーティ製DNSモジュールや、Node.jsの標準dnsモジュールとは異なる低レベルのAPIを使用しているライブラリは、setDefaultResultOrder()の設定を無視する可能性があります。
  • --dns-result-orderコマンドライン引数との競合
    Node.jsの起動時に--dns-result-orderコマンドライン引数で設定することも可能ですが、dns.setDefaultResultOrder()このコマンドライン引数よりも優先されます。もしコマンドライン引数とコード内の設定が矛盾している場合、コード内の設定が優先されます。
  • Worker Threadsを使用している場合
    メインスレッドでsetDefaultResultOrder()を設定しても、Worker Threads内で実行されるDNSルックアップには影響しません。各Workerスレッド内で個別に設定する必要があります。
  • 設定のタイミングが遅い
    setDefaultResultOrder()は、DNSルックアップが行われる前に設定される必要があります。アプリケーションの初期化段階で設定しないと、既に実行されたDNSルックアップには影響しません。

トラブルシューティング

  • テスト環境での確認
    開発環境やテスト環境で、実際にDNSルックアップの結果が期待通りになっているかを確認するコードを追加してください。例えば、dns.lookup('example.com', { all: true }, (err, addresses) => console.log(addresses));のようにall: trueオプションを使用すると、解決されたすべてのアドレスとそのファミリーを確認できます。
  • Worker Threads内の設定
    Worker Threadsを使用している場合は、Workerスクリプトの冒頭でもdns.setDefaultResultOrder()を設定してください。
  • 設定場所の確認
    アプリケーションのエントリーポイントの冒頭で設定されていることを確認してください。

DNSルックアップの順序を強制することで、特定のネットワーク環境下でパフォーマンスが低下する可能性があります。

原因

  • 優先するプロトコルが利用できない、または遅い場合
    例えば、'ipv6first'を設定したものの、IPv6接続が不安定だったり、利用できない場合、フォールバックまで時間がかかり全体の遅延につながることがあります。
  • Happy Eyeballsの欠如
    Node.jsはHappy Eyeballsアルゴリズム(IPv4とIPv6の両方を同時に試行し、先に成功した方を使用する)を標準では実装していません。setDefaultResultOrder()で一方を強制すると、もう一方のプロトコルが利用可能であっても、常に優先された方から試行するため、特定の環境で遅延が発生する可能性があります。
  • DNSキャッシュの影響
    Node.js自体はDNSキャッシュを行いませんが、OSレベルのDNSキャッシュが影響する場合があります。DNSキャッシュをクリアすることで、問題が解決することもあります。
  • ネットワーク環境の診断
    ping -4ping -6コマンドを使用して、特定のホストに対するIPv4とIPv6の接続性や応答時間をテストし、どちらのプロトコルがより高速か、または利用可能かを確認します。
  • 'verbatim'に戻すことを検討する
    多くのケースでは、OSが最適なDNS結果順序を決定するため、'verbatim'(Node.js 17以降のデフォルト)が最もバランスの取れた選択肢です。特定の問題がない限り、この設定を維持することをお勧めします。


例1: 基本的な使い方とデフォルトの挙動(Node.js 17以降)

Node.js 17以降では、dns.setDefaultResultOrder()を呼び出さない場合、または'verbatim'を設定した場合のデフォルトの挙動は、OSが返すDNS結果の順序をそのまま使用します。多くのシステムでは、localhostに対してはIPv6アドレスがIPv4アドレスよりも先に返される傾向があります。

// example1.js
const dns = require('dns');
const http = require('http');

console.log('--- 例1: デフォルトの挙動 (Node.js 17以降のverbatim) ---');

// デフォルトの挙動は 'verbatim' ですが、明示的に設定することもできます
// dns.setDefaultResultOrder('verbatim'); // これをコメントアウトしても結果は同じになることが多い

// 'localhost' のIPアドレスをルックアップ
dns.lookup('localhost', { all: true }, (err, addresses) => {
    if (err) {
        console.error('DNS lookup error:', err.message);
        return;
    }
    console.log('localhostのDNSルックアップ結果 (all: true):', addresses);
    // 多くの環境で [{ address: '::1', family: 6 }, { address: '127.0.0.1', family: 4 }] のような順序になります
});

// 'localhost' にHTTPリクエストを試みる
// このリクエストは、OSが先に返すIPアドレス(多くの場合IPv6: ::1)を最初に試みます。
// もしサーバーがIPv6でリッスンしていない場合、接続エラーになる可能性があります。
const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from server!\n');
});

server.listen(0, () => { // 0番ポートを指定すると空いているポートを自動的に割り当てる
    const port = server.address().port;
    console.log(`サーバーはポート ${port} でリッスン中...`);

    // サーバーが準備できた後にリクエストを送信
    setTimeout(() => {
        http.get(`http://localhost:${port}`, (res) => {
            console.log(`HTTPリクエスト (localhost:${port}) ステータス: ${res.statusCode}`);
            res.on('data', (chunk) => process.stdout.write(chunk));
            res.on('end', () => {
                server.close(() => console.log('サーバー停止'));
            });
        }).on('error', (e) => {
            console.error(`HTTPリクエスト (localhost:${port}) エラー:`, e.message);
            server.close(() => console.log('サーバー停止 (エラーにより)'));
        });
    }, 100); // サーバー起動を待つ
});

実行結果の例

--- 例1: デフォルトの挙動 (Node.js 17以降のverbatim) ---
localhostのDNSルックアップ結果 (all: true): [ { address: '::1', family: 6 }, { address: '127.0.0.1', family: 4 } ]
サーバーはポート 52123 でリッスン中...
HTTPリクエスト (localhost:52123) ステータス: 200
Hello from server!
サーバー停止

解説
この例では、サーバーはIPv6とIPv4の両方でリッスンしているため、localhostに対するHTTPリクエストは成功します。しかし、もしサーバーがIPv6に対応していない場合(例: server.listen('127.0.0.1', port)のようにIPv4アドレスを明示的に指定した場合)、このリクエストはエラーになる可能性があります。

例2: ipv4first の設定

IPv4アドレスをIPv6アドレスよりも優先させたい場合に非常に役立ちます。特に、IPv4のみに対応しているレガシーシステムや、特定のクラウド環境でIPv4を優先したい場合に有用です。

// example2.js
const dns = require('dns');
const http = require('http');

console.log('\n--- 例2: IPv4を優先 (dns.setDefaultResultOrder(\'ipv4first\')) ---');

// IPv4アドレスを優先するように設定
dns.setDefaultResultOrder('ipv4first');

// 'localhost' のIPアドレスをルックアップ
dns.lookup('localhost', { all: true }, (err, addresses) => {
    if (err) {
        console.error('DNS lookup error:', err.message);
        return;
    }
    console.log('localhostのDNSルックアップ結果 (all: true):', addresses);
    // これにより、[{ address: '127.0.0.1', family: 4 }, { address: '::1', family: 6 }] のような順序になります
});

// 'localhost' にHTTPリクエストを試みる
// このリクエストは、IPv4アドレス (127.0.0.1) を最初に試みます。
const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from server!\n');
});

server.listen(0, () => {
    const port = server.address().port;
    console.log(`サーバーはポート ${port} でリッスン中...`);

    setTimeout(() => {
        http.get(`http://localhost:${port}`, (res) => {
            console.log(`HTTPリクエスト (localhost:${port}) ステータス: ${res.statusCode}`);
            res.on('data', (chunk) => process.stdout.write(chunk));
            res.on('end', () => {
                server.close(() => console.log('サーバー停止'));
            });
        }).on('error', (e) => {
            console.error(`HTTPリクエスト (localhost:${port}) エラー:`, e.message);
            server.close(() => console.log('サーバー停止 (エラーにより)'));
        });
    }, 100);
});

実行結果の例

--- 例2: IPv4を優先 (dns.setDefaultResultOrder('ipv4first')) ---
localhostのDNSルックアップ結果 (all: true): [ { address: '127.0.0.1', family: 4 }, { address: '::1', family: 6 } ]
サーバーはポート 52124 でリッスン中...
HTTPリクエスト (localhost:52124) ステータス: 200
Hello from server!
サーバー停止

解説
dns.setDefaultResultOrder('ipv4first')を設定することで、dns.lookup()の結果の順序が変わり、HTTPリクエストもIPv4アドレスから試行されるようになります。これにより、特にIPv4しか対応していないサーバーとの接続問題が解消されることが多いです。

例3: ipv6first の設定

IPv6を積極的に利用したい場合や、IPv6のみが利用可能な環境で動作させる場合に有用です。

// example3.js
const dns = require('dns');
const http = require('http');

console.log('\n--- 例3: IPv6を優先 (dns.setDefaultResultOrder(\'ipv6first\')) ---');

// IPv6アドレスを優先するように設定
dns.setDefaultResultOrder('ipv6first');

// 'localhost' のIPアドレスをルックアップ
dns.lookup('localhost', { all: true }, (err, addresses) => {
    if (err) {
        console.error('DNS lookup error:', err.message);
        return;
    }
    console.log('localhostのDNSルックアップ結果 (all: true):', addresses);
    // これにより、[{ address: '::1', family: 6 }, { address: '127.0.0.1', family: 4 }] のような順序になります
});

// 'localhost' にHTTPリクエストを試みる
// このリクエストは、IPv6アドレス (::1) を最初に試みます。
const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from server!\n');
});

server.listen(0, () => {
    const port = server.address().port;
    console.log(`サーバーはポート ${port} でリッスン中...`);

    setTimeout(() => {
        http.get(`http://localhost:${port}`, (res) => {
            console.log(`HTTPリクエスト (localhost:${port}) ステータス: ${res.statusCode}`);
            res.on('data', (chunk) => process.stdout.write(chunk));
            res.on('end', () => {
                server.close(() => console.log('サーバー停止'));
            });
        }).on('error', (e) => {
            console.error(`HTTPリクエスト (localhost:${port}) エラー:`, e.message);
            server.close(() => console.log('サーバー停止 (エラーにより)'));
        });
    }, 100);
});

実行結果の例

--- 例3: IPv6を優先 (dns.setDefaultResultOrder('ipv6first')) ---
localhostのDNSルックアップ結果 (all: true): [ { address: '::1', family: 6 }, { address: '127.0.0.1', family: 4 } ]
サーバーはポート 52125 でリッスン中...
HTTPリクエスト (localhost:52125) ステータス: 200
Hello from server!
サーバー停止

解説
'ipv6first'を設定すると、IPv6アドレスが優先されます。これは、IPv6ネットワークでのみ動作するサービスや、IPv6が推奨される環境で役立ちます。

Worker Threadsを使用する場合、dns.setDefaultResultOrder()はメインスレッドの設定を継承しません。各Workerスレッド内で個別に設定する必要があります。

// main.js
const { Worker } = require('worker_threads');
const dns = require('dns');

console.log('--- 例4: Worker Threads との連携 ---');

// メインスレッドでIPv4を優先設定
dns.setDefaultResultOrder('ipv4first');
console.log('メインスレッド: dns.setDefaultResultOrder(\'ipv4first\')を設定しました');

// メインスレッドからlocalhostをルックアップ (IPv4が優先されるはず)
dns.lookup('localhost', { all: true }, (err, addresses) => {
    if (err) throw err;
    console.log('メインスレッドでのlocalhostルックアップ:', addresses);
});

// Workerを起動
const worker = new Worker('./worker.js');

worker.on('message', (msg) => {
    console.log(`メインスレッドからWorkerからのメッセージ: ${msg}`);
});

worker.on('error', (err) => {
    console.error('Workerエラー:', err);
});

worker.on('exit', (code) => {
    if (code !== 0)
        console.error(`Workerがコード ${code} で停止しました`);
});

// worker.js
const { parentPort } = require('worker_threads');
const dns = require('dns');

// Workerスレッドではデフォルトの挙動を期待(verbatim)
// ここでは特に dns.setDefaultResultOrder() を設定しません。
// もしWorker内でもIPv4を優先したければ、ここで再度設定する必要があります。
// dns.setDefaultResultOrder('ipv4first');

console.log('Workerスレッド: DNSルックアップを開始します');

// Workerスレッドからlocalhostをルックアップ (デフォルトの順序になるはず)
dns.lookup('localhost', { all: true }, (err, addresses) => {
    if (err) {
        parentPort.postMessage(`Worker: DNS lookup error: ${err.message}`);
        return;
    }
    parentPort.postMessage(`Workerスレッドでのlocalhostルックアップ: ${JSON.stringify(addresses)}`);
});

実行結果の例

--- 例4: Worker Threads との連携 ---
メインスレッド: dns.setDefaultResultOrder('ipv4first')を設定しました
メインスレッドでのlocalhostルックアップ: [ { address: '127.0.0.1', family: 4 }, { address: '::1', family: 6 } ]
Workerスレッド: DNSルックアップを開始します
メインスレッドからWorkerからのメッセージ: Workerスレッドでのlocalhostルックアップ: [{"address":"::1","family":6},{"address":"127.0.0.1","family":4}]

解説
メインスレッドで'ipv4first'を設定しても、Workerスレッドではその設定は引き継がれていません。Workerスレッド内のDNSルックアップは、Worker自身のデフォルトの挙動(多くの環境で'verbatim'によりIPv6が先に)に従っています。Workerスレッドで特定の順序が必要な場合は、Workerスクリプト内で明示的にdns.setDefaultResultOrder()を呼び出す必要があります。



以下に、dns.setDefaultResultOrder()の代替となるプログラミング方法をいくつか説明します。

dns.lookup()のfamilyオプションを使用する

これは、dns.setDefaultResultOrder()の最も直接的な代替方法であり、特定のDNSルックアップに対してのみ、IPv4またはIPv6のいずれかを強制的に指定したい場合に非常に効果的です。

  • family: 0: IPv4とIPv6の両方を試行し、最初に見つかったものを返します(デフォルトの挙動)。
  • family: 6: IPv6アドレスのみを解決します。
  • family: 4: IPv4アドレスのみを解決します。

利点

  • 不要なプロトコルを試行しないため、場合によってはパフォーマンスが向上する可能性がある。
  • グローバルな設定を変更せずに、特定のルックアップの動作を制御できる。

欠点

  • http.request()net.connect()などの高レベルAPIでは、直接familyオプションを指定できない場合がある(内部でdns.lookup()が使用されるため、影響を受けることはある)。
  • すべてのdns.lookup()呼び出しで明示的に指定する必要があるため、コードが冗長になる可能性がある。

コード例

const dns = require('dns');

console.log('--- familyオプションを使用したDNSルックアップ ---');

// IPv4アドレスのみを要求
dns.lookup('google.com', { family: 4 }, (err, address, family) => {
    if (err) {
        console.error('IPv4 lookup error:', err.message);
        return;
    }
    console.log(`Google (IPv4): ${address} (Family: ${family})`); // 例: 142.250.199.14 (Family: 4)
});

// IPv6アドレスのみを要求
dns.lookup('google.com', { family: 6 }, (err, address, family) => {
    if (err) {
        console.error('IPv6 lookup error:', err.message);
        return;
    }
    console.log(`Google (IPv6): ${address} (Family: ${family})`); // 例: 2a00:1450:4001:820::200e (Family: 6)
});

// localhostに対してIPv4のみを要求 (ECONNREFUSED回避策として有効)
dns.lookup('localhost', { family: 4 }, (err, address, family) => {
    if (err) {
        console.error('localhost IPv4 lookup error:', err.message);
        return;
    }
    console.log(`localhost (IPv4): ${address} (Family: ${family})`); // 127.0.0.1 (Family: 4)
});

コマンドライン引数 --dns-result-order を使用する

Node.jsアプリケーションの起動時に、コマンドライン引数としてDNS解決の順序を指定できます。これは、アプリケーションコードを変更することなく、デプロイ環境でDNSの挙動を調整したい場合に便利です。

  • --dns-result-order=verbatim (Node.js 17以降のデフォルト)
  • --dns-result-order=ipv6first
  • --dns-result-order=ipv4first

利点

  • 環境変数やデプロイスクリプトで簡単に制御できる。
  • アプリケーションコードを変更する必要がない。

欠点

  • dns.setDefaultResultOrder()がコード内で呼び出された場合、そちらの設定が優先される。
  • 実行時に動的に変更できない。

使用例

# IPv4を優先してNode.jsアプリケーションを実行
node --dns-result-order=ipv4first your_app.js

# IPv6を優先してNode.jsアプリケーションを実行
node --dns-result-order=ipv6first your_app.js

http.request()やnet.connect()でIPアドレスを直接指定する

ホスト名ではなく、解決済みのIPアドレスを直接http.request()net.connect()に渡すことで、DNSルックアッププロセスを完全にバイパスできます。これは、IPアドレスが事前にわかっている場合や、独自のDNS解決ロジック(例: カスタムキャッシュ、サービスディスカバリ)を使用している場合に有用です。

利点

  • 特定のネットワークインターフェースや経路を選択できる。
  • どのIPアドレスに接続するかを完全に制御できる。
  • DNSルックアップのオーバーヘッドをなくすことができる(DNSキャッシュが有効な場合を除く)。

欠点

  • IPアドレスの変更に対応しにくい。
  • ドメイン名解決の柔軟性が失われる。
  • 事前にIPアドレスを知っている必要がある。

コード例

const http = require('http');

console.log('--- IPアドレスを直接指定したHTTPリクエスト ---');

// GoogleのIPv4アドレスを直接指定
const ipv4Address = '142.250.199.14'; // 例: google.comのIPv4アドレス
http.get(`http://${ipv4Address}`, (res) => {
    console.log(`HTTPリクエスト (IPv4直接指定) ステータス: ${res.statusCode}`);
    res.on('data', () => {}); // データを消費
    res.on('end', () => console.log('IPv4直接指定リクエスト完了'));
}).on('error', (e) => {
    console.error(`HTTPリクエスト (IPv4直接指定) エラー:`, e.message);
});

// localhostのIPv4アドレスを直接指定 (ECONNREFUSED回避策として特に有効)
const localhostIpv4 = '127.0.0.1';
const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from server on IPv4 only!\n');
});

server.listen(0, localhostIpv4, () => { // IPv4アドレスにのみリッスン
    const port = server.address().port;
    console.log(`サーバーは ${localhostIpv4}:${port} でリッスン中...`);

    setTimeout(() => {
        http.get(`http://${localhostIpv4}:${port}`, (res) => {
            console.log(`HTTPリクエスト (localhost IPv4直接指定) ステータス: ${res.statusCode}`);
            res.on('data', (chunk) => process.stdout.write(chunk));
            res.on('end', () => {
                server.close(() => console.log('サーバー停止'));
            });
        }).on('error', (e) => {
            console.error(`HTTPリクエスト (localhost IPv4直接指定) エラー:`, e.message);
            server.close(() => console.log('サーバー停止 (エラーにより)'));
        });
    }, 100);
});

lookupオプションをカスタマイズする (上級者向け)

http.Agentなどの一部のNode.jsのモジュールでは、カスタムのlookup関数を指定できます。これにより、DNS解決のロジックを完全に制御できます。例えば、独自のキャッシュメカニズムを実装したり、外部のサービスディスカバリシステム(Consul, ZooKeeperなど)と連携させたりすることが可能です。

利点

  • 独自のキャッシュ、フォールバック、サービスディスカバリロジックを統合できる。
  • DNS解決プロセスを完全にカスタマイズできる。

欠点

  • dnsモジュールのデフォルトの挙動を完全に置き換えるため、慎重なテストが必要。
  • 実装が複雑になる。
const http = require('http');
const dns = require('dns');

// カスタムのlookup関数を定義
function customLookup(hostname, options, callback) {
    console.log(`カスタムlookupが呼ばれました: ${hostname}`);
    // ここで独自のロジックを実装
    // 例: キャッシュをチェック、特定のIPアドレスを返す、
    // または元のdns.lookup()を呼び出す
    if (hostname === 'mycustomservice.internal') {
        // 特定のホスト名に対して固定のIPを返す
        process.nextTick(() => callback(null, '192.168.1.100', 4));
    } else {
        // それ以外はデフォルトのdns.lookup()を使用
        dns.lookup(hostname, options, callback);
    }
}

// HTTP Agentを作成し、カスタムlookupを割り当てる
const customAgent = new http.Agent({
    lookup: customLookup,
    keepAlive: true,
});

// カスタムAgentを使用してHTTPリクエストを送信
console.log('\n--- カスタムAgentを使用したHTTPリクエスト ---');
http.get({
    hostname: 'mycustomservice.internal',
    port: 80,
    path: '/',
    agent: customAgent, // カスタムAgentを使用
}, (res) => {
    console.log(`カスタムAgentリクエスト ステータス: ${res.statusCode}`);
    res.on('data', () => {});
    res.on('end', () => console.log('カスタムAgentリクエスト完了'));
}).on('error', (e) => {
    console.error(`カスタムAgentリクエスト エラー:`, e.message);
});

// 通常のホスト名へのリクエストもカスタムlookup経由
http.get({
    hostname: 'example.com',
    port: 80,
    path: '/',
    agent: customAgent,
}, (res) => {
    console.log(`example.comリクエスト ステータス: ${res.statusCode}`);
    res.on('data', () => {});
    res.on('end', () => console.log('example.comリクエスト完了'));
}).on('error', (e) => {
    console.error(`example.comリクエスト エラー:`, e.message);
});
  • 独自の高度なDNS解決ロジックを実装したい
    lookupオプションのカスタマイズ。非常に特殊な要件がある場合にのみ検討。
  • DNS解決プロセスを完全にバイパスしたい
    IPアドレスを直接指定。特に、特定のサービスや開発環境で有用。
  • アプリケーション全体に影響させたいがコード修正を避けたい
    --dns-result-orderコマンドライン引数。
  • 最も手軽で局所的な制御
    dns.lookup()familyオプション。特定の箇所でIPv4/IPv6を強制したい場合に最適。