Como determinar o endereço IP de um usuário no nó

349

Como posso determinar o endereço IP de uma solicitação de dentro de um controlador? Por exemplo (em expresso):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})
Shamoon
fonte
22
Se você estiver usando Express você pode usar req.ip fonte - expressjs.com/en/api.html#req.ip
FrickeFresh
Tente isto: github.com/indutny/node-ip
Stephen Última
16
Para aqueles que estão trabalhando localhost- como eu, o resultado de todas as respostas abaixo (quase todas as respostas funcionam) pode vir ::1. Isso me deixou confuso por algum tempo. Mais tarde, descobri que ::1é o endereço IP real e é uma IPV6notação para o host local. Hope this helps someone
Pramesh Bajracharya

Respostas:

452

No seu requestobjeto, existe uma propriedade chamada connection, que é um net.Socketobjeto. O objeto net.Socket possui uma propriedade remoteAddress, portanto, você poderá obter o IP com esta chamada:

request.connection.remoteAddress

Consulte a documentação para http e net

EDITAR

Como @juand aponta nos comentários, o método correto para obter o IP remoto, se o servidor estiver atrás de um proxy, é request.headers['x-forwarded-for']

topek
fonte
6
Isso me dá um endereço IP diferente do que whatismyip.com me fornece. Por que isso seria?
Shamoon
3
Eu tenho meu serviço de API instalado em uma instância no.de. Quando tento acessá-lo de meu computador, eu obter um endereço IP de "10.2.XXX.YYY" que, se meu mundo real IP é "67.250.AAA.BBB"
Shamoon
7
it's request.headers ['X-Forwarded-For']
0x6A75616E 13/11
4
Note-se que net.Stream é agora net.Socket, ea documentação vive aqui: nodejs.org/api/net.html#net_class_net_socket
Monsur
4
Para qualquer pessoa cuja interessados, para Heroku é: 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);

Observe que às vezes você pode obter mais de um endereço IP req.headers['x-forwarded-for']. Além disso, umx-forwarded-for nem sempre cabeçalho será definido, o que pode gerar um erro.

O formato geral do campo é:

x encaminhado para: client, proxy1, proxy2, proxy3

em que o valor é uma lista de endereços IP separados por vírgula + espaço, sendo o mais à esquerda o cliente original e cada proxy sucessivo que passou na solicitação, adicionando o endereço IP de onde recebeu a solicitação. Neste exemplo, o pedido passado através de proxy1, proxy2e, em seguidaproxy3 .proxy3aparece como endereço remoto da solicitação.

Esta é a solução sugerida por Arnav Gupta com uma correção que Martin sugeriu abaixo nos comentários para casos em que x-forwarded-fornão está definido:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress
Edmar Miyake
fonte
9
Como evitar a falsificação desses cabeçalhos?
Domi 27/05
8
Isso geralmente funciona bem, mas por algum motivo recentemente recebi o erro "Não é possível ler a propriedade 'remoteAddress' of undefined" porque aparentemente tudo estava nulo / indefinido, inclusive req.connection.socket. Não sei ao certo por que / quais condições fazem com que esse seja o caso, mas seria bom verificar se req.connection.socketexiste para evitar o travamento do servidor, se isso acontecer.
Matt Browne
9
Erro de lançamento da última linha req.connection.socket.remoteAddress. Seja cuidadoso.
yAnTar
11
O endereço IP retornado é :: 1. Por quê?
Bagusflyer
3
Observando o funcionamento do pop (), parece que você obterá o último proxy e não o cliente que é o que deseja. Estou errado?
Michel
84

Se estiver usando express ...

req.ip

Eu estava procurando isso e fiquei tipo espera, estou usando express. Duh.

Jason Sebring
fonte
Retornará uma variação de 127.0.0.1 se o servidor estiver executando atrás de um proxy. Use a resposta de Edmar ou defina x-real-ip .
Dan Dascalescu
31

Você pode ficar seco e apenas usar o node-ipware que suporta IPv4 e IPv6 .

Instalar:

npm install ipware

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

Ele fará a melhor tentativa de obter o endereço IP do usuário ou retornar 127.0.0.1para indicar que não foi possível determinar o endereço IP do usuário. Dê uma olhada no arquivo LEIA - ME para obter opções avançadas.

un33k
fonte
40
"Ou retornos 127.0.0.1 para indicar que ele não pôde determinar o endereço IP do usuário" Há uma grande diferença entre 127.0.0.1 e desconhecido ...
Nepoxx
4
Ele retornou algo estranho para mim :ffff:(not my IP address)quando testado no Heroku. A resposta de @ edmar-miyake está funcionando corretamente para mim.
Nilloc
Gostaria de saber qual seria o IP se você usasse a pesquisa right2left no caso 'x-forwarded-for'. var ip_info = get_ip (req, right_most_proxy = True), como em algumas configurações, o IP do cliente pode ser o IP mais correto.
Un33k
2
Esse método está retornando clientIp: '::1'para mim. Não parece funcionar.
JamEngulfer
@JamEngulfer - o ipware funciona apenas se o endereço IP for passado corretamente para o seu aplicativo via request.headers []. exemplo: o AWS LBS envia o endereço IP em 'x-forwarded-for', enquanto o NginX personalizado usa muitas outras variáveis. O ipware faz a melhor tentativa de descobrir o endereço IP, mas somente se o IP tiver sido passado nos cabeçalhos.
un33k
19

