Jak ustalić adres IP użytkownika w węźle

349

Jak mogę ustalić adres IP danego żądania z poziomu kontrolera? Na przykład (ekspresowo):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})
Shamoon
źródło
22
Jeśli używasz Express, możesz użyć req.ip źródła - expressjs.com/en/api.html#req.ip
FrickeFresh
Spróbuj tego: github.com/indutny/node-ip
Stephen Last
16
Dla tych, którzy pracują localhost- tak jak ja, wynik dla wszystkich odpowiedzi poniżej (Prawie wszystkie odpowiedzi działają) ::1. Przez pewien czas byłem zdezorientowany. Później okazało się, że ::1jest to prawdziwy adres IP i jest IPV6notacją dla hosta lokalnego. Hope this helps someone
Pramesh Bajracharya

Odpowiedzi:

452

W twoim requestobiekcie znajduje się właściwość o nazwie connection, która jest net.Socketprzedmiotem. Obiekt net.Socket ma właściwość remoteAddress, dlatego powinieneś być w stanie uzyskać adres IP za pomocą tego wywołania:

request.connection.remoteAddress

Zobacz dokumentację dla http i net

EDYTOWAĆ

Jak wskazuje @juand w komentarzach, poprawną metodą uzyskania zdalnego adresu IP jest serwer za serwerem proxy request.headers['x-forwarded-for']

topek
źródło
6
To daje mi adres IP inny niż whatismyip.com. Dlaczego miałoby to być?
Shamoon
3
Mam moją usługę API zainstalowaną w instancji no.de. Kiedy próbuję uzyskać do niego dostęp z mojego komputera, otrzymuję adres IP „10.2.XXX.YYY”, podczas gdy mój rzeczywisty adres IP to „67.250.AAA.BBB”
Shamoon,
7
to request.headers ['X-Forwarded-For']
0x6A75616E
4
Zauważ, że net.Stream jest teraz net.Socket, a dokumentacja znajduje się tutaj: nodejs.org/api/net.html#net_class_net_socket
monsur
4
Dla wszystkich zainteresowanych, dla Heroku jest to: 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);

Pamiętaj, że czasami możesz uzyskać więcej niż jeden adres IP req.headers['x-forwarded-for']. Ponadto x-forwarded-fornagłówek nie zawsze będzie ustawiony, co może spowodować błąd.

Ogólny format pola to:

x-forwarded-for: client, proxy1, proxy2, proxy3

gdzie wartością jest lista adresów IP oddzielona przecinkami i spacjami, skrajnie lewy to klient oryginalny, a każdy kolejny serwer proxy, który przekazał żądanie, dodał adres IP, z którego otrzymał żądanie. W tym przykładzie, żądanie przepuszcza proxy1, proxy2i potem proxy3. proxy3pojawia się jako zdalny adres żądania.

Jest to rozwiązanie sugerowane przez Arnava Gupta z poprawką zaproponowaną przez Martina w komentarzach w przypadkach, gdy x-forwarded-fornie jest ustawione:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress
Edmar Miyake
źródło
9
Jak jednak zapobiec fałszowaniu tych nagłówków?
Domi
8
Zwykle działa to dobrze, ale z jakiegoś powodu ostatnio pojawił się błąd „Nie można odczytać właściwości„ remoteAddress ”niezdefiniowanej”, ponieważ najwyraźniej wszystko było puste / niezdefiniowane, w tym req.connection.socket. Nie jestem pewien, dlaczego / jakie warunki powodują, że tak jest, ale dobrze byłoby sprawdzić, czy req.connection.socketistnieje, aby uniknąć awarii serwera, jeśli tak się stanie.
Matt Browne
9
Ostatni wiersz wymagający połączenia.socket.remote Błąd zgłaszania adresu. Bądź ostrożny.
yAnTar
11
Zwrócony adres ip to: 1. Dlaczego?
Bagusflyer
3
Patrząc na sposób działania pop (), wygląda na to, że dostaniesz ostatni serwer proxy, a nie klienta, który jest tym, czego chcesz. Czy się mylę?
Michel
84

Jeśli używasz ekspresowego ...

req.ip

