Obtenha o endereço IP do cliente em socket.io

132

Ao usar o socket.IO em um servidor Node.js., existe uma maneira fácil de obter o endereço IP de uma conexão de entrada? Eu sei que você pode obtê-lo a partir de uma conexão HTTP padrão, mas o socket.io é um pouco diferente.

Toji
fonte
3
Tangente ligeira, mas console.cat (socket) pode, eventualmente, ter ajudado por recursivamente despejar tudo no objeto de soquete para o console
izb
4
@izb Bom ponto, mas console.dir(socket)pode ser o que você quis dizer
LanguagesNamedAfterCofee

Respostas:

160

Ok, a partir de 0.7.7 isso está disponível, mas não da maneira que o lubar descreve. Acabei precisando analisar alguns logs de confirmação no hub git para descobrir isso, mas o código a seguir realmente funciona para mim agora:

var io = require('socket.io').listen(server);

io.sockets.on('connection', function (socket) {
  var address = socket.handshake.address;
  console.log('New connection from ' + address.address + ':' + address.port);
});
Toji
fonte
5
Hum ... porque o dele é .connection.remoteAddress e o meu é .handshake.address?
Toji
2
@GarciadelCastillo você está atrás de um proxy provavelmente. tente isso: stackoverflow.com/a/11187053/971459
Samson:
4
Não funciona na v1.0 - apenas registra o endereço do host para mim.
Iest
1
A partir da versão 1.3.7, isso retorna::ffff:127.0.0.1
dmr07 18/11/2015
3
socket.request.connection.remoteAddresspara versão 1.x
Lukas Liesis
71

para 1.0.4:

io.sockets.on('connection', function (socket) {
  var socketId = socket.id;
  var clientIp = socket.request.connection.remoteAddress;

  console.log(clientIp);
});
flatroze
fonte
Onde você conseguiu as informações? Eu pensei que tinha lido todos os documentos para socket.io e não vi isso. Funcionou perfeitamente para resolver meus problemas semelhantes ao OP.
MikeB
1
Apenas o console.log para ver todas as informações disponíveis, acredito que ele continue mudando porque não está documentado.
Pez Cuckow
6
Na v1.2.1, socket.request.connection.remoteAddresse socket.request.connection.remotePorttrabalhe para mim. No entanto, não vi nenhuma dessas propriedades listadas quando tentei: console.log(util.inspect(socket.request.connection, {showHidden: true, colors: true})); Por que não?
Jeffrey LeCours
1
Funciona em 1.3.4 também. Graças
lima_fil
3
A partir da versão 1.3.7, isso retorna::ffff:127.0.0.1
dmr07 18/11/2015
46

Se você usar outro servidor como proxy reverso, todos os campos mencionados conterão localhost. A solução mais fácil é adicionar cabeçalhos para ip / porta no servidor proxy.

Exemplo para nginx: adicione isto após o seu proxy_pass:

proxy_set_header  X-Real-IP $remote_addr;
proxy_set_header  X-Real-Port $remote_port;

Isso disponibilizará os cabeçalhos no servidor do nó socket.io:

var ip = socket.handshake.headers["x-real-ip"];
var port = socket.handshake.headers["x-real-port"];

Observe que o cabeçalho é convertido internamente em minúsculas.

Se você estiver conectando o servidor do nó diretamente ao cliente,

var ip = socket.conn.remoteAddress;

funciona com socket.io versão 1.4.6 para mim.

zuim
fonte
5
Esta é a melhor solução, as outras respostas não funcionam se nodejs está atrás de um proxy
Alfredo Gt
2
@zuim Você é meu herói!
Flavio
20

Para a versão mais recente do socket.io, use

socket.request.connection.remoteAddress

Por exemplo:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var client_ip_address = socket.request.connection.remoteAddress;
}

tenha em atenção que o código abaixo devolve o IP do servidor, não o IP do cliente

var address = socket.handshake.address;
console.log('New connection from ' + address.address + ':' + address.port);
SlyBeaver
fonte
2
eu estava prestes a experimentar esse código de aperto de mão, obrigado por apontar que é inútil !!
precisa saber é o seguinte
1
Qual versão significa "última versão do socket.io"? Por favor, forneça uma versão específica.
Akseli Palén 19/05/19
Último para julho de 2014
SlyBeaver
8

