Express.js req.ip kembali :: ffff: 127.0.0.1

99

Saat ini saya mencoba mendapatkan IP dari pengguna yang diminta. Masalahnya adalah IP kembali, ::ffff:127.0.0.1bukan 127.0.0.1. Saya mencoba menggunakan trusted proxyopsi (meskipun tidak menggunakan proxy) dan req.ipskosong. Menggunakan 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});
rockerBOO
sumber
Jadi apa yang kamu gunakan req.ipatau req.ips?
Aleksandr M
req.ip, baru saja dicoba req.ipssebagai ujian. Saya hanya tidak yakin apa yang menyebabkan awalan ::ffff:.
rockerBOO
Ya, ini dia. Windows 7 memiliki lapisan transisi untuk permintaan IPv4, dan menambahkan awalan ini ke IP.
rockerBOO

Jawaban:

157

::ffff:adalah awalan subnet untuk alamat IPv4 (32 bit) yang ditempatkan di dalam ruang IPv6 (128 bit). IPv6 dipecah menjadi dua bagian, awalan subnet, dan akhiran antarmuka. Masing-masing memiliki panjang 64 bit, atau, 4 grup dengan 4 karakter heksadesimal.

Di IPv6, Anda diizinkan untuk menghapus angka nol di depan, dan kemudian menghapus angka nol yang berurutan, yang berarti ::ffff:benar-benar diterjemahkan menjadi 0000:0000:ffff:0000, alamat ini telah ditetapkan sebagai awalan subnet IPv4 ke IPv6, sehingga prosesor IPv6 apa pun akan memahami bahwa itu berfungsi dengan alamat IPv4 dan menanganinya demikian.

Dalam waktu dekat, semua alamat IP akan menjadi IPv6, ini karena kami hampir kehabisan jumlah (4,2 miliar, dikurangi beberapa ruang untuk tujuan lain-lain) di ruang alamat IPv4.

IPv6 memungkinkan ruang yang jauh lebih besar. "340 undecillion seharusnya cukup untuk siapa pun" - Bill Gates berbicara di IPv6.

Penting untuk mulai menangani alamat IP menggunakan namespace IPv6 dan karena itu sertakan ::ffff:dalam kode Anda karena di masa mendatang akan ada data heksadesimal nyata di antara titik dua tersebut. Jika Anda melepasnya karena alasan estetika, kode Anda akan rusak saat beralih ke jaringan IPv6 atau dihadapkan dengan alamat IPv6.

Beberapa jaringan saat ini menjalankan IPv6 dan Anda akan segera dihadapkan dengan alamat IP IPv6; lakukan lompatan sekarang atau risiko melanggar kode Anda di masa mendatang.

Versi TL; DR (singkat) dari masalah ini adalah: Semuanya bekerja dengan baik. Jangan mengubahnya, ini adalah versi IPv6 dari alamat IPv4.

IPv4 IPv6

Jika Anda ingin membuat kode Anda kompatibel dengan IPv6, yang harus Anda lakukan adalah memeriksa ::ffff:prefiks ... jika ada, hapus dan proses sisanya sebagai IPv4 ... jika ::ffff:tidak ada, itu adalah alamat IPv6 dan perlu diproses seperti itu. Anda dapat memeriksa ulang dengan melihat apakah titik ada dalam string, jika demikian, itu adalah IPv4.

Ingatlah untuk semuanya kecuali penyesuaian yang perlu Anda lakukan pada alamat IP, Anda hanya merekam IP, bukan? Ini akan menjadi penting bagi parser dan agregat log yang diharapkan ::ffff:127.0.0.1dan semacamnya di masa mendatang. Kecuali Anda perlu mengubah IP, biarkan saja seperti yang Anda terima.

Nick Steele
sumber
Kedengarannya cukup berbahaya untuk memeriksa ::ffff:awalannya . Anda tahu, IPv6 memiliki banyak notasi.
Константин Ван
1
Tidak, itu aman :) Ada proposal, dan kemudian ada implementasinya. en.wikipedia.org/wiki/… IETF telah menyadari bahwa router tidak dapat membakar banyak siklus untuk mencari alamat IP, dan juga di alam liar, tidak ada yang menyimpan angka nol karena itu menyia-nyiakan ruang. Ide untuk mengizinkan nol hanyalah sebuah ide. Pada 2019 jika Anda mengirim :: ffff: dalam paket jaringan sebagai 0000: 0000: ffff: 0000, meskipun secara teknis valid untuk proposal asli, ini tidak valid untuk rekomendasi IETF saat ini serta tidak akan terlihat di sebagian besar router yang kompatibel dengan IPv6.
Nick Steele
1
Jadi saya yakin mereka selalu dalam bentuk kanonik . Tidak tahu bagaimana keadaan di alam liar. Terima kasih.
Константин Ван
Sayangnya ini biasa terjadi. Manusia hanya memperhatikan jika diperlukan. Seseorang membuat draf sesuatu, desain aslinya mendukung banyak fitur, mereka membuat RFC, tidak ada yang benar-benar memperhatikan banyak bagian desain, itu menjadi standar, kemudian ketika diimplementasikan orang-orang memperhatikan perubahan besar diperlukan :) IPv6 agak aneh karena menyebutnya "meriam" agak aneh. Mereka mungkin harus menyebutnya "1.1" atau sesuatu sehingga orang dapat dengan cepat memahami apa yang sedang terjadi, tetapi karena nol opsional draf asli membuat Anda menghabiskan 10x lebih banyak komputasi di router, itu diabaikan begitu saja.
Nick Steele
29

Ini tampaknya merupakan kekhasan dari ipv6: untuk alamat ipv4, ipv6 tampaknya mencampur notasi ipv6 dengan notasi ipv4.

Untuk mendapatkan alamat ipv4 dan ipv6 dalam notasi sederhana dan tidak tercampur, saya menggunakan:

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

Windows 7 memiliki IPv6 yang diaktifkan secara default. Meskipun server saya hanya mendengarkan IPv4, Windows 7 mengirimkan ::ffff:awalan ke IPv4 sebagai bagian dari transisi ke IPv6

::ffff:0:0:0/96 - Awalan yang digunakan untuk alamat terjemahan IPv4 yang digunakan oleh protokol Stateless IP / ICMP Translation (SIIT).

Transisi dari IPv4

rockerBOO
sumber
8

Saya mengalami masalah dengan mencoba membandingkan alamat yang dipetakan ipv4, dan menemukan perpustakaan ipaddr.js membantu :-)

misalnya

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

Coba ini untuk mendapatkan alamat ip yang tepat dengan menghapus subnetting,

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

Anda bisa mendapatkan alamat Ip Anda sendiri atau dengan Keluarga yang ditentukan menggunakan soket

     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]);  
      }
muthukumar selvaraj
sumber
-2
var ip = req.ip.split(':').pop();
Mateo Marin
sumber
Seperti jawaban lain yang menjelaskan, ini adalah alamat IPv6. Lihat jawaban @Nick Steele di atas. Anda benar-benar tidak ingin melakukan ini.
Misha Nasledov