148

When using socket.IO in a Node.js server, is there an easy way to get the IP address of an incoming connection? I know you can get it from a standard HTTP connection, but socket.io is a bit of a different beast.

Nic
  • 6,211
  • 10
  • 46
  • 69
Toji
  • 33,927
  • 22
  • 105
  • 115

22 Answers22

169

Okay, as of 0.7.7 this is available, but not in the manner that lubar describes. I ended up needing to parse through some commit logs on git hub to figure this one out, but the following code does actually work for me now:

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);
});
Preview
  • 35,317
  • 10
  • 92
  • 112
Toji
  • 33,927
  • 22
  • 105
  • 115
  • +1 thanks mate, do you perhaps know how i could get the remote address - or rather originating address? Right now its just logging the forward off my router. – cillierscharl Oct 09 '11 at 18:46
  • 6
    Um... because his is .connection.remoteAddress and mine is .handshake.address? – Toji Apr 10 '12 at 18:38
  • And still working at 0.9.13 I'm getting the IP with socket.handhsake.address.address with no problems. Thank you! – Riwels Jan 16 '13 at 20:06
  • It's yielding me the client's local lan address. – GarciadelCastillo May 13 '13 at 23:11
  • 2
    @GarciadelCastillo you are behind a proxy probably. try this: http://stackoverflow.com/a/11187053/971459 – Samson Jun 25 '13 at 09:30
  • 5
    Does not work in v1.0 — it just logs the address of the host for me. – Iest Aug 24 '14 at 11:23
  • this is the only thing that's worked for me, io v0.9 - logs client's web IP – RozzA Sep 20 '14 at 00:48
  • 1
    As of version `1.3.7`, this returns `::ffff:127.0.0.1` – dmr07 Nov 18 '15 at 22:08
  • In version 1.3.7 this works great. I am using this to track reconnects as i keep track of my own sockets myself. socket.request.connection.remoteAddress works until the device stops responding and then it goes to undefined. Also damn07 is getting a loopback address whether he uses either approach which likely means he is testing the system locally – Pljeskavica Nov 25 '15 at 22:33
  • 3
    `socket.request.connection.remoteAddress` for 1.x version – Lukas Liesis Nov 18 '16 at 23:23
  • `socket.conn.transport.socket._socket.remoteAddress` for 2.0 – Chris' Aug 28 '17 at 22:19
  • 4
    I tried this on my local PC, But i receive `New connection from undefined:undefined` – S.Sakthybaalan Aug 10 '18 at 11:31
79

for 1.0.4:

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

  console.log(clientIp);
});
Preview
  • 35,317
  • 10
  • 92
  • 112
flatroze
  • 871
  • 7
  • 3
  • Where did you get the info? I thought I had read all the docs for socket.io and did not see this. It worked perfectly to solve my problems similar to the OP. – MikeB Jun 13 '14 at 18:42
  • 1
    Just console.log socket to view all of the available information, I believe it keeps changing because it's not documented. – Pez Cuckow Jun 19 '14 at 09:04
  • 6
    In v1.2.1, `socket.request.connection.remoteAddress` and `socket.request.connection.remotePort` work for me. However, I didn't see either of these properties listed when I tried: `console.log(util.inspect(socket.request.connection, {showHidden: true, colors: true}));` Why not? – Jeffrey LeCours Dec 15 '14 at 02:49
  • 1
    Works in 1.3.4 also. Thanks – lima_fil Feb 15 '15 at 21:15
  • And what error is this, can you please explain? TypeError: Cannot read property 'connection' of undefined Is this the version issue? My socket version is 0.9.11 My code is: io.sockets.on('connection', function (socket) { var socketId = socket.id var clientIp = socket.request.connection.remoteAddress console.log(clientIp) – Sanjay Mar 02 '15 at 10:47
  • 3
    As of version `1.3.7`, this returns `::ffff:127.0.0.1` – dmr07 Nov 18 '15 at 22:10
  • In version 1.3.7 socket.request.connection.remoteAddress will work intermittently. It will go undefined if the device stops responding. I am using this to check whether the device reconnects as I track all my own sockets to keep them organized by the group that is connecting. But I switched my code to use socket.handshake.address and it works great for this use. – Pljeskavica Nov 25 '15 at 22:29
  • Working for me perfectly. – Akash Agarwal Mar 29 '16 at 19:00
61

If you use an other server as reverse proxy all of the mentioned fields will contain localhost. The easiest workaround is to add headers for ip/port in the proxy server.

Example for nginx: add this after your proxy_pass:

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

This will make the headers available in the socket.io node server:

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

Note that the header is internally converted to lower case.

If you are connecting the node server directly to the client,

var ip = socket.conn.remoteAddress;

works with socket.io version 1.4.6 for me.

zuim
  • 1,039
  • 8
  • 10
23

For latest socket.io version use

socket.request.connection.remoteAddress

For example:

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

beware that the code below returns the Server's IP, not the Client's IP

var address = socket.handshake.address;
console.log('New connection from ' + address.address + ':' + address.port);
Preview
  • 35,317
  • 10
  • 92
  • 112
SlyBeaver
  • 1,272
  • 12
  • 22
9

Using the latest 1.0.6 version of Socket.IO and have my app deployed on Heroku, I get the client IP and port using the headers into the 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']);

}
Preview
  • 35,317
  • 10
  • 92
  • 112
9

This works for the 2.3.0 version:

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

Since socket.io 1.1.0, I use :

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

Edit : Note that this is not part of the official API, and therefore not guaranteed to work in future releases of socket.io.

Also see this relevant link : engine.io issue

Preview
  • 35,317
  • 10
  • 92
  • 112
nha
  • 17,623
  • 13
  • 87
  • 133
  • 1
    Confirmed with 1.3.3 also. – Codesleuth Feb 07 '15 at 12:55
  • @Rachael @ Codesleuth Thanks for the confirmation for the versions, it is much appreciated. I'm getting a few upvotes so i guess this is still valid, but I haven't tested myself. – nha Jun 23 '15 at 10:17
6

Version 0.7.7 of Socket.IO now claims to return the client's IP address. I've had success with:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var ip_address = client.connection.remoteAddress;
}
Preview
  • 35,317
  • 10
  • 92
  • 112
