Express.js req.ipが:: ffff:127.0.0.1を返す


98

現在、リクエストされたユーザーのIPを取得しようとしています。問題は、IPがの::ffff:127.0.0.1代わりに戻ってくることです127.0.0.1trusted proxyオプションを使用してみましたが(プロキシを使用していません)、req.ips空白です。4.x Express.jsを使用します。

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});

それであなたは何を使っていますreq.ipreq.ips
Aleksandr M

req.ipreq.ipsテストとして試してみました。何がプレフィックスを引き起こしているのか、私にはわかりません::ffff:
rockerBOO


はい、これで終わりです。Windows 7にはIPv4要求用の移行レイヤーがあり、このプレフィックスをIPに追加します。
rockerBOO 2015

回答:


155

::ffff:IPv6(128ビット)スペース内に配置されるIPv4(32ビット)アドレスのサブネットプレフィックスです。IPv6は、サブネットプレフィックスとインターフェイスサフィックスの2つの部分に分かれています。それぞれが64ビット長、つまり4つの16進文字の4つのグループです。

IPv6では、先行ゼロを削除してから連続ゼロを削除することができます。つまり、::ffff:実際にはに変換されます0000:0000:ffff:0000。このアドレスはIPv4からIPv6へのサブネットプレフィックスとして指定されているため、どのIPv6プロセッサもIPv4アドレスで機能していることを理解し、処理しますそれに応じて。

近い将来、IPアドレスはすべてIPv6になります。これは、IPv4アドレススペースの数(42億から、その他の目的のためのスペースを差し引いたもの)がほぼなくなるためです。

IPv6では、はるかに大きなスペースが可能です。「誰にとっても340十億ユーロで十分だ」-IPv6について語るビルゲイツ氏。

IPv6名前空間を使用してIPアドレスのアドレス指定を開始::ffff:し、コードにを含めることが重要です。将来、これらのコロンの間に実際の16進データが存在するようになるためです。審美的な理由でそれを取り除くと、コードがIPv6ネットワークに切り替わったとき、またはIPv6アドレスに直面したときにコードが壊れます。

一部のネットワークは現在IPv6を実行しており、間もなくIPv6 IPアドレスに直面することになります。今すぐ飛躍するか、将来あなたのコードを壊す危険を冒してください。

問題のTL; DR(短縮)バージョンは次のとおりです。すべてが正常に動作しています。変更しないでください。これはIPv4アドレスのIPv6バージョンです。

IPv6 IPv4

コードにIPv6との互換性を持たせたい場合は、::ffff:プレフィックスを確認するだけです...プレフィックスが存在する場合は削除し、残りをIPv4として処理します... ::ffff:存在しない場合はIPv6アドレスです。そのように処理する必要があります。文字列にピリオドが含まれているかどうかを確認することで再確認できます。含まれている場合は、IPv4です。

IPアドレスに加える必要がある調整以外はすべて覚えておいてください。IPを記録するだけですよね?パーサーとログの集合体にとって::ffff:127.0.0.1、今後期待されることなどが重要になります。IPを変更する必要がない限り、受け取ったままにしておきます。


ただし::ffff:プレフィックス確認するのはかなり危険に聞こえます。IPv6には多くの表記法があります。
КонстантинВан

1
いいえ、それは安全です:)提案があり、次に実装があります。en.wikipedia.org/wiki/…IETFは、ルーターはIPアドレスを探すためにそれほど多くのサイクルを実行できないことを認識しています。また、実際には、無駄なスペースのためにゼロを維持する人はいません。ゼロを許可するというアイデアは、単なるアイデアでした。2019で:: ffff:をネットワークパケットで0000:0000:ffff:0000として送信した場合、元の提案では技術的には有効ですが、現在のIETF推奨では無効であり、ほとんどのIPv6互換ルーターでは見られません。
Nick Steele

1
だから私はそれらが常に標準的な形であることを確信することができます。状況がどうなっているかわからなかった。ありがとう。
КонстантинВан

これは残念ながら一般的です。人間は必要なときだけ注意を払います。誰かが何かをドラフトし、元のデザインは多くの機能をサポートし、RFCを作成し、誰もデザインの多くの部分に注意を払わず、それが標準となり、実装された人々は大きな変更が必要であることに気づきます:) IPv6は少し奇妙です「大砲」と呼ぶのは少し奇妙だからです。おそらく何が起こっているのかをすぐに理解できるように、「1.1」などと呼ぶ必要がありますが、元のドラフトのオプションのゼロはルーターで10倍以上のコンピューティングを費やすため、単に無視されました。
Nick Steele

29

これはipv6の癖のようです:ipv4アドレスの場合、ipv6はipv6表記とipv4表記を混合しているようです。

単純な混合表記でipv4とipv6の両方のアドレスを取得するために、私は以下を使用しています。

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
if (ip.substr(0, 7) == "::ffff:") {
  ip = ip.substr(7)
}


10

Windows 7では、デフォルトでIPv6が有効になっています。私のサーバーはIPv4のみでリッスンしていますが、Windows 7 ::ffff:はIPv6への移行の一部としてプレフィックスをIPv4に送信します

::ffff:0:0:0/96 —ステートレスIP / ICMP変換(SIIT)プロトコルで使用されるIPv4変換アドレスに使用されるプレフィックス。

IPv4からの移行


8

ipv4でマッピングされたアドレスを比較しようとして問題が発生し、ipaddr.jsライブラリが役に立った:-)

例えば

_.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true

3

サブネットを削除して正確なIPアドレスを取得するには、これを試してください。

    let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    ip = ip.toString().replace('::ffff:', '');

-2

あなたは自分のIPアドレスを単独で、またはソケットを使用して指定されたファミリで取得できます

     var app = require('express')();

 app.get("/ip", (req, res) => {
        console.log(req.ip) 
       let ip = req.ip.split(':');
        let ip_details = req.socket.address();
          console.log(ip_details);                     
   // { address: '::ffff:127.0.0.1', family: 'IPv6', port: 3001 

           console.log(ip[3]);//127.0.0.1
                            res.json(ip[3]);  
      }

-2
var ip = req.ip.split(':').pop();

他の回答が説明するように、これはIPv6アドレスです。上記の@Nick Steeleの回答を参照してください。あなたは本当にこれをしたくありません。
Misha Nasledov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.