Comment déterminer l'adresse IP d'un utilisateur dans le nœud

349

Comment puis-je déterminer l'adresse IP d'une demande donnée à partir d'un contrôleur? Par exemple (en express):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})
Shamoon
la source
22
Si vous utilisez Express, vous pouvez utiliser req.ip source - expressjs.com/en/api.html#req.ip
FrickeFresh
Essayez ceci: github.com/indutny/node-ip
Stephen
16
Pour ceux qui travaillent à partir de localhost- comme je l'ai fait, le résultat pour toutes les réponses ci-dessous (Presque toutes les réponses fonctionne) pourrait venir ::1. Cela m'a dérouté pendant un certain temps. Plus tard, j'ai découvert qu'il ::1s'agit de la véritable adresse IP et de la IPV6notation pour localhost. Hope this helps someone
Pramesh Bajracharya

Réponses:

452

Dans votre requestobjet, il existe une propriété appelée connection, qui est un net.Socketobjet. L'objet net.Socket a une propriété remoteAddress, donc vous devriez pouvoir obtenir l'IP avec cet appel:

request.connection.remoteAddress

Voir la documentation pour http et net

ÉDITER

Comme le souligne @juand dans les commentaires, la bonne méthode pour obtenir l'adresse IP distante, si le serveur est derrière un proxy, est request.headers['x-forwarded-for']

topek
la source
6
Cela me donne une adresse IP différente de ce que me donne whatismyip.com. Pourquoi serait-ce?
Shamoon
3
J'ai mon service API installé sur une instance no.de. Lorsque j'essaie d'y accéder depuis mon ordinateur, j'obtiens une adresse IP de "10.2.XXX.YYY" alors que mon adresse IP réelle est "67.250.AAA.BBB"
Shamoon
7
c'est request.headers ['X-Forwarded-For']
0x6A75616E
4
Notez que net.Stream est maintenant net.Socket, et la documentation se trouve ici: nodejs.org/api/net.html#net_class_net_socket
monsur
4
Pour tous ceux qui sont intéressés, pour Heroku c'est: 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);

Notez que parfois, vous pouvez obtenir plusieurs adresses IP req.headers['x-forwarded-for']. De plus, un en- x-forwarded-fortête n'est pas toujours défini, ce qui peut générer une erreur.

Le format général du champ est:

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

où la valeur est une liste d'adresses IP séparées par des virgules + espaces, la plus à gauche étant le client d'origine et chaque proxy successif ayant transmis la demande en ajoutant l'adresse IP d'où il a reçu la demande. Dans cet exemple, la demande est passée par proxy1, proxy2puis proxy3. proxy3apparaît comme adresse distante de la demande.

C'est la solution suggérée par Arnav Gupta avec un correctif que Martin a suggéré ci-dessous dans les commentaires pour les cas où x-forwarded-forn'est pas défini:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress
Edmar Miyake
la source
9
Comment empêcher l'usurpation de ces en-têtes?
Domi
8
Cela fonctionne généralement bien, mais pour une raison quelconque, j'ai récemment reçu l'erreur «Impossible de lire la propriété« remoteAddress »de non défini», car apparemment tout était nul / non défini, y compris req.connection.socket. Je ne sais pas pourquoi / quelles conditions font que cela soit le cas, mais il serait bon de vérifier qu'il req.connection.socketexiste pour éviter que votre serveur ne plante si cela se produit.
Matt Browne
9
Dernière ligne req.connection.socket.remoteAddress, erreur de lancement. Sois prudent.
yAnTar
11
L'adresse IP retournée est :: 1. Pourquoi?
Bagusflyer
3
En regardant le fonctionnement de pop (), il semble que vous obtiendrez le dernier proxy et non le client qui est ce que vous voulez. Ai-je tort?
Michel
84

Si vous utilisez express ...

req.ip

Je cherchais ça puis j'étais comme attendre, j'utilise express. Duh.

Jason Sebring
la source
Renvoie une variation de 127.0.0.1 si le serveur s'exécute derrière un proxy. Utilisez la réponse d'Edmar ou définissez x-real-ip .
Dan Dascalescu
31

Vous pouvez rester SEC et simplement utiliser un noeud-ipware qui prend en charge IPv4 et IPv6 .

Installer:

npm install ipware

Dans votre app.js ou middleware:

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

Il tentera au mieux d'obtenir l'adresse IP de l'utilisateur ou retournera 127.0.0.1pour indiquer qu'il n'a pas pu déterminer l'adresse IP de l'utilisateur. Jetez un œil au fichier README pour les options avancées.

un33k
la source
40
"ou renvoie 127.0.0.1 pour indiquer qu'il n'a pas pu déterminer l'adresse IP de l'utilisateur" Il y a une grande différence entre 127.0.0.1 et inconnue ...
Nepoxx
4
Cela m'a retourné quelque chose de bizarre :ffff:(not my IP address)lors d'un test avec Heroku. La réponse de @ edmar-miyake fonctionne correctement pour moi.
Nilloc
Je me demande quelle serait l'IP si vous utilisiez la recherche right2left dans le cas 'x-forwarded-for'. var ip_info = get_ip (req, right_most_proxy = True), comme dans certaines configurations, l'IP client peut être l'IP la plus à droite.
un33k
2
Cette méthode revient clientIp: '::1'pour moi. Cela ne semble pas fonctionner.
JamEngulfer
@JamEngulfer - ipware ne fonctionne que si l'adresse IP est correctement transmise à votre application via request.headers []. exemple: AWS LBS envoie l'adresse IP dans «x-forwarded-for» tandis que NginX personnalisé utilise de nombreuses autres variables. ipware fait la meilleure tentative pour comprendre l'adresse IP, mais uniquement si l'adresse IP a été transmise dans les en-têtes.
un33k
19