Patrzyłem na to, a potem czułem się, używam ekspresu. Duh.

Jason Sebring
źródło
Zwróci odmianę 127.0.0.1, jeśli serwer działa za serwerem proxy. Użyj odpowiedzi Edmara lub ustaw x-real-ip .
Dan Dascalescu
31

Możesz pozostać SUCHY i po prostu użyć węzła ipware, który obsługuje zarówno IPv4, jak i IPv6 .

Zainstalować:

npm install ipware

W pliku app.js lub oprogramowaniu pośrednim:

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

Podejmie najlepszą próbę uzyskania adresu IP użytkownika lub zwróci, 127.0.0.1aby wskazać, że nie może określić adresu IP użytkownika. Spójrz na plik README , aby uzyskać zaawansowane opcje.

un33k
źródło
40
”lub zwraca 127.0.0.1, aby wskazać, że nie może określić adresu IP użytkownika” Istnieje dość duża różnica między 127.0.0.1 a nieznanym ...
Nepoxx
4
W :ffff:(not my IP address)testach z Heroku zwróciło mi to coś dziwnego . Odpowiedź @ edmar-miyake działa dla mnie poprawnie.
Nilloc,
Zastanawiam się, jaki byłby adres IP, gdybyś użył odnośnika right2left w przypadku „x-forwarded-for”. var ip_info = get_ip (req, right_most_proxy = True), ponieważ w niektórych konfiguracjach adres IP klienta może być najodpowiedniejszym adresem IP.
un33k
2
Ta metoda wraca clientIp: '::1'do mnie. Wydaje się, że to nie działa.
JamEngulfer
@JamEngulfer - ipware działa tylko wtedy, gdy adres IP jest poprawnie przekazywany do Twojej aplikacji za pośrednictwem request.headers []. przykład: AWS LBS wysyła adres IP w 'x-forwarded-for', podczas gdy niestandardowe NginX wielu używa innych zmiennych. ipware podejmuje najlepszą próbę ustalenia adresu IP, ale tylko wtedy, gdy adres IP został przekazany w nagłówkach.
un33k
19

Możesz użyć request-ip , aby uzyskać adres IP użytkownika. Obsługuje wiele różnych przypadków krawędzi, z których niektóre są wymienione w innych odpowiedziach.

Ujawnienie: Stworzyłem ten moduł

Zainstalować:

npm install request-ip

W Twojej aplikacji:

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

Mam nadzieję że to pomoże

pbojinov
źródło
2
sprawdzanie kodu źródłowego pakietu request-ip na github.com/pbojinov/request-ip/blob/master/index.js sprawdza x-forwarded-for i wszelkiego rodzaju innych nagłówków dla popularnych równoważników obciążenia, takich jak AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB i Riverbed's Stingray
Giorgio
1
wraca nullpo mnie.
S.M_Emamian
To samo zamiast tego użyjrequest.headers['x-forwarded-for']
Prathamesh More
19

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

Jeśli x-forwarded-fornagłówek tam jest, użyj go, w przeciwnym razie użyj .remoteAddresswłaściwości.

x-forwarded-forNagłówek zostanie dodany do wniosków, które przechodzą przez równoważenia obciążenia (lub innych rodzajów proxy) utworzonych przez HTTP lub HTTPS (jest to również możliwe, aby dodać nagłówek do żądania podczas równoważenia na TCP poziomie stosując protokół proxy ). Wynika to z faktu, że request.connection.remoteAddresswłaściwość będzie zawierać prywatny adres IP modułu równoważenia obciążenia, a nie publiczny adres IP klienta. Za pomocą instrukcji OR w powyższej kolejności sprawdzasz, czy istnieje x-forwarded-fornagłówek i używasz go, jeśli istnieje, użyj request.connection.remoteAddress.

Ben Davies
źródło
12

Funkcja Follow ma wszystkie uwzględnione przypadki, które pomogą

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
źródło
Zauważ, że IP są , dla mnie pośrednie.
ThomasReggi,
8

Istnieją dwa sposoby uzyskania adresu IP:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Ale istnieje problem z powyższymi podejściami.

