Cara menentukan alamat IP pengguna di simpul

349

Bagaimana saya bisa menentukan alamat IP dari permintaan yang diberikan dari dalam pengontrol? Misalnya (dalam express):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})
Shamoon
sumber
22
Jika Anda menggunakan Express, Anda dapat menggunakan req.ip source - expressjs.com/en/api.html#req.ip
FrickeFresh
Coba ini: github.com/indutny/node-ip
Stephen Last
16
Bagi mereka yang bekerja dari localhost- seperti yang saya lakukan, hasil untuk semua jawaban di bawah (Hampir semua jawaban berfungsi) mungkin datang ::1. Ini kadang membuat saya bingung. Kemudian ditemukan bahwa itu ::1adalah Alamat IP asli dan IPV6notasi untuk localhost. Hope this helps someone
Pramesh Bajracharya

Jawaban:

452

Di requestobjek Anda ada properti yang disebut connection, yang merupakan net.Socketobjek. Objek net.ocket memiliki properti remoteAddress, oleh karena itu Anda harus bisa mendapatkan IP dengan panggilan ini:

request.connection.remoteAddress

Lihat dokumentasi untuk http dan net

EDIT

Seperti @juand tunjukkan dalam komentar, metode yang benar untuk mendapatkan IP jarak jauh, jika server berada di belakang proxy, adalah request.headers['x-forwarded-for']

topek
sumber
6
Ini memberi saya alamat IP yang berbeda dari apa yang diberikan whatismyip.com kepada saya. Kenapa bisa begitu?
Shamoon
3
Saya memiliki layanan API saya diinstal pada instance no.de. Ketika saya mencoba mengaksesnya dari komputer saya, saya mendapatkan alamat IP "10.2.XXX.YYY" sedangkan IP dunia nyata saya adalah "67.250.AAA.BBB"
Shamoon
7
it's request.headers ['X-Forwarded-For']
0x6A75616E
4
Perhatikan bahwa net.Stream sekarang net.Socket, dan dokumentasinya tinggal di sini: nodejs.org/api/net.html#net_class_net_socket
monsur
4
Bagi siapa pun yang tertarik, untuk Heroku: request.headers['x-forwarded-for']
FueledPublishing
407
var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     (req.connection.socket ? req.connection.socket.remoteAddress : null);

Perhatikan bahwa terkadang Anda bisa mendapatkan lebih dari satu alamat IP req.headers['x-forwarded-for']. Selain itu, x-forwarded-fortajuk tidak akan selalu disetel yang dapat menimbulkan kesalahan.

Format umum bidang ini adalah:

x-diteruskan-untuk: client, proxy1, proxy2, proxy3

di mana nilainya adalah daftar alamat IP yang dipisahkan koma + spasi, yang paling kiri adalah klien asli, dan setiap proksi berturut-turut yang lulus permintaan menambahkan alamat IP dari mana ia menerima permintaan. Dalam contoh ini, permintaan melewati proxy1, proxy2dan kemudian proxy3. proxy3muncul sebagai alamat permintaan yang jauh.

Ini adalah solusi yang disarankan oleh Arnav Gupta dengan perbaikan yang disarankan Martin di bawah dalam komentar untuk kasus-kasus ketika x-forwarded-fortidak disetel:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress
Edmar Miyake
sumber
9
Bagaimana mencegah spoofing header ini?
Domi
8
Ini biasanya bekerja dengan baik tetapi untuk beberapa alasan saya baru-baru ini mendapatkan kesalahan "Tidak dapat membaca properti 'remoteAddress' dari yang tidak terdefinisi" karena ternyata semuanya adalah null / tidak terdefinisi, termasuk req.connection.socket. Saya tidak yakin mengapa / kondisi apa yang menyebabkan hal itu terjadi tetapi akan lebih baik untuk memeriksa yang req.connection.socketada untuk menghindari server Anda crash jika ini terjadi.
Matt Browne
9
Baris terakhir req.connection.socket.remoteAddress galat melempar. Hati-hati.
yAnTar
11
Alamat ip yang dikembalikan adalah :: 1. Mengapa?
Bagusflyer
3
Melihat cara pop () berfungsi, sepertinya Anda akan mendapatkan proksi terakhir dan bukan klien yang Anda inginkan. Apakah aku salah?
Michel
84

Jika menggunakan express ...

req.ip

Saya melihat ini lalu saya seperti menunggu, saya menggunakan express. Duh.

Jason Sebring
sumber
Akan mengembalikan variasi 127.0.0.1 jika server berjalan di belakang proxy. Gunakan jawaban Edmar atau atur x-real-ip .
Dan Dascalescu
31

Anda dapat tetap KERING dan cukup gunakan node-ipware yang mendukung IPv4 dan IPv6 .

