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

22
Jeśli używasz Express, możesz użyć req.ip źródła - expressjs.com/en/api.html#req.ip
FrickeFresh


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']


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

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


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.


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


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.


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

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;

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.


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
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.


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


3

Prosty dostęp do zdalnego IP w nodejs:

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

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;

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.


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
}


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.