Node.js ネットワークプログラミング: リモートポートの重要性 (tlsSocket)

2025-06-01

「tlsSocket.remotePort」は、TLS (Transport Layer Security) または SSL (Secure Sockets Layer) で保護された接続において、リモート側のポート番号を示すプロパティです。

具体的には、Node.js の tls.TLSSocket オブジェクトが確立したセキュアな接続の相手方、つまりクライアントまたはサーバーのアプリケーションが使用しているネットワークポートの番号を取得するために使われます。

イメージ

あなたが電話で誰かと話していると想像してください。「tlsSocket.remotePort」は、相手が電話をかけてきた、または相手が応答した電話回線の番号のようなものです。ネットワークの世界では、この「電話回線の番号」がポート番号に相当します。

  • この情報は、接続の相手方を特定したり、ログ記録などの目的で使用したりできます。
  • remotePort は読み取り専用のプロパティであり、値を変更することはできません。
  • tlsSocket は、TLS/SSL で暗号化されたネットワーク接続を表すオブジェクトです。

簡単なコード例

const tls = require('tls');
const server = tls.createServer({}, (tlsSocket) => {
  console.log(`クライアントが接続しました。リモートポート: ${tlsSocket.remotePort}`);

  tlsSocket.on('data', (data) => {
    console.log(`受信データ: ${data.toString()}`);
    tlsSocket.write('データを処理しました。\n');
  });

  tlsSocket.on('end', () => {
    console.log('クライアントが切断しました。');
  });
});

server.listen(8000, () => {
  console.log('TLS サーバーがポート 8000 で起動しました。');
});

// (クライアント側のコードは省略)

上記のサーバー側のコードでは、クライアントからの接続が確立されるたびに、tlsSocket.remotePort を使ってクライアントのポート番号をログに出力しています。



接続確立前のアクセス

  • エラー
    tlsSocket オブジェクトがまだ完全に接続を確立していない状態で tlsSocket.remotePort にアクセスしようとすると、undefined が返ってくることがあります。

誤ったタイミングでのログ出力

  • トラブルシューティング
    • ログ出力のタイミングを見直し、secureConnect イベントが発生した後など、接続が完全に確立してからポート番号を取得するようにしてください。
  • 状況
    接続処理の途中で誤って tlsSocket.remotePort をログ出力しようとして、期待するポート番号が表示されない。

ネットワークの問題による接続失敗

  • トラブルシューティング
    • 接続先のホスト名、ポート番号が正しいか確認してください。
    • ファイアウォールが接続をブロックしていないか確認してください。クライアント側とサーバー側の両方のファイアウォール設定を確認する必要があります。
    • ネットワーク接続が正常であるか (ping などで確認) を確認してください。
  • 状況
    ファイアウォールやネットワーク設定の問題により、TLS 接続自体が確立せず、結果的に tlsSocket オブジェクトが作成されなかったり、remotePort が利用できない。

サーバー側の設定ミス

  • トラブルシューティング
    • サーバー側の TLS 設定 (証明書、秘密鍵、ポート番号など) が正しいか確認してください。
    • サーバー側のログを確認し、エラーが発生していないか確認してください。
    • netstat や同様のツールを使用して、サーバーが指定されたポートでリッスンしているか確認してください。
  • 状況
    サーバー側で TLS が正しく設定されておらず、クライアントからの接続を受け付けられない。この場合、クライアント側では tlsSocket オブジェクトが作成されないか、エラーが発生し、結果的に remotePort にアクセスできない。

プロキシ環境

  • トラブルシューティング
    • プロキシ環境下での動作を考慮し、必要に応じてプロキシの設定を確認してください。最終的な宛先サーバーのポート番号が必要な場合は、プロキシサーバーとの通信方法やプロトコルに依存する可能性があります。
  • 状況
    クライアントがプロキシを経由して接続している場合、tlsSocket.remotePort がプロキシサーバーのポート番号を示すことがあります。

