Uzyskaj adres IP klienta w socket.io

133

Używając socket.IO na serwerze Node.js, czy istnieje łatwy sposób na uzyskanie adresu IP połączenia przychodzącego? Wiem, że możesz to uzyskać ze standardowego połączenia HTTP, ale socket.io to trochę inna bestia.

Toji
źródło
3
Nieznaczna styczna, ale console.cat (gniazdo) mogła prawdopodobnie pomóc, rekurencyjnie zrzucając wszystko z obiektu gniazda na konsolę
izb
4
@izb Słuszna uwaga, ale console.dir(socket)może o to chodziło
LanguagesNamedAfterCofee

Odpowiedzi:

161

OK, od wersji 0.7.7 jest to dostępne, ale nie w sposób opisany przez Lubar. Skończyło się na tym, że musiałem przeanalizować niektóre dzienniki zatwierdzeń w git hub, aby to zrozumieć, ale następujący kod faktycznie teraz działa dla mnie:

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
źródło
5
Um ... ponieważ jego to .connection.remoteAddress, a mój to .handshake.address?
Toji,
2
@GarciadelCastillo prawdopodobnie znajdujesz się za proxy. spróbuj tego: stackoverflow.com/a/11187053/971459
Samson,
4
Nie działa w wersji 1.0 - po prostu loguje dla mnie adres hosta.
Ostatni
1
Począwszy od wersji 1.3.7, to powraca::ffff:127.0.0.1
dmr07
3
socket.request.connection.remoteAddressdla wersji 1.x
Lukas Liesis
73

dla 1.0.4:

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

  console.log(clientIp);
});
flatroze
źródło
Skąd masz informacje? Myślałem, że przeczytałem wszystkie dokumenty dotyczące socket.io i nie widziałem tego. Zadziałało idealnie, aby rozwiązać moje problemy podobne do OP.
MikeB
1
Wystarczy gniazdo console.log, aby wyświetlić wszystkie dostępne informacje. Myślę, że to się zmienia, ponieważ nie jest udokumentowane.
Pez Cuckow
6
W wersji 1.2.1 socket.request.connection.remoteAddressi socket.request.connection.remotePortpracuj dla mnie. Jednak gdy próbowałem, nie widziałem żadnej z tych właściwości: console.log(util.inspect(socket.request.connection, {showHidden: true, colors: true})); Dlaczego nie?
Jeffrey LeCours
1
Działa również w 1.3.4. Dzięki
lima_fil,
3
Od wersji 1.3.7zwraca to::ffff:127.0.0.1
dmr07
50

Jeśli używasz innego serwera jako zwrotnego proxy, wszystkie wymienione pola będą zawierać localhost. Najłatwiejszym sposobem obejścia tego problemu jest dodanie nagłówków adresu IP / portu na serwerze proxy.

Przykład dla nginx: dodaj to po proxy_pass:

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

Spowoduje to udostępnienie nagłówków na serwerze węzła socket.io:

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

Zauważ, że nagłówek jest wewnętrznie konwertowany na małe litery.

Jeśli łączysz serwer węzła bezpośrednio z klientem,

var ip = socket.conn.remoteAddress;

działa z socket.io w wersji 1.4.6 dla mnie.

zuim
źródło
5
To jest najlepsze rozwiązanie, inne odpowiedzi nie działają, jeśli nodejs jest za proxy
Alfredo Gt
2
@zuim Ty panie, jesteś moim bohaterem!
Flavio
20

Aby uzyskać najnowszą wersję socket.io, użyj

socket.request.connection.remoteAddress

Na przykład:

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

uważaj, poniższy kod zwraca adres IP serwera, a nie klienta

var address = socket.handshake.address;
console.log('New connection from ' + address.address + ':' + address.port);
SlyBeaver
źródło
2
właśnie miałem wypróbować ten kod uścisku dłoni, dziękuję za wskazanie, że jest bezużyteczny !!
RozzA
1
Jaką wersję rozumie się przez „ostatnią wersję socket.io”? Proszę podać konkretną wersję.
Akseli Palén
Najnowsze na lipiec 2014
SlyBeaver
8

Korzystając z najnowszej 1.0.6wersji Socket.IOi mam wdrożoną aplikację Heroku, otrzymuję klienta IPi portużywam headersgo w 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
źródło
6

Od socket.io 1.1.0 używam:

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

Edycja : Zwróć uwagę, że nie jest to część oficjalnego interfejsu API, a zatem nie ma gwarancji, że będzie działać w przyszłych wydaniach socket.io.

Zobacz także ten odpowiedni link: problem z engine.io

nha
źródło
1
Potwierdzone również w 1.3.3.
Codesleuth
@Rachael @ Codesleuth Dzięki za potwierdzenie wersji, jest to bardzo cenne. Dostaję kilka głosów za, więc myślę, że jest to nadal ważne, ale nie testowałem siebie.
nha
6

Wersja 0.7.7 Socket.IO twierdzi teraz, że zwraca adres IP klienta. Odniosłem sukces z:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var ip_address = client.connection.remoteAddress;
}
lubar
źródło
2
jego client.conn.remoteAddress; w nowszych wersjach.
Mujtaba Kably
4