Jeśli korzystasz z aplikacji za Nginx lub innym serwerem proxy, każdy adres IP będzie taki 127.0.0.1.

Tak więc najlepszym rozwiązaniem do uzyskania adresu IP użytkownika jest: -

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
Mansi Teharia
źródło
6

Jeśli używasz ekspresowej wersji 3.x lub nowszej, możesz użyć ustawienia proxy zaufania ( http://expressjs.com/api.html#trust.proxy.options.table ), a on przejdzie przez łańcuch adresów w nagłówek x-forwarded-for i umieść najnowszy adres IP w łańcuchu, który nie został skonfigurowany jako zaufany serwer proxy we właściwości ip na obiekcie żądania.

Michael Lang
źródło
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
źródło
1
Masz rację, jeśli chcesz ip jako ciąg znaków, możesz zastąpić ostatni wiersz: ip = ip.split (':'). Slice (-1) [0]
Ahmad Agbaryah
Odpowiedzi zawierające tylko kod są odradzane. Czy potrafisz wyjaśnić, w jaki sposób ta odpowiedź jest lepsza od starszych, lepiej wyjaśnionych i (znacznie) bardziej pozytywnych odpowiedzi ?
Dan Dascalescu
5

Ostrzeżenie:

Nie używaj tego na ślepo do ważnego ograniczenia prędkości:

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

Bardzo łatwo jest sfałszować:

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

W takim przypadku prawdziwy adres IP użytkownika będzie:

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

Dziwię się, że żadne inne odpowiedzi o tym nie wspominały.


źródło
Top odpowiedź robi sobie z tym poradzić przez pop()ing z tablicy, która jest bardziej ogólne niż uzyskanie elementu o indeksie 1, który można nabrać przez curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu
3

Jeśli otrzymasz wiele adresów IP, działa to dla mnie:

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

Kirill Chatrov
źródło
3

Prosty dostęp do zdalnego IP w nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
Vlogi IT
źródło
3

W węźle 10.14, za nginx, możesz odzyskać ip, żądając go poprzez nagłówek nginx w następujący sposób:

proxy_set_header X-Real-IP $remote_addr;

Następnie w pliku app.js:

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

Następnie, gdziekolwiek ma się pojawiać:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;
Alexandru
źródło
2

Zdaję sobie sprawę, że odpowiedź na to pytanie została podjęta na śmierć, ale oto nowoczesna wersja ES6, którą napisałem, która jest zgodna ze standardem eslint bazy airbnb.

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

Nagłówek X-Forwarded-For może zawierać rozdzieloną przecinkami listę adresów IP serwerów proxy. Zamówienie to klient, proxy1, proxy2, ..., proxyN. W prawdziwym świecie ludzie wdrażają serwery proxy, które mogą dostarczać wszystko, co chcą w tym nagłówku. Jeśli masz za sobą moduł równoważenia obciążenia lub coś takiego, możesz przynajmniej zaufać, że pierwszy adres IP na liście to przynajmniej to proxy, przez które wpłynęło jakieś żądanie.

Misza Nasledow
źródło
1

Jeśli używasz Graphql-Yoga, możesz użyć następującej funkcji:

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
źródło
-7

Miałem ten sam problem ... jestem również nowy w javascript, ale rozwiązałem to za pomocą req.connection.remoteAddress; co dało mi adres IP (ale w formacie ipv6 :: ffff.192.168.0.101), a następnie .slice, aby usunąć 7 pierwszych cyfr.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}
aCo
źródło
nie jest to dobra metoda, ponieważ ipv6 NIE jest tylko 7 cyframi + IPv4, ale może być zupełnie inny.
Radek
@Radek, jeśli potwierdzisz początek adresu, jest zgodny ze specyfikacją (patrz en.wikipedia.org/wiki/IPv6_address ctrl-f wyszukiwanie „IPv4-mapped”) ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))zastąpiłby if ... w powyższym kodzie
niezsynchronizowany
ja osobiście zawijam getClientIp () z npm request-ip, aby utworzyć, 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)); }który przyjmuje jako dane wejściowe poprzednio pobrany ip lub obiekt żądania i daje ip lub niezdefiniowany w wyniku
niezsynchronizowany