Bir kullanıcının düğümdeki IP adresini belirleme


350

Bir denetleyiciden belirli bir isteğin IP adresini nasıl belirleyebilirim? Örneğin (açık olarak):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})

23
Express kullanıyorsanız, req.ip kaynağı kullanabilirsiniz - expressjs.com/en/api.html#req.ip
FrickeFresh


16
Çalıştığım localhostgibi - benim yaptığım gibi, aşağıdaki tüm cevapların sonucu (Neredeyse tüm cevaplar çalışır) gelebilir ::1. Bu beni bir süre karıştırdı. Daha sonra ::1bunun gerçek IP Adresi olduğunu ve IPV6localhost için bir gösterim olduğunu öğrendim . Hope this helps someone
Pramesh Bajracharya

Yanıtlar:


452

Senin içinde requestnesne adında bir özellik vardır connectionbir olduğunu, net.Socketnesne. Net.Socket nesnesinin bir özelliği vardır remoteAddress, bu nedenle IP'yi şu çağrı ile alabilmeniz gerekir:

request.connection.remoteAddress

Http ve net için belgelere bakın

DÜZENLE

@Juand yorumlarda belirtildiği gibi, sunucu bir proxy'nin arkasındaysa, uzak IP'yi almak için doğru yöntem request.headers['x-forwarded-for']


6
Bu bana whatismyip.com'un bana verdiğinden farklı bir IP adresi veriyor. Neden olsun ki?
Shamoon

3
Bir no.de örneğinde API hizmetim yüklü . Bilgisayarımdan erişmeye çalıştığımda, "10.2.XXX.YYY" IP adresi alırken, gerçek dünya IP adresim "67.250.AAA.BBB"
Shamoon

7
request.headers ['X-Forwarded-For']
0x6A75616E

4
Net.Stream'in artık net.Socket olduğunu ve belgelerin burada yaşadığını unutmayın: nodejs.org/api/net.html#net_class_net_socket
monsur

4
İlgilenenler için Heroku için: request.headers['x-forwarded-for']
FueledPublishing

408
var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     (req.connection.socket ? req.connection.socket.remoteAddress : null);

Bazen birden fazla IP adresi alabileceğinizi unutmayın req.headers['x-forwarded-for']. Ayrıca, x-forwarded-forher zaman bir hata atabilecek bir başlık ayarlanmayacaktır.

Alanın genel biçimi:

X-iletilen-için: client, proxy1, proxy2, proxy3

burada değer, virgülle + boşlukla ayrılmış bir IP adresi listesidir; en soldaki orijinal istemci olur ve isteği ileten birbirini izleyen her proxy, isteği aldığı IP adresini ekler. Bu örnekte, istek geçirildi proxy1, proxy2ve sonra proxy3. proxy3isteğin uzak adresi olarak görünür.

Bu önerdiği çözüm Arnav Gupta bir düzeltme ile Martin durumlar için yorumlardaki aşağıda önerdi x-forwarded-forayarlı değil:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress

9
Bu başlıkların kimlik sahtekarlığı nasıl önlenir?
Domi

8
Bu genellikle iyi çalışır ama bazı nedenlerden dolayı yakın zamanda "undefined 'remoteAddress' özelliği okunamıyor" hatası var çünkü görünüşe göre her şey null / undefined, dahil req.connection.socket. Neden / hangi koşulların böyle olmasına neden olduğundan emin değilim, ancak bu durumda req.connection.socketsunucunuzun çökmesini önlemek için var olduğunu kontrol etmek iyi olurdu .
Matt Browne

9
Son satır req.connection.socket.remoteAddress atma hatası. Dikkatli ol.
yAnTar

11
Döndürülen ip adresi :: 1'dir. Neden?
Bagusflyer

3
Pop () 'un çalışma şekline baktığınız zaman, istediğiniz son istemciyi değil son proxy'yi alacaksınız. Yanlış mıyım?
Michel


31

DRY kalabilir ve sadece IPv4 ve IPv6'yı destekleyen düğüm ipware'i kullanabilirsiniz .

Yüklemek:

npm install ipware

App.js veya ara katman yazılımınızda:

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();
});

Kullanıcının IP adresini almak için en iyi girişimi yapar veya kullanıcının IP adresini 127.0.0.1belirleyemediğini belirtmek için geri döner . Bir göz atın README gelişmiş seçenekler için dosyanın.


40
"veya kullanıcının IP adresini belirleyemediğini belirtmek için 127.0.0.1 değerini döndürür" 127.0.0.1 ile bilinmeyen arasında oldukça büyük bir fark vardır ...
Nepoxx

4
:ffff:(not my IP address)Heroku'dan test edildiğinde benim için garip bir şey verdi. @ edmar-miyake'nin cevabı benim için düzgün çalışıyor.
Nilloc

'X-forwarded-for' durumunda right2left aramasını kullanırsanız IP'nin ne olacağını merak ediyorum. var ip_info = get_ip (req, right_most_proxy = True), bazı kurulumlarda olduğu gibi, istemci IP'si en doğru IP olabilir.
un33k

2
Bu yöntem clientIp: '::1'benim için geri dönüyor . Çalışmıyor gibi görünüyor.
JamEngulfer

@JamEngulfer - ipware yalnızca ip adresi, request.headers [] aracılığıyla uygulamanıza düzgün bir şekilde aktarılırsa çalışır. örnek: AWS LBS, Ip adresini 'x-forwarded-for' biçiminde gönderirken, özel NginX pek çok başka değişken kullanır. ipware, IP adresini bulmak için en iyi girişimi yapar, ancak yalnızca IP başlıklarda aktarılmışsa.
un33k

