Express.js: uzak istemci adresi nasıl alınır


256

Uzak kullanıcı IP adresini nasıl almam gerektiğini tam olarak anlamıyorum.

Diyelim ki böyle basit bir istek yolum var:

app.get(/, function (req, res){
   var forwardedIpsStr = req.header('x-forwarded-for');
   var IP = '';

   if (forwardedIpsStr) {
      IP = forwardedIps = forwardedIpsStr.split(',')[0];  
   }
});

Yukarıdaki yaklaşım gerçek kullanıcı IP adresini almak için doğru mu veya daha iyi bir yol var mı? Peki ya proxy'ler?


1
Nasıl kullanmayla ilgili düğüm-ipware açıklama gereği burada .
un33k

'example.com' gibi req.hostname alamıyorsanız: stackoverflow.com/a/37824880/5333284
zhi.yang

Yanıtlar:


471

NGiNX gibi bir vekilin veya sizin neyiniz varsa, sadece o zaman 'x-forwarded-for' seçeneğini kontrol etmelisiniz:

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

Proxy 'sizin' değilse, 'x-forwarded-for' başlığına güvenmem, çünkü parodi yapılabilir.


2
Bu doğrudur, ancak benim durumumda köşeli ayraç kullanmak zorunda kaldım (yukarıdaki düzenlemeye bakın) Ayrıca, xgined-for'un nginx yapılandırmanızda etkinleştirildiğinden emin olun. Tıkır tıkır çalışıyor!
ninehundreds

43
proxy_set_header X-Forwarded-For $remote_addr;Kendi ters proxy'nizi kullanıyorsanız, bu yönergeyi nginx yapılandırmanıza koymanız gerektiğini unutmayın .
Coxer

IP'yi tarayıcıda kullanmayı planlıyorsanız http (s): // [ipv6]: port [] 'a ihtiyaç duyulduğuna dikkat edin, bunun yardımcı
olacağını

43
kopya makarna kullanıcıları lütfen dikkat: Bu, IP adreslerinin virgülle ayrılmış bir listesini döndürebilir. Bunu kopyalayan ve sonucu bir IP ile karşılaştıran bir geliştiriciden bir hata aldık. Belki var ip = (req.headers['x-forwarded-for'] || req.connection.remoteAddress || '').split(',')[0].trim();istemci IP'si almak gibi bir şey yapın .
Davy Jones

3
@Rishav :: 1, localhost için IPv6 adresidir
Daniel O

238

@Alessioalex'in yanıtı çalışırken, Express kılavuzunun vekillerin arkasındaki Express bölümünde belirtildiği gibi başka bir yol var .

  1. app.set('trust proxy', true)Hızlı başlatma kodunuza ekleyin .
  2. Uzak istemcinin ipini almak istediğinizde, req.ipveya req.ipsnormal şekilde kullanın (ters proxy yokmuş gibi)