Usando a 1.0.6versão mais recente Socket.IOe implantando meu aplicativo Heroku, obtenho o cliente IPe o portuso headersno socket handshake:

var socketio = require('socket.io').listen(server);

socketio.on('connection', function(socket) {

  var sHeaders = socket.handshake.headers;
  console.info('[%s:%s] CONNECT', sHeaders['x-forwarded-for'], sHeaders['x-forwarded-port']);

}
Balthazar
fonte
6

Desde socket.io 1.1.0, eu uso:

io.on('connection', function (socket) {
  console.log('connection :', socket.request.connection._peername);
  // connection : { address: '192.168.1.86', family: 'IPv4', port: 52837 }
}

Edit : Observe que isso não faz parte da API oficial e, portanto, não é garantido que funcione em versões futuras do socket.io.

Consulte também este link relevante: questão do engine.io

nha
fonte
1
Confirmado com 1.3.3 também.
Codesleuth
@Rachael @ Codesleuth Obrigado pela confirmação das versões, é muito apreciado. Estou recebendo alguns votos positivos, então acho que isso ainda é válido, mas ainda não testei.
nha 23/06
6

A versão 0.7.7 do Socket.IO agora afirma retornar o endereço IP do cliente. Eu tive sucesso com:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var ip_address = client.connection.remoteAddress;
}
lubar
fonte
2
seu client.conn.remoteAddress; nas versões mais recentes.
Mujtaba Kably
4

Isso parece funcionar:

var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
  var endpoint = socket.manager.handshaken[socket.id].address;
  console.log('Client connected from: ' + endpoint.address + ":" + endpoint.port);
});
Robert Larsen
fonte
1
Isso sempre retorna 127.0.0.1para mim, não o IP do cliente (o node.js é executado no servidor remoto).
Daniel W.
tente socket.request.connection.remoteAddress
Lukas Liesis
Forneça a versão Socket.io que você estava usando.
Akseli Palén 19/05/19
4

Descobri que dentro do socket.handshake.headers existe um endereço encaminhado que não aparece na minha máquina local. E consegui obter o endereço remoto usando:

socket.handshake.headers['x-forwarded-for']

Isso está no lado do servidor e não no lado do cliente.

Ufb007
fonte
1
Tudo o resto eu tentei retornou ::ffff:127.0.0.1, mas isso me deu o IP real
Steven Pothoven
amo vc, todas as outras respostas me dão loopback ip, somente esse cabeçalho funciona!
datdinhquoc
Esta é a solução para a versão mais recente [2.2.0]. Tudo o resto retornou o servidor ip para mim.
Abdul Sadik Yalcin
3

Ao ler o código-fonte socket.io, parece que o método "listen" recebe argumentos (servidor, opções, fn) e se "server" for uma instância de um servidor HTTP / S, ele simplesmente o envolverá.

Portanto, você provavelmente poderia dar a ele um servidor vazio que escute o evento 'connection' e lide com o socket remoteAddress; no entanto, as coisas podem ser muito difíceis se você precisar associar esse endereço a um objeto socket.io socket.io real.

var http = require('http')
  , io = require('socket.io');
io.listen(new http.Server().on('connection', function(sock) {
  console.log('Client connected from: ' + sock.remoteAddress);
}).listen(80));

Pode ser mais fácil enviar um patch para socket.io em que seu próprio objeto Socket é estendido com a propriedade remoteAddress atribuída no momento da conexão ...

maerics
fonte
Esse patch provavelmente será incluído na próxima versão github.com/LearnBoost/Socket.IO-node/pull/286
mak
3

Muito fácil. Coloque primeiro