Vous pouvez utiliser request-ip pour récupérer l'adresse IP d'un utilisateur. Il gère un certain nombre de cas de bord différents, dont certains sont mentionnés dans les autres réponses.

Divulgation: j'ai créé ce module

Installer:

npm install request-ip

Dans votre application:

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

J'espère que cela t'aides

pbojinov
la source
2
en vérifiant le code source du package request-ip sur github.com/pbojinov/request-ip/blob/master/index.js, il vérifie x-forwarded-for et toutes sortes d'autres en-têtes pour les équilibreurs de charge populaires comme AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB et Riverbed's Stingray
Giorgio
1
ça revient nullpour moi.
S.M_Emamian
Utilisez la même chose à la placerequest.headers['x-forwarded-for']
Prathamesh More
19

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

Si l'en- x-forwarded-fortête est là, utilisez-le, sinon utilisez la .remoteAddresspropriété.

L'en- x-forwarded-fortête est ajouté aux demandes qui transitent par des équilibreurs de charge (ou d'autres types de proxy) configurés pour HTTP ou HTTPS (il est également possible d'ajouter cet en-tête aux demandes lors de l'équilibrage au niveau TCP à l' aide du protocole proxy ). En effet, la request.connection.remoteAddresspropriété contiendra l'adresse IP privée de l'équilibreur de charge plutôt que l'adresse IP publique du client. En utilisant une instruction OR , dans l'ordre ci-dessus, vous vérifiez l'existence d'un en- x-forwarded-fortête et l'utilisez s'il existe sinon utilisez le request.connection.remoteAddress.

Ben Davies
la source
12

La fonction suivante a tous les cas couverts aidera

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
la source
Notez que les ips sont un intermédiaire , pour moi.
ThomasReggi
8

Il existe deux façons d'obtenir l'adresse IP:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Mais il y a un problème avec les approches ci-dessus.

Si vous exécutez votre application derrière Nginx ou tout autre proxy, chaque adresse IP unique le sera 127.0.0.1.

Ainsi, la meilleure solution pour obtenir l'adresse IP de l'utilisateur est: -

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

Si vous utilisez la version express 3.x ou supérieure, vous pouvez utiliser le paramètre de proxy de confiance ( http://expressjs.com/api.html#trust.proxy.options.table ) et il parcourra la chaîne d'adresses dans l'en-tête x-forwarded-for et placez la dernière ip dans la chaîne que vous n'avez pas configurée comme proxy de confiance dans la propriété ip sur l'objet req.

Michael Lang
la source
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
la source
1
Vous avez raison, si vous voulez que l'ip soit une chaîne, vous pouvez remplacer la dernière ligne par: ip = ip.split (':'). Slice (-1) [0]
Ahmad Agbaryah
Les réponses uniquement codées sont déconseillées. Pouvez - vous expliquer comment cette réponse est meilleure que l'ancienne, mieux expliqué, et (beaucoup) plus upvoted réponses ?
Dan Dascalescu
5

Attention:

Ne vous contentez pas d'utiliser aveuglément ceci pour une limitation de débit importante:

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

Il est très facile d'usurper:

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

Dans ce cas, la véritable adresse IP de l'utilisateur sera:

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

Je suis surpris qu'aucune autre réponse n'ait mentionné cela.


la source
La première réponse gère cela en pop()ing à partir du tableau, ce qui est plus général que d'obtenir l'élément à l'index 1, qui peut être trompé par curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu
3

Si vous obtenez plusieurs IP, cela fonctionne pour moi:

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

Kirill Chatrov
la source
3

IP simple à distance dans nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
IT Vlogs
la source
3

Dans le nœud 10.14, derrière nginx, vous pouvez récupérer l'ip en le demandant via l'en-tête nginx comme ceci:

proxy_set_header X-Real-IP $remote_addr;

Puis dans votre app.js:

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

Après cela, où que vous souhaitiez qu'il apparaisse:

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

Je me rends compte que cela a été répondu à mort, mais voici une version ES6 moderne que j'ai écrite qui suit les normes eslint basées sur 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;
};

L'en-tête X-Forwarded-For peut contenir une liste d'IP proxy séparées par des virgules. La commande est client, proxy1, proxy2, ..., proxyN. Dans le monde réel, les gens implémentent des proxys qui peuvent fournir tout ce qu'ils veulent dans cet en-tête. Si vous êtes derrière un équilibreur de charge ou quelque chose, vous pouvez au moins faire confiance à la première adresse IP de la liste, au moins quel que soit le proxy qu'une demande a traversé.

Misha Nasledov
la source
1

Si vous utilisez Graphql-Yoga, vous pouvez utiliser la fonction suivante:

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
la source
1

J'utilise express derrière nginx et

req.headers.origin

a fait l'affaire pour moi

Matan Livne
la source
-7

Eu le même problème ... im aussi nouveau à javascript mais j'ai résolu cela avec req.connection.remoteAddress; cela m'a donné l'adresse IP (mais au format ipv6 :: ffff.192.168.0.101) puis .slice pour supprimer les 7 premiers chiffres.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}
aCo
la source
ce n'est pas une bonne méthode, car ipv6 n'est PAS seulement 7 chiffres + IPv4, mais peut être totalement différent.
Radek
@Radek si vous validez le début de l'adresse, elle est conforme aux spécifications (voir en.wikipedia.org/wiki/IPv6_address ctrl-f recherche de "IPv4-mapped") ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))remplacerait le if ... dans le code ci-dessus
non synchronisé
j'enveloppe personnellement getClientIp () de npm request-ip pour créer 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)); }qui accepte soit une ip précédemment récupérée, soit un objet de requête en entrée et donne ip ou undefined comme résultat
non synchronisé le