Express.jsでreq.ipが::ffff:127.0.0.1を返す理由と解決策
Express.jsにおける req.ip が ::ffff:127.0.0.1 を返す理由と解決策
Express.js で req.ip
を使用すると、場合によっては ::ffff:127.0.0.1
という値が返されることがあります。これは、IPv6 アドレス表記における IPv4 アドレス表現であるためです。この現象自体は問題ありませんが、IPv4 アドレスとして処理したい場合は、適切な処理を行う必要があります。
原因
IPv6 アドレスは 128 ビットの長さを持っていますが、IPv4 アドレスは 32 ビットの長さです。IPv6 アドレスの中で、最初の 64 ビットが ::ffff
である場合、残りの 64 ビットは IPv4 アドレスを表します。::ffff:127.0.0.1
は、この形式で表現された IPv4 アドレス 127.0.0.1
(localhost) を表します。
解決策
req.ip
に含まれる ::ffff
プレフィックスを削除することで、IPv4 アドレスとして処理することができます。以下に、その方法をいくつか紹介します。
方法 1: 正規表現を使用する
const ip = req.ip;
const ipv4Address = ip.replace(/^::ffff:/, '');
console.log(ipv4Address); // 127.0.0.1
方法 2: ipaddr.js モジュールを使用する
const ipaddr = require('ipaddr.js');
const ip = req.ip;
const address = ipaddr.process(ip);
const ipv4Address = address.getOctetString();
console.log(ipv4Address); // 127.0.0.1
const os = require('os');
const interfaces = os.networkInterfaces();
const ipv4Address = findIPv4Address(interfaces);
console.log(ipv4Address); // 127.0.0.1
function findIPv4Address(interfaces) {
for (const name in interfaces) {
const iface = interfaces[name];
for (const address of iface) {
if (address.family === 'IPv4' && !address.internal) {
return address.address;
}
}
}
return null;
}
注意点
上記の方法で取得した IPv4 アドレスは、あくまでもその時点での有効なアドレスであることに注意してください。ネットワーク環境によっては、異なるアドレスが割り当てられる場合があります。
req.headers['x-forwarded-for']
ヘッダーを使用すると、プロキシサーバーを経由したリクエストの場合でも、元のクライアントの IP アドレスを取得することができます。express-ip
やexpress-request-ip
などのサードパーティ製ミドルウェアを使用すると、req.ip
により詳細な IP アドレス情報 (例: サブネットマスク) を取得することができます。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
const ip = req.ip;
const ipv4Address = ip.replace(/^::ffff:/, '');
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
const express = require('express');
const ipaddr = require('ipaddr.js');
const app = express();
app.get('/', (req, res) => {
const ip = req.ip;
const address = ipaddr.process(ip);
const ipv4Address = address.getOctetString();
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
const express = require('express');
const os = require('os');
const app = express();
app.get('/', (req, res) => {
const ipv4Address = findIPv4Address(os.networkInterfaces());
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
function findIPv4Address(interfaces) {
for (const name in interfaces) {
const iface = interfaces[name];
for (const address of iface) {
if (address.family === 'IPv4' && !address.internal) {
return address.address;
}
}
}
return null;
}
説明
上記のコードは、以下の処理を行います。
- Express アプリケーションを作成します。
/
パスに対して GET リクエストを処理するルートハンドラーを定義します。- リクエストオブジェクト (
req
) からip
プロパティを取得します。 - 選択した方法 (正規表現、
ipaddr.js
モジュール、os
モジュール) を使用して、::ffff
プレフィックスを削除し、IPv4 アドレスを取得します。 - 取得した IPv4 アドレスをコンソールにログ出力します。
- クライアントに "Hello from Express!" というメッセージを送信します。
- アプリケーションをポート 3000 で起動します。
実行方法
上記コードを実行するには、以下の手順を実行します。
- Node.js と Express.js をインストールします。
- コードを保存します。
- 以下のコマンドを実行して、コードを実行します。
node index.js
- ブラウザで
http://localhost:3000
にアクセスします。
補足
- 上記のコードはあくまで一例であり、状況に応じて変更する必要があります。
req.ip
には、プロキシサーバーを経由したリクエストの場合、プロキシサーバーの IP アドレスが格納される場合があります。- より詳細な IP アドレス情報が必要な場合は、
express-ip
やexpress-request-ip
などのサードパーティ製ミドルウェアを使用することを検討してください。
Express.js で req.ip から IPv4 アドレスを取得するその他の方法
すでに説明した方法以外にも、req.ip
から IPv4 アドレスを取得する方法がいくつかあります。以下に、その例を紹介します。
const express = require('express');
const requestIp = require('request-ip');
const app = express();
app.get('/', (req, res) => {
const ipv4Address = requestIp.getFwd(req);
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
const express = require('express');
const expressRequestInfo = require('express-request-info');
const app = express();
app.use(expressRequestInfo());
app.get('/', (req, res) => {
const ipv4Address = req.info.ip;
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
方法 6: カスタムミドルウェアを使用する
const express = require('express');
const app = express();
app.use((req, res, next) => {
const ip = req.ip;
const ipv4Address = ip.replace(/^::ffff:/, '');
req.ipv4Address = ipv4Address;
next();
});
app.get('/', (req, res) => {
const ipv4Address = req.ipv4Address;
console.log(`Client IP address: ${ipv4Address}`);
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
上記の方法はいずれも、req.ip
から ::ffff
プレフィックスを削除し、IPv4 アドレスを取得する処理を行います。
- 方法 5:
express-request-info
モジュールを使用する方法は、req.info.ip
プロパティから IPv4 アドレスを取得することができます。 - 方法 6: カスタムミドルウェアを使用する方法は、より柔軟な処理を行うことができます。
選択方法
どの方法を選択するかは、以下の要素を考慮する必要があります。
- プロキシサーバーを使用しているかどうか
- 取得したい IP アドレスの詳細度
- コードの複雑さ
node.js express