Você pode usar request-ip , para recuperar o endereço IP de um usuário. Ele lida com vários casos de borda diferentes, alguns dos quais são mencionados nas outras respostas.

Divulgação: eu criei este módulo

Instalar:

npm install request-ip

No seu aplicativo:

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

Espero que isto ajude

pbojinov
fonte
2
verificando o código-fonte do pacote request-ip em github.com/pbojinov/request-ip/blob/master/index.js, ele verifica x-forwarded e todos os tipos de outros cabeçalhos para balanceadores de carga populares como AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB e Stingray da Riverbed
Giorgio
11
retorna nullpara mim.
S.M_Emamian
A mesma coisa em vez usarrequest.headers['x-forwarded-for']
Prathamesh Mais 24/01
19

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

Se o x-forwarded-forcabeçalho estiver lá, use-o; caso contrário, use a .remoteAddresspropriedade

O x-forwarded-forcabeçalho é adicionado às solicitações que passam pelos balanceadores de carga (ou outros tipos de proxy) configurados para HTTP ou HTTPS (também é possível adicionar esse cabeçalho às solicitações ao balancear no nível TCP usando o protocolo proxy ). Isso ocorre porque a request.connection.remoteAddresspropriedade conterá o endereço IP privado do balanceador de carga, e não o endereço IP público do cliente. Ao usar uma instrução OR , na ordem acima, você verifica a existência de um x-forwarded-forcabeçalho e o utiliza, se existir, caso contrário, use o request.connection.remoteAddress.

Ben Davies
fonte
12

A função a seguir tem todos os casos abordados, ajudará

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
fonte
Note que os ips são , intermediários para mim.
9786 ThomasReggi #
8

Existem duas maneiras de obter o endereço IP:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Mas há um problema com as abordagens acima.

Se você estiver executando seu aplicativo atrás do Nginx ou de qualquer proxy, todos os endereços IP serão 127.0.0.1.

Portanto, a melhor solução para obter o endereço IP do usuário é: -

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

Se você estiver usando a versão expressa 3.x ou superior, poderá usar a configuração do proxy de confiança ( http://expressjs.com/api.html#trust.proxy.options.table ) e ela percorrerá a cadeia de endereços em o cabeçalho x-forwarded-for e coloque o ip mais recente na cadeia que você não configurou como um proxy confiável na propriedade ip no objeto req.

Michael Lang
fonte
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
fonte
11
Você está certo, se quiser o ip como string, poderá substituir a última linha por: ip = ip.split (':'). Slice (-1) [0]
Ahmad Agbaryah
As respostas somente de código são desencorajadas. Você pode explicar como esta resposta é melhor do que o mais velho, melhor explicado, e (muito) mais upvoted respostas ?
Dan Dascalescu
5

Atenção:

Não use isso cegamente apenas para limitar a taxa de maneira importante:

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

É muito fácil falsificar:

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

Nesse caso, o endereço IP real do usuário será:

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

Estou surpreso que nenhuma outra resposta tenha mencionado isso.


fonte
A resposta topo lida com este por pop()ção a partir da matriz, o que é mais geral do que começar o elemento no índice 1, que pode ser enganado por curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu
3

Se você obtiver vários IPs, isso funcionará para mim:

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

Kirill Chatrov
fonte
3

Simples obter ip remoto no nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
Vlogs de TI
fonte
3

No nó 10.14, atrás do nginx, você pode recuperar o ip solicitando-o através do cabeçalho nginx, desta forma:

proxy_set_header X-Real-IP $remote_addr;

Em seguida, no seu app.js:

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

Depois disso, onde você quiser que ele apareça:

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

Sei que isso foi respondido até a morte, mas aqui está uma versão moderna do ES6 que escrevi que segue os padrões eslint baseados no 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;
};

O cabeçalho X-Forwarded-For pode conter uma lista separada por vírgula de IPs de proxy. O pedido é cliente, proxy1, proxy2, ..., proxyN. No mundo real, as pessoas implementam proxies que podem fornecer o que quiserem neste cabeçalho. Se você está atrás de um balanceador de carga ou algo assim, pode pelo menos confiar que o primeiro IP da lista seja pelo menos o proxy que alguma solicitação veio.

Misha Nasledov
fonte
1

Se você estiver usando o Graphql-Yoga, poderá usar a seguinte função:

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

Teve o mesmo problema ... eu também sou novo em javascript, mas eu resolvi isso com req.connection.remoteAddress; que me deu o endereço IP (mas no formato ipv6 :: ffff.192.168.0.101) e, em seguida, .slice para remover os 7 primeiros dígitos.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}
aCo
fonte
esse não é um bom método, pois o ipv6 NÃO possui apenas 7 dígitos + IPv4, mas pode ser totalmente diferente.
Radek
@Radek se você validar o início do endereço, ele está de acordo com especificação (ver en.wikipedia.org/wiki/IPv6_address pesquisa ctrl-f para "IPv4-mapeados") ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))substituiria o se ... no código acima
unsynchronized
Eu, pessoalmente, enrole getClientIp () de npm pedido-ip para criar 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)); }que aceita tanto um IP previamente obtida, ou um objeto de solicitação como entrada e dá ip ou indefinido, como resultado
não sincronizada