lubar
  • 2,589
  • 2
  • 26
  • 28
4

Very easy. First put

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

console.log(socket);

You will see all fields of socket. then use CTRL+F and search the word address. Finally, when you find the field remoteAddress use dots to filter data. in my case it is

console.log(socket.conn.remoteAddress);
Preview
  • 35,317
  • 10
  • 92
  • 112
geniant
  • 117
  • 2
  • 10
4

I have found that within the socket.handshake.headers there is a forwarded for address which doesn't appear on my local machine. And I was able to get the remote address using:

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

This is in the server side and not client side.

Ufb007
  • 243
  • 2
  • 8
4

In version v2.3.0

this work for me :

socket.handshake.headers['x-forwarded-for'].split(',')[0]
4

This seems to work:

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
  • 1,018
  • 2
  • 11
  • 18
3

on socket.io 1.3.4 you have the following possibilities.

socket.handshake.address,

socket.conn.remoteAddress or

socket.request.client._peername.address

Yaki Klein
  • 3,978
  • 3
  • 37
  • 34
3

In socket.io 2.0: you can use:

socket.conn.transport.socket._socket.remoteAddress

works with transports: ['websocket']

Chris'
  • 13,624
  • 1
  • 15
  • 14
3

From reading the socket.io source code it looks like the "listen" method takes arguments (server, options, fn) and if "server" is an instance of an HTTP/S server it will simply wrap it for you.

So you could presumably give it an empty server which listens for the 'connection' event and handles the socket remoteAddress; however, things might be very difficult if you need to associate that address with an actual socket.io Socket object.

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

Might be easier to submit a patch to socket.io wherein their own Socket object is extended with the remoteAddress property assigned at connection time...

maerics
  • 151,642
  • 46
  • 269
  • 291
  • This patch will most likely be included in the next release https://github.com/LearnBoost/Socket.IO-node/pull/286 – mak Jun 25 '11 at 08:46
3

I went through blog posts and even peoples answers to the question.

I tried socket.handshake.address and it worked but was prefixed with ::ffff:

I had to use regex to remove that.

This works for version 4.0.1

socket.conn.remoteAddress
Joel
  • 487
  • 6
  • 8
2

Welcome in 2019, where typescript slowly takes over the world. Other answers are still perfectly valid. However, I just wanted to show you how you can set this up in a typed environment.

In case you haven't yet. You should first install some dependencies (i.e. from the commandline: 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"
  }

I defined the imports using ES6 imports (which you should enable in your tsconfig.json file first.)

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

Because I use typescript I have full typing now, on everything I do with these objects.

So, obviously, first you need a http server:

const handler = express();

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

I guess you already did all that. And you probably already added socket io to it:

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

Next, for the handling of new socket-io connections, you can put the SocketIO.Socket type on its parameter.

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

And then finally, because we have full typing now, we can easily retrieve the ip from our socket, without guessing:

const ip = socket.conn.remoteAddress;
console.log(`client ip: ${ip}`);
bvdb
  • 22,839
  • 10
  • 110
  • 123
2

Here's how to get your client's ip address (v 3.1.0):


// Current Client
const ip = socket.handshake.headers["x-forwarded-for"].split(",")[1].toString().substring(1, this.length);
// Server 
const ip2 = socket.handshake.headers["x-forwarded-for"].split(",")[0].toString();

And just to check if it works go to geoplugin.net/json.gsp?ip= just make sure to switch the ip in the link. After you have done that it should give you the accurate location of the client which means that it worked.

Fus_ion
  • 41
  • 6
1

use socket.request.connection.remoteAddress

DuckHunter
  • 91
  • 1
  • 6
1

Latest version works with:

console.log(socket.handshake.address);
SZ4
  • 61
  • 2
  • 9
1

for my case

i change my

app.configure(socketio)

to

app.configure(socketio(function(io) {
 io.use(function (socket, next) {
   socket.feathers.clientIP = socket.request.connection.remoteAddress;
   next();
 });
}));

and i'm able to get ip like this

function checkIP() {
  return async context => {
    context.data.clientIP = context.params.clientIP
  }
}

module.exports = {
  before: {
    all: [],
    find: [
      checkIp()
    ]}
  }
Chung Fei
  • 11
  • 1
-1

In 1.3.5 :

var clientIP = socket.handshake.headers.host;
Syscall
  • 19,327
  • 10
  • 37
  • 52