Install:

npm install ipware

Di app.js atau middleware Anda:

var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
    var ipInfo = getIP(req);
    console.log(ipInfo);
    // { clientIp: '127.0.0.1', clientIpRoutable: false }
    next();
});

Ini akan melakukan upaya terbaik untuk mendapatkan alamat IP pengguna atau mengembalikan 127.0.0.1untuk menunjukkan bahwa itu tidak dapat menentukan alamat IP pengguna. Lihatlah file README untuk opsi lanjutan.

un33k
sumber
40
"atau mengembalikan 127.0.0.1 untuk menunjukkan bahwa itu tidak dapat menentukan alamat IP pengguna" Ada perbedaan yang cukup besar antara 127.0.0.1 dan tidak diketahui ...
Nepoxx
4
Itu mengembalikan sesuatu yang aneh bagi saya :ffff:(not my IP address)ketika diuji dari Heroku. Jawaban @ edmar-miyake bekerja dengan baik untuk saya.
Nilloc
Saya bertanya-tanya apa yang akan IP jika Anda menggunakan lookup right2left dalam kasus 'x-forwarded-for'. var ip_info = get_ip (req, right_most_proxy = True), seperti pada beberapa pengaturan, IP klien mungkin IP yang paling tepat.
un33k
2
Metode itu kembali clientIp: '::1'untuk saya. Sepertinya tidak berhasil.
JamEngulfer
@JamEngulfer - ipware hanya berfungsi jika alamat ip diturunkan dengan benar ke aplikasi Anda melalui request.headers []. contoh: AWS LBS mengirim alamat Ip dalam 'x-diteruskan-untuk' sementara NginX kustom banyak menggunakan variabel lain. ipware melakukan upaya terbaik untuk mengetahui alamat IP, tetapi hanya jika IP telah diturunkan di header.
un33k
19

Anda dapat menggunakan permintaan-ip , untuk mengambil alamat ip pengguna. Ini menangani beberapa kasus tepi yang berbeda, beberapa di antaranya disebutkan dalam jawaban lain.

Pengungkapan: Saya membuat modul ini

Install:

npm install request-ip

Di aplikasi Anda:

var requestIp = require('request-ip');

// inside middleware handler
var ipMiddleware = function(req, res, next) {
    var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
    next();
};

Semoga ini membantu

pbojinov
sumber
2
memeriksa kode sumber permintaan paket-ip di github.com/pbojinov/request-ip/blob/master/index.js memeriksa x-forwarded-for dan segala macam header lainnya untuk load balancers populer seperti AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB dan Stingray Riverbed
Giorgio
1
itu kembali nulluntukku.
S.M_Emamian
Hal yang sama malah digunakanrequest.headers['x-forwarded-for']
Prathamesh More
19

request.headers['x-forwarded-for'] || request.connection.remoteAddress

Jika x-forwarded-fortajuk ada di sana kemudian gunakan itu, jika tidak gunakan .remoteAddressproperti.

The x-forwarded-forheader ditambahkan ke permintaan yang melewati balancers beban (atau jenis proxy) diatur untuk HTTP atau HTTPS (itu juga mungkin untuk menambahkan header ini permintaan ketika menyeimbangkan pada TCP tingkat menggunakan protokol proxy yang ). Ini karena request.connection.remoteAddressproperti akan berisi alamat IP pribadi penyeimbang beban daripada alamat IP publik klien. Dengan menggunakan pernyataan ATAU , dalam urutan di atas, Anda memeriksa keberadaan x-forwarded-forheader dan menggunakannya jika ada, gunakan request.connection.remoteAddress.

Ben Davies
sumber
12

Fungsi Berikut memiliki semua kasus yang dibahas akan membantu

var ip;
if (req.headers['x-forwarded-for']) {
    ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
    ip = req.connection.remoteAddress;
} else {
    ip = req.ip;
}console.log("client IP is *********************" + ip);
ashishyadaveee11
sumber
Perhatikan ips ada di , antara saya.
ThomasReggi
8

Ada dua cara untuk mendapatkan alamat ip:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Tetapi ada masalah dengan pendekatan di atas.

Jika Anda menjalankan aplikasi di belakang Nginx atau proxy apa pun, setiap alamat IP akan menjadi 127.0.0.1 .

Jadi, solusi terbaik untuk mendapatkan alamat ip pengguna adalah: -

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
Mansi Teharia
sumber
6