19

Bir kullanıcının ip adresini almak için request-ip kullanabilirsiniz . Bazıları diğer cevaplarda bahsedilen farklı uç durumlardan birkaçını ele alır.

Açıklama: Bu modülü oluşturdum

Yüklemek:

npm install request-ip

Uygulamanızda:

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();
};

Bu yardımcı olur umarım


2
request-ip paketinin kaynak kodunu github.com/pbojinov/request-ip/blob/master/index.js adresinden kontrol ederek, AWS ELB, Cloudflare gibi popüler yük dengeleyiciler için x-forwarded for ve diğer her türlü başlığı kontrol eder , Akamai, nginx, Rackspace LB ve Riverbed's Stingray
Giorgio

1
benim için geri döner null.
S.M_Emamian

Aynı şey yerinerequest.headers['x-forwarded-for']
Prathamesh More

19

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

Eğer x-forwarded-forbaşlık var o zaman başka türlü kullanmak, kullanan .remoteAddressözelliğini.

x-forwarded-forBaşlığı için ayarlanmış yük dengeleyici (veya vekaleten diğer türleri) geçmesine isteklere eklenir HTTP veya HTTPS (bir de dengeleme zaman isteklerine bu başlığı eklemek de mümkündür TCP kullanarak düzeyde vekil protokol ). Bunun nedeni, request.connection.remoteAddressözelliğin istemcinin genel IP adresi yerine yük dengeleyicisinin özel IP adresini içermesidir. Bir OR ifadesi kullanarak , yukarıdaki sırayla, bir x-forwarded-forüstbilginin varlığını kontrol edersiniz ve varsa bunu kullanırsınız request.connection.remoteAddress.


12

Aşağıdaki Fonksiyonu kapsanan tüm durumlarda yardımcı olacaktır

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);

İps , benim için bir arada olduğunu unutmayın .
ThomasReggi

8

IP adresini almanın iki yolu vardır:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Ancak yukarıdaki yaklaşımlarla ilgili bir sorun var.

Uygulamanızı Nginx veya herhangi bir proxy'nin arkasında çalıştırıyorsanız, her IP adresi olacaktır 127.0.0.1.

Yani, kullanıcının ip adresini almak için en iyi çözüm: -

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


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;
}


1
Haklısınız, ipi dize olarak istiyorsanız, son satırı şu şekilde değiştirebilirsiniz: ip = ip.split (':'). Dilim (-1) [0]
Ahmad Agbaryah

Yalnızca kod yanıtları önerilmez. Bu cevabın daha eski, daha iyi açıklanmış ve (çok) daha fazla onaylanmış cevaplardan daha iyi olduğunu açıklayabilir misiniz?
Dan Dascalescu

5

Uyarı:

Bunu sadece önemli hız sınırlaması için körü körüne kullanmayın:

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

Taklit etmek çok kolay:

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

Bu durumda kullanıcının gerçek IP adresi:

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

Bundan başka cevap gelmediğine şaşırdım.


Üst cevap tarafından bu işi yapar pop()edilebilir indeksi 1, en eleman almaktan daha geneldir dizisinden ing aptal tarafından curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu

3

Birden fazla IP alırsanız, bu benim için çalışır:

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


3

Basit nodejs uzaktan ip olsun:

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

3

10.14 düğümünde, nginx'in arkasında, ipi şu şekilde nginx üstbilgisinden isteyerek alabilirsiniz:

proxy_set_header X-Real-IP $remote_addr;

Sonra app.js dosyasında:

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

Bundan sonra, nerede görünmesini istiyorsanız:

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

2

Bunun ölümle sonuçlandığını anlıyorum, ama burada yazdığım modern bir ES6 versiyonu airbnb-base eslint standartlarını takip ediyor.

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;
};

X-Forwarded-For üstbilgisi, virgülle ayrılmış bir proxy IP listesi içerebilir. Sipariş istemci, proxy1, proxy2, ..., proxyN'dir. Gerçek dünyada, insanlar bu başlıkta istedikleri her şeyi sağlayabilecek vekilleri uygularlar. Bir yük dengeleyicisinin veya başka bir şeyin arkasındaysanız, en azından listedeki ilk IP'nin en azından bazı isteklerin geldiği proxy olduğuna güvenebilirsiniz.


1

Graphql-Yoga kullanıyorsanız, aşağıdaki işlevi kullanabilirsiniz:

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
}


1

Ben nginx arkasında express kullanıyorum ve

req.headers.origin

benim için hile yaptı


-7

Aynı sorun vardı ... im de javascript yeni ama ben req.connection.remoteAddress ile çözüldü; Bu bana IP adresini verdi (ancak ipv6 biçiminde :: ffff.192.168.0.101) ve sonra .slice 7 rakamı kaldırmak için .slice .

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}

ipv6 sadece 7 basamak + IPv4 DEĞİLDİR, ancak tamamen farklı olabileceğinden bu iyi bir yöntem değildir.
Radek

Eğer adresin başlangıcını doğrulamak eğer @Radek, bu spec uygundur (bkz en.wikipedia.org/wiki/IPv6_address "IPv4 eşlenmiş" için ctrl-f arama) ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))eğer ... Yukarıdaki kodda yerini alacak
Eşitlenmemiş

kişisel olarak 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)); }önceden getirilmiş bir ip veya bir istek nesnesi girdi olarak kabul eder ve sonuç olarak ip veya tanımsız verir oluşturmak için npm request-ip'den getClientIp () 'i sarın
senkronize olmayan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.