İsteğe bağlı okuma:

  • req.ipVeya tuşunu kullanın req.ips. req.connection.remoteAddressbu çözümle çalışmaz.
  • Üstbilgide 'trust proxy'iletilen her şeye güvenmekten daha karmaşık bir şeye ihtiyacınız varsa için daha fazla seçenek mevcuttur x-forwarded-for(örneğin, proxy'niz önceden var olan x iletilen üstbilgiyi güvenilmeyen kaynaklardan kaldırmazsa). Daha fazla ayrıntı için bağlantılı kılavuza bakın.
  • Proxy sunucunuz x-forwarded-forüstbilgiyi doldurmazsa , iki olasılık vardır.
    1. Proxy sunucusu, isteğin orijinal olduğu yerle ilgili bilgileri iletmez. Bu durumda, isteğin nereden geldiğini öğrenmenin bir yolu olmazdı. Önce proxy sunucusunun yapılandırmasını değiştirmeniz gerekir.
      • Örneğin, ters proxy'niz olarak nginx kullanıyorsanız proxy_set_header X-Forwarded-For $remote_addr;, yapılandırmanıza eklemeniz gerekebilir .
    2. Proxy sunucusu, isteğin orijinal olarak nereden geldiğiyle ilgili bilgileri özel bir şekilde iletir (örneğin, özel http başlığı). Bu durumda, bu cevap işe yaramaz. Bu bilgiyi elde etmenin özel bir yolu olabilir, ancak önce mekanizmayı anlamanız gerekir.

4
Cevabım daha geneldi (Express'e bağlı değil), ancak Express kullanıyorsanız bu gerçekten daha iyi bir yoldur.
alessioalex

4
Proxy sunucunuzun 'x-forwarded-for' başlığının uzak adrese ayarlanmış olması gerekir. Örneğin, nginx durumunda, yapılandırma dosyanızda proxy_set_header X-Forwarded-For $ remote_addr olmalıdır
Kamagatos

1
IIS'nin arkasında IISnode vekil sunucu app.enable('trust proxy')olarak kullanmak için de çalışır req.ip. Dışında ben onunla bağlantı noktası olsun 1.2.3.4:56789. Bunu şerit için, benvar ip = req.ip.split(':')[0]
Christiaan Westerbeek

Bu çözüm güvenli mi?
Daniel Kmak

3
Bu cevabın güvenlikten yoksun olduğunu ve güncellenmesi gerektiğini hissediyorum. Uygulamanıza hangi proxy'lerin güvendiğini DAİMA tanımlamalısınız. Kabul edilen cevabın en azından kimlik sahtekarlığıyla ilgili küçük bir bildirimi vardır. Bununla birlikte, ekspres kullanıyorsanız böyle bir kütüphane kullanmak daha iyi bir çözümdür, ancak alıntılanan kod yanlıştır ve bağlantılı kaynakta bulunmaz.
Phil

54

In nginx.confdosyası:
proxy_set_header X-Real-IP $remote_addr;

Gelen node.jssunucu dosyası:
var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;

küçük harf başlıklarını ifade etmeyi unutmayın


3
Stack Overflow'a hoş geldiniz! Lütfen yalnızca bir kod bloğu göndermek yerine, bu kodun neden ortaya çıkan sorunu çözdüğünü açıklayın. Bir açıklama olmadan, bu bir cevap değildir.
Artemix

1
@ququzone'un cevabı tamam. Açıklama, orijinal ip adresini ziyaretçiden alan "x-real-ip" adlı istek üzerine özel bir üstbilgi ayarlanır. Düğüm ve socket.io ile benim için çalışıyor.
coffekid

8
Benim için, IP adresi altında büyük harflerle ayarlanmış başlık altında req.headers['x-real-ip']bile kullanılabilir nginx.conf.
Nik Sumeiko

Bunu benim için çözen şey buydu. Trust-proxy doğru olarak ayarlanmış olsa bile, hala yerel 127.0.0.1 adresini kullanıyordu
David

30

Özellikle düğüm için, olay bağlantısı altında http sunucusu bileşeninin belgeleri şöyle diyor:

Yeni bir TCP akışı kurulduğunda [Tetiklendi]. [] Soketi net.Socket türünde bir nesnedir. Genellikle kullanıcılar bu etkinliğe erişmek istemez. Özellikle, protokol ayrıştırıcısının sokete nasıl bağlandığı nedeniyle soket okunabilir olaylar yayınlamaz. Sokete adresinden de erişilebilir request.connection.

Yani, bu request.connectionbir soket anlamına gelir ve belgelere göre gerçekten de belgelere göre bir socket.remoteAddress özniteliği vardır:

Uzak IP adresinin dize ile temsil edilen hali. Örneğin, '74 .125.127.100 'veya' 2001: 4860: a005 :: 68 '.

Ekspres altında, istek nesnesi de Node http istek nesnesinin bir örneğidir, bu nedenle bu yaklaşım yine de çalışmalıdır.

Ancak, Express.js altında isteğin zaten iki özelliği vardır: req.ip ve req.ips

req.ip

Uzak adresi veya "güven proxy'si" etkinleştirildiğinde - yukarı akış adresi.

req.ips

Ne zaman "güven vekil" olduğunu true, "X-Forward-For" ip adres listesi ayrıştırmak ve bir dizi, aksi boş bir dizi döndürülür dönün. Örneğin, değer "istemci, proxy1, proxy2" olsaydı, "proxy2" en uzak aşağı akış olan ["istemci", "proxy1", "proxy2"] dizisini alırsınız.

Bu değer, benim anlayışıma göre, Ekspres söz olabilir req.ipdaha iyi bir yaklaşımdır req.connection.remoteAddress, çünkü req.ipgerçek müşteri ip içeren diğer proxy IP adresini içerebilir, oysa varsa ((güvenilen vekil express etkin olması koşuluyla) bir).

Şu anda kabul edilen cevabın bu nedenle şunu öne sürmesinin nedeni:

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

req.headers['x-forwarded-for']Express eşdeğer olacaktır req.ip.



7

Bu sadece bu cevap için ek bilgi .

Kullanıyorsanız , sitenin konum bloğuna nginxeklersiniz proxy_set_header X-Real-IP $remote_addr;. /etc/nginx/sites-available/www.example.comÖrneğin. İşte örnek bir sunucu bloğu.

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    location / {
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_pass http://127.0.1.1:3080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Yeniden başlattıktan sonra nginx, node/ expressuygulama rotalarınızdaki IP'ye aşağıdakilerle erişebilirsiniz:req.headers['x-real-ip'] || req.connection.remoteAddress;


3

Express'e göre proxy sunucuları , doğru req.ipyapılandırdıysanız ters proxy'yi hesaba katmıştır trust proxy. Bu nedenle req.connection.remoteAddress, ağ katmanından elde edilen ve proxy'den habersiz olandan daha iyidir .


3

Bu amaçla bir paket yazdım. Hızlı ara katman yazılımı olarak kullanabilirsiniz. Paketim burada yayınlandı: https://www.npmjs.com/package/express-ip

Modülü aşağıdakileri kullanarak kurabilirsiniz:

npm i express-ip

kullanım

const express = require('express');
const app = express();
const expressip = require('express-ip');
app.use(expressip().getIpInfoMiddleware);

app.get('/', function (req, res) {
    console.log(req.ipInfo);
});

1
Sen görevde ilişkisi açıklamak zorundadır bağlı olduğunuz şeye bağlarken. Bağlantıyı açıklamazsanız spam olarak kabul edilir. İfşa açık olmalı, ancak resmi olması gerekmez (örn. Kendi kişisel içeriğiniz için: "sitemde ...", "blogumda ..." vb.). Bakınız: "İyi" kendini tanıtmanın anlamı nedir? , kendi kendine tanıtım hakkında bazı ipuçları ve öneriler , Stack Overflow için "spam" tam tanımı nedir? ve Bir şeyi spam yapan şey .
Makyen

2

Bu sorunun cevaplandığını biliyorum, ama işte benimkini böyle buldum.

let ip = req.connection.remoteAddress.split(`:`).pop();

2

3. taraf kitaplığı kullanmayı düşünüyorsanız. İstek-ip'i kontrol edebilirsiniz .

Kullanabilirsiniz

import requestIp from 'request-ip';

app.use(requestIp.mw())

app.use((req, res) => {
  const ip = req.clientIp;
});

Kaynak kodu oldukça uzun, bu yüzden buraya kopyalamayacağım, https://github.com/pbojinov/request-ip/blob/master/src/index.js adresinden kontrol edebilirsiniz.

Temel olarak,

İstekte belirli başlıklar arar ve yoksa bazı varsayılanlara geri döner.

Kullanıcı ipi aşağıdaki sıraya göre belirlenir:

  1. X-Client-IP
  2. X-Forwarded-For (Başlık birden fazla IP adresini şu biçimde döndürebilir: "istemci IP, proxy 1 IP, proxy 2 IP", bu yüzden ilkini alıyoruz.)
  3. CF-Connecting-IP (Cloudflare)
  4. Fastly-Client-Ip (Bulut işlevine geçildiğinde hızlıca CDN ve Firebase barındırma üst bilgisi)
  5. True-Client-Ip (Akamai ve Cloudflare)
  6. X-Real-IP (Nginx proxy / FastCGI)
  7. X-Cluster-Client-IP (Rackspace LB, Nehir Yatağı Vatozu)
  8. X-Forwarded, Forwarded-Forve Forwarded(# 2 Çeşitleri)
  9. req.connection.remoteAddress
  10. req.socket.remoteAddress
  11. req.connection.socket.remoteAddress
  12. req.info.remoteAddress

Bir IP adresi bulunamazsa, geri döner null.

Açıkla: Kütüphane ile ilişkili değilim.


1

Bu benim için diğerlerinden daha iyi çalıştı. Sitelerim CloudFlare'nin arkasında ve gerektiriyor gibi görünüyordu cf-connecting-ip.

req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress

Bu başlık hakkında hiçbir şey söylemediği için Express'i proxy'lerin arkasında test etmedi cf-connecting-ip.


1

Ateşleme, nginx ve x-real-ip desteği ile

var user_ip;

    if(req.headers['cf-connecting-ip'] && req.headers['cf-connecting-ip'].split(', ').length) {
      let first = req.headers['cf-connecting-ip'].split(', ');
      user_ip = first[0];
    } else {
      let user_ip = req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
    }

1

Benim durumumda, bu çözüme benzer şekilde , aşağıdaki x-forwarded-for yaklaşımını kullandım:

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

x-forwarded-forüstbilgisi, başlangıç ​​hedef sunucusuna kadar başlangıç ​​noktasından IP'nin rotasını eklemeye devam eder, böylece başlangıç ​​istemcisinin IP'sini almanız gerekirse, bu dizinin ilk öğesi olur .


0

var ip = req.connection.remoteAddress;

ip = ip.split (':') [3];


çıkış gibi: - :: ffff: XXX.XX.XX.XX bundan ip
alacağız

3
Bence ip = ip.split(':').pop();normal ip yani 127.0.0.1 gelirse bu durumda meyilli olacağını düşünüyorum Hala size ip vermek mümkün olacak.
9me

0

Headers nesnesi ihtiyacınız olan her şeye sahiptir, sadece bunu yapın:

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

0

Hepsini bir araya getirmek witk @kakopappa çözüm artı morganistemci ip adresi günlüğü:

morgan.token('client_ip', function getId(req) {
    return req.client_ip
});
const LOG_OUT = ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" :client_ip'
self.app.use(morgan(LOG_OUT, {
    skip: function(req, res) { // custom logging: filter status codes
        return res.statusCode < self._options.logging.statusCode;
    }
}));

// could-flare, nginx and x-real-ip support
var getIpInfoMiddleware = function(req, res, next) {
    var client_ip;
    if (req.headers['cf-connecting-ip'] && req.headers['cf-connecting-ip'].split(', ').length) {
        var first = req.headers['cf-connecting-ip'].split(', ');
        client_ip = first[0];
    } else {
        client_ip = req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
    }
    req.client_ip = client_ip;
    next();
};
self.app.use(getIpInfoMiddleware);
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.