Jika Anda menggunakan versi ekspres 3.x atau lebih besar, Anda dapat menggunakan pengaturan proxy kepercayaan ( http://expressjs.com/api.html#trust.proxy.options.table ) dan itu akan berjalan di rantai alamat di header x-forwarded-for dan letakkan ip terbaru di rantai yang belum Anda konfigurasikan sebagai proxy tepercaya ke properti ip pada objek req.

Michael Lang
sumber
6

function getCallerIP(request) {
    var ip = request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress ||
        request.connection.socket.remoteAddress;
    ip = ip.split(',')[0];
    ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
    return ip;
}

Ahmad Agbaryah
sumber
1
Anda benar, jika Anda ingin ip sebagai string, maka Anda dapat mengganti baris terakhir dengan: ip = ip.split (':'). Slice (-1) [0]
Ahmad Agbaryah
Jawaban khusus kode tidak disarankan. Bisakah Anda menjelaskan bagaimana jawaban ini lebih baik dari yang lebih tua, lebih baik dijelaskan, dan (banyak) lebih upvoted jawaban ?
Dan Dascalescu
5

Peringatan:

Jangan hanya menggunakan ini secara membabi buta untuk pembatasan tingkat penting:

let ip = request.headers['x-forwarded-for'].split(',')[0];

Sangat mudah untuk spoof:

curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"

Dalam hal ini alamat IP asli pengguna akan:

let ip = request.headers['x-forwarded-for'].split(',')[1];

Saya terkejut bahwa tidak ada jawaban lain yang menyebutkan ini.


sumber
The top jawaban tidak menangani ini dengan pop()ing dari array, yang lebih umum daripada mendapatkan elemen pada indeks 1, yang dapat tertipu oleh curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu
3

Jika Anda mendapatkan beberapa IP, ini berfungsi untuk saya:

var ipaddress = (req.headers['x-forwarded-for'] || 
req.connection.remoteAddress || 
req.socket.remoteAddress || 
req.connection.socket.remoteAddress).split(",")[0];

Kirill Chatrov
sumber
3

Sederhana mendapatkan ip jarak jauh di nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
Vlog IT
sumber
3

Di simpul 10.14, di belakang nginx, Anda dapat mengambil ip dengan memintanya melalui header nginx seperti ini:

proxy_set_header X-Real-IP $remote_addr;

Kemudian di app.js Anda:

app.set('trust proxy', true);

Setelah itu, di mana pun Anda ingin itu muncul:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;
Alexandru
sumber
2

Saya menyadari ini telah dijawab sampai mati, tetapi inilah versi ES6 modern yang saya tulis yang mengikuti standar eslint airbnb-base.

const getIpAddressFromRequest = (request) => {
  let ipAddr = request.connection.remoteAddress;

  if (request.headers && request.headers['x-forwarded-for']) {
    [ipAddr] = request.headers['x-forwarded-for'].split(',');
  }

  return ipAddr;
};

Header X-Forwarded-For dapat berisi daftar IP proxy yang dipisahkan koma. Pesanannya adalah klien, proxy1, proxy2, ..., proxyN. Di dunia nyata, orang menerapkan proxy yang dapat memasok apa pun yang mereka inginkan di header ini. Jika Anda berada di belakang penyeimbang beban atau sesuatu, Anda setidaknya dapat memercayai IP pertama dalam daftar setidaknya adalah proxy apa pun yang diminta oleh beberapa permintaan.

Misha Nasledov
sumber
1

Jika Anda menggunakan Graphql-Yoga, Anda dapat menggunakan fungsi berikut:

const getRequestIpAddress = (request) => {
    const requestIpAddress = request.request.headers['X-Forwarded-For'] || request.request.connection.remoteAddress
    if (!requestIpAddress) return null

    const ipv4 = new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")

    const [ipAddress] = requestIpAddress.match(ipv4)

    return ipAddress
}

Arsham Gh
sumber
-7

Punya masalah yang sama ... saya juga baru di javascript tetapi saya menyelesaikan ini dengan req.connection.remoteAddress; yang memberi saya alamat IP (tetapi dalam format ipv6 :: ffff.192.168.0.101) dan kemudian .slice untuk menghapus 7 digit pertama.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}
aCo
sumber
ini bukan metode yang baik, karena ipv6 BUKAN hanya 7 digit + IPv4, tetapi bisa sangat berbeda.
Radek
@Radek jika Anda memvalidasi awal alamat, itu sesuai dengan spec (lihat en.wikipedia.org/wiki/IPv6_address pencarian ctrl-f untuk "IPv4-mapped") ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))akan menggantikan if ... pada kode di atas
tidak disinkronkan
saya pribadi membungkus getClientIp () dari npm request-ip untuk membuat function getClientIp4(req){ var ip=typeof req==='string'?req:getClientIp(req); return (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined)); }yang menerima ip yang sebelumnya diambil, atau objek permintaan sebagai input dan memberikan ip atau tidak didefinisikan sebagai hasilnya
tidak disinkronkan