イベントリスナーの登録漏れ

  • トラブルシューティング
    • tlsSocket オブジェクトに対して、必要なイベントリスナー (connect, secureConnect, error, end, close, data など) が適切に登録されているか確認してください。
  • 状況
    secureConnect イベントなどの必要なイベントリスナーが登録されていないため、接続が確立したタイミングを検知できず、remotePort に適切なタイミングでアクセスできない。


例1: サーバー側で接続してきたクライアントのポート番号をログ出力する

この例では、TLS サーバーがクライアントからの接続を受け付けた際に、接続してきたクライアントのポート番号をコンソールに出力します。

const tls = require('tls');
const fs = require('fs');

// サーバーの証明書と秘密鍵
const options = {
  key: fs.readFileSync('server-key.pem'), // 秘密鍵のパス
  cert: fs.readFileSync('server-cert.pem'), // 証明書のパス
};

const server = tls.createServer(options, (tlsSocket) => {
  console.log(`クライアントが接続しました。リモートアドレス: ${tlsSocket.remoteAddress}, リモートポート: ${tlsSocket.remotePort}`);

  tlsSocket.on('data', (data) => {
    console.log(`受信データ: ${data.toString()}`);
    tlsSocket.write('データを処理しました。\n');
  });

  tlsSocket.on('end', () => {
    console.log('クライアントが切断しました。');
  });
});

const port = 8000;
server.listen(port, () => {
  console.log(`TLS サーバーがポート ${port} で起動しました。`);
});

このコードでは、tls.createServer のコールバック関数内で、接続された tlsSocket オブジェクトの remotePort プロパティにアクセスして、クライアントのポート番号を取得し、ログに出力しています。

例2: クライアント側で接続確立後にサーバーのポート番号を確認する

この例では、TLS クライアントがサーバーに接続した後、確立された接続のサーバー側のポート番号をコンソールに出力します。

const tls = require('tls');

const options = {
  host: 'localhost', // 接続先のホスト名または IP アドレス
  port: 8000,        // 接続先のポート番号
  rejectUnauthorized: false, // 自己署名証明書の場合に必要 (本番環境では推奨されません)
};

const client = tls.connect(options, () => {
  console.log('サーバーに接続しました。');
  console.log(`サーバーのポート: ${client.remotePort}`);

  client.write('こんにちは、サーバー!\n');
});

client.on('data', (data) => {
  console.log(`受信データ: ${data.toString()}`);
  client.end();
});

client.on('end', () => {
  console.log('サーバーとの接続を閉じました。');
});

client.on('error', (err) => {
  console.error(`エラーが発生しました: ${err.message}`);
});

ここでは、tls.connect のコールバック関数内で、接続された client (これは TLSSocket のインスタンスです) オブジェクトの remotePort を使用して、接続先のサーバーのポート番号を取得しています。

例3: 複数のクライアント接続を処理し、それぞれのポート番号を記録するサーバー

この例では、サーバーが複数のクライアントからの接続を受け付け、それぞれのクライアントのポート番号をログに記録します。

const tls = require('tls');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),
};

const server = tls.createServer(options, (tlsSocket) => {
  const clientAddress = `${tlsSocket.remoteAddress}:${tlsSocket.remotePort}`;
  console.log(`クライアント (${clientAddress}) が接続しました。`);

  tlsSocket.on('data', (data) => {
    console.log(`(${clientAddress}) 受信データ: ${data.toString()}`);
    tlsSocket.write(`(${clientAddress}) データを処理しました。\n`);
  });

  tlsSocket.on('end', () => {
    console.log(`(${clientAddress}) が切断しました。`);
  });
});

const port = 8000;
server.listen(port, () => {
  console.log(`TLS サーバーがポート ${port} で起動しました。`);
});

この例では、接続ごとにクライアントの IP アドレス (remoteAddress) とポート番号 (remotePort) を組み合わせてクライアントを一意に識別し、ログ出力に利用しています。