io.sockets.on('connection', function (socket) {

console.log(socket);

Você verá todos os campos do soquete. use CTRL + F e procure o endereço da palavra. Finalmente, quando você encontrar o campo remoteAddress, use pontos para filtrar os dados. no meu caso é

console.log(socket.conn.remoteAddress);
geniant
fonte
Hoje eu encontrei a mesma solução em um assunto semelhante!
precisa saber é o seguinte
Isso não fornece o IP do terminal do cliente. No meu caso, apenas retorna o IP do servidor proxy reverso.
Akseli Palén 19/05/19
3

No socket.io 2.0 : você pode usar:

socket.conn.transport.socket._socket.remoteAddress

funciona com transports: ['websocket']

Chris
fonte
3

Isso funciona para a versão mais recente 2.3.0 :

io.on('connection', socket => {
   const ip = socket.handshake.headers[x-forwarded-for] || socket.conn.remoteAddress.split(":")[3];
   console.log(ip);
});
Diogo Capela
fonte
2

no socket.io1.3.4 você tem as seguintes possibilidades.

socket.handshake.address,

socket.conn.remoteAddress ou

socket.request.client._peername.address

Yaki Klein
fonte
2

Na versão v2.3.0

este trabalho para mim:

socket.handshake.headers['x-forwarded-for'].split(',')[0]
Rizuwan Intercooler
fonte
1

usar socket.request.connection.remoteAddress

DuckHunter
fonte
4
A partir da versão 1.3.7, isso retorna::ffff:127.0.0.1
dmr07 18/11/2015
1

A versão mais recente funciona com:

console.log(socket.handshake.address);
Khanasyubighi
fonte
5
A partir da versão 1.3.7, isso retorna::ffff:127.0.0.1
dmr07 18/11/2015
1.4.8 :: ffff: 10.0.0.7
Xin
1
@ dmr07 esta é a versão do IPv6. Você pode forçar o IPv4 fazendo o servidor http escutar 0.0.0.0. Relacionados: stackoverflow.com/a/37378670/5138796
darrachequesne
você pode fazer console.log (socket.handshake.address.substring (7)) ele só irá imprimir o ip 127.0.0.1
node_man
1

Bem-vindo em 2019, onde o texto datilografado domina lentamente o mundo. Outras respostas ainda são perfeitamente válidas. No entanto, eu só queria mostrar como você pode configurar isso em um ambiente digitado.

Caso você ainda não tenha. Você deve primeiro instalar algumas dependências (ou seja, a partir da linha de comando: npm install <dependency-goes-here> --save-dev)

  "devDependencies": {
    ...
    "@types/express": "^4.17.2",
    ...
    "@types/socket.io": "^2.1.4",
    "@types/socket.io-client": "^1.4.32",
    ...
    "ts-node": "^8.4.1",
    "typescript": "^3.6.4"
  }

Eu defini as importações usando as importações do ES6 (que você deve ativar tsconfig.jsonprimeiro no seu arquivo.)

import * as SocketIO from "socket.io";
import * as http from "http";
import * as https from "https";
import * as express from "express";

Como uso o texto datilografado, agora tenho digitação completa, em tudo o que faço com esses objetos.

Então, obviamente, primeiro você precisa de um servidor http:

const handler = express();

const httpServer = (useHttps) ?
  https.createServer(serverOptions, handler) :
  http.createServer(handler);

Eu acho que você já fez tudo isso. E você provavelmente já adicionou o soquete io a ele:

const io = SocketIO(httpServer);
httpServer.listen(port, () => console.log("listening") );
io.on('connection', (socket) => onSocketIoConnection(socket));

Em seguida, para o tratamento de novas conexões socket-io, você pode colocar o SocketIO.Sockettipo em seu parâmetro.

function onSocketIoConnection(socket: SocketIO.Socket) {      
  // I usually create a custom kind of session object here.
  // then I pass this session object to the onMessage and onDisconnect methods.

  socket.on('message', (msg) => onMessage(...));
  socket.once('disconnect', (reason) => onDisconnect(...));
}

E finalmente, como temos digitação completa agora, podemos recuperar facilmente o ip do soquete, sem adivinhar:

const ip = socket.conn.remoteAddress;
console.log(`client ip: ${ip}`);
bvdb
fonte
-1

No 1.3.5:

var clientIP = socket.handshake.headers.host;
Syscall
fonte
5
A partir da versão 1.3.7, isso retorna o URL da página, não o ip
dmr07 18/11/2015