To wydaje się działać:

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
źródło
1
To zawsze zwraca 127.0.0.1za mnie, a nie adres IP klienta (node.js działa na serwerze zdalnym).
Daniel W.
spróbuj socket.request.connection.remoteAddress
Lukas Liesis
Podaj używaną wersję Socket.io.
Akseli Palén
4

Odkryłem, że w pliku socket.handshake.headers jest plik przekierowany adres, który nie pojawia się na moim komputerze lokalnym. I udało mi się uzyskać zdalny adres za pomocą:

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

Jest to po stronie serwera, a nie klienta.

Ufb007
źródło
1
Wszystko inne, czego próbowałem, wróciło, ::ffff:127.0.0.1ale to dało mi rzeczywisty adres IP
Steven Pothoven
kocham cię, wszystkie inne odpowiedzi dają mi pętlę ip, tylko ten nagłówek działa!
datdinhquoc
To jest rozwiązanie dla najnowszej wersji [2.2.0]. Wszystko inne zwróciło mi IP serwera.
Abdul Sadik Yalcin,
3

Po odczytaniu kodu źródłowego socket.io wygląda na to, że metoda „Listen” pobiera argumenty (serwer, opcje, fn) i jeśli „serwer” jest instancją serwera HTTP / S, po prostu ją za ciebie zapakuje.

Można więc przypuszczalnie dać mu pusty serwer, który nasłuchuje zdarzenia „connection” i obsługuje gniazdo remoteAddress; Jednak sytuacja może być bardzo trudna, jeśli trzeba skojarzyć ten adres z rzeczywistym obiektem gniazda socket.io.

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

Może być łatwiejsze przesłanie poprawki do socket.io, w którym ich własny obiekt Socket jest rozszerzony o właściwość remoteAddress przypisaną w czasie połączenia ...

maerics
źródło
Ta poprawka najprawdopodobniej zostanie uwzględniona w następnym wydaniu github.com/LearnBoost/Socket.IO-node/pull/286
mak
3

Bardzo łatwe. Pierwsze włożenie

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

console.log(socket);

Zobaczysz wszystkie pola gniazda. następnie użyj CTRL + F i wyszukaj słowo adres. Wreszcie, gdy znajdziesz pole remoteAddress, użyj kropek do filtrowania danych. w moim przypadku tak

console.log(socket.conn.remoteAddress);
genialny
źródło
Dziś znalazłem to samo rozwiązanie w podobnej sprawie!
Filippo1980,
To nie daje adresu IP punktu końcowego klienta. W moim przypadku po prostu zwraca adres IP odwrotnego serwera proxy.
Akseli Palén
3

W socket.io 2.0 : możesz użyć:

socket.conn.transport.socket._socket.remoteAddress

pracuje z transports: ['websocket']

Chris
źródło
3

Działa to dla najnowszej wersji 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
źródło
2

w socket.io1.3.4 masz następujące możliwości.

socket.handshake.address,

socket.conn.remoteAddress lub

socket.request.client._peername.address

Yaki Klein
źródło
2

W wersji v2.3.0

ta praca dla mnie:

socket.handshake.headers['x-forwarded-for'].split(',')[0]
Rizuwan Intercooler
źródło
1

posługiwać się socket.request.connection.remoteAddress

DuckHunter
źródło
4
Począwszy od wersji 1.3.7, zwraca to::ffff:127.0.0.1
dmr07
1

Najnowsza wersja współpracuje z:

console.log(socket.handshake.address);
Khanasyubighi
źródło
5
Od wersji 1.3.7zwraca to::ffff:127.0.0.1
dmr07
podobny 1.4.8 :: ffff: 10.0.0.7
Xin
1
@ dmr07 to jest wersja IPv6. Możesz wymusić IPv4, powodując, że serwer HTTP nasłuchuje 0.0.0.0. Związane z: stackoverflow.com/a/37378670/5138796
darrachequesne
możesz zrobić console.log (socket.handshake.address.substring (7)), po prostu wydrukuje
adres
1

Witamy w 2019 roku, kiedy maszynopis powoli przejmuje świat. Inne odpowiedzi są nadal całkowicie aktualne. Chciałem jednak tylko pokazać, jak można to ustawić w środowisku pisania.

Na wypadek, gdybyś jeszcze tego nie zrobił. Najpierw należy zainstalować pewne współzależności (czyli z linii poleceń: 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"
  }

Zdefiniowałem import za pomocą importu ES6 (który powinieneś najpierw włączyć w swoim tsconfig.jsonpliku).

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

Ponieważ używam maszynopisu, mam teraz pełne pisanie na wszystkim, co robię z tymi obiektami.

Więc oczywiście najpierw potrzebujesz serwera http:

const handler = express();

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

Chyba już to wszystko zrobiłeś. I pewnie już dodałeś do niego gniazdo io:

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

Następnie, w celu obsługi nowych połączeń typu socket-io, możesz umieścić SocketIO.Sockettyp w jego parametrze.

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

I wreszcie, ponieważ mamy teraz pełne wpisywanie, możemy łatwo pobrać ip z naszego gniazda, bez zgadywania:

const ip = socket.conn.remoteAddress;
console.log(`client ip: ${ip}`);
bvdb
źródło
-1

W 1.3.5:

var clientIP = socket.handshake.headers.host;
Syscall
źródło
5
Od wersji 1.3.7zwraca to adres URL strony, a nie adres IP
dmr07