Find out private ip when using node / socket.io? - node.js

Currently my socket.io chat app only allows 1 user per ip, which means if two people in the same house or net want to use the chat, only one of them will be able to.
Is there a way to find out what private ip a user has, besides it's public ip which i already know?

Assuming your chat app is Javascript that runs in a browser, then "No", there is no way for your server to know what the private IP address is of the end-user. If your chat app was a native app, then your native chat app could fetch the local private IP address and send it to the server. But, that can't be done from a browse without native code plug-ins.
The browser does not provide a way for Javascript to obtain the private IP address so there is no way for your chat app to send it to your server. And, there is certainly no way for the server to know the private IP address all by itself.
You can use cookies to detect multiple chat windows in the same browser open at once (cookie the first connection, then look for any other incoming connections with the same cookie). But, you cannot prevent multiple browsers using that scheme.
The usual way to deal with this is to require an account and login to that account and enforce only one login per account at a time and to require unique email addresses or even verified credit card numbers per account to discourage people making lots of accounts. Of course, there are still ways around this too (multiple email boxes or multiple credit cards), but it's enough of an obstacle to stop many and prevent large scale abuse. In general, you should design your service so if someone does this, it frankly isn't a problem.

Related

Is there a RIGHT approach for securing data further by doing an IP match?

So here is an approach I was thinking of:
PROBLEM:
- after you have done everything possible to secure your servers and client app. I wanted to add an extra layer to make sure even if a user looses access to their data, they can only really affect their own little space in a shared database. (obvisouly authentications are in place but this is the basis of the authenticatino model)
SOLUTION I HAD IN MIND:
- I wanted to add a "hidden" field that stores users IP addresses.
This means when a user does the normal password and usenrame entry, they also have to verify whether the machine they are using is their own, and thus we store that IP address by taking it from their request.
Later if they need to log in again they can, but if they want to retrieve data, the look up on the router server will recieve the IP from the request, add that onto the message as part of the filter parameters.
Once it queries the database if the combination of IP + data that users wants is found then it sends that back.
If a different IP is detected then no data exists in the server so nothing is sent back. which would initially be done on login and would trigger a mail to the user to verify the machine they are using is trusted.
Is there an easier way? is this overegging?
Thanks,
Alex
Tried ip-request module in Express, works fine, but wanted to know if there was a potential security threat with the way I am using this and it will be implemented before proceding.
First off, an IP address your server sees is often not the actual IP address of the computer the user is on because there is often a NAT device or proxy in between that maps a private network IP address of the user's machine to a public IP address for use on the internet. This would be true whether you were using a computer on your home network, using a computer at work, connected via WiFi at Starbucks, etc...
User Computer (private IP 192.168.1.x) => Gateway (some public IP address) => Your server
If the same computer connected to your server the same way over and over, it "might" be assigned the same public IP address every time it does so. But, in other circumstances it might not.
If the same computer is mobile at all (phone, laptop, tablet) and connects to the internet in different ways (WiFi, cellular), then it may show as a different IP address every time it connects from a different location.
So, in these days of lots of mobile devices and a user that may even access a service from more than one device, an IP address is just NOT a good measure of whether this is a risk or not.
Furthermore, in the case of shared NAT such as a WiFi hotshot or connecting from a corporate network, it's possible for lots of different users to all appear to be coming from the same public IP address.
I would not suggest using IP address at all as any security indicator. You will just get lots of false indicators of an invalid IP address that changed since last access and you may even get false positives where a different user appears on the same IP address as a legit user. In these days of NAT and mobility, there is no one-to-one correspondence between a public IP address and a user. Trying to pretend there is will cause all sorts of problems.

How to get incoming request ip address using .net Core

I deployed my .NET CORE solution in AZURE environment (PAAS).I used following code snippet there to get client's ip address
dtoItem.LogIP = HttpContext.Connection.RemoteIpAddress.ToString();
I used standard .net core libraries and did necessary changes into Startup.cs as well
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false,
});
I believe I have implemented everything in correct manner. But still I haven't got accurate client IP address. I am always getting client's public IP instead of his private IP. Since this can be repeated (Same office 2 users have same public IP) I need client's private IP instead of his public IP.
Is it possible to get private IP address in PAAS solution. If it is not possible, is there a way to track client's PC information. (Such as IP Address, MAC address).
Is it possible to get private IP address in PAAS solution?
No it is not possible as shared in this SO post and this answer address this about MACAddress
On the client side javascript, there is no API exposed to get the IPAddress(obviously due to security consideration) .Then you can get the IPAddress on the server side but typically if you are accessing internet from your company,it would go through the corporate proxy and the Ipaddress seen by the server will never be the actual client IP but the proxy server's address. So this is limited on the server side as server only sees the proxy (public IP address).
If it is not possible, is there a way to track client's PC information. (Such as IP Address, MAC address) ?
What you can reliably track is the user agent. Breaking the user agent down, we get the some information about browser ,OS versions. But user agent can easily be spoofed with some browser extension .
If you are looking for browser finger printing or tracking ,have a
look at Panopticlick which shows some more information like
fonts > installed, screen resolution,plugins installed etc to track
any client. fingerprintjs2 javascript library helps to track
using 26 parameters as of today
There is no straight forward answer to this. The thread shared by Rob has some great insights. However, one needs to understand that a lot can happen to the request before it reaches the server. The intermediary networking devices can manipulate the TCP headers so it may not reflect the correct IP Address that you need.
From a solution perspective, this might be perfectly possible, if you develop your own client and log this information somewhere so that you can track it. Otherwise there is no reliable way to get this information.

Security about creating a server on client side on the fly

I have a security question about games and network.
Today most games (like Call of Duty) uses a 'on client side host' server system. So for some time, one client becomes the host of the game. I'm looking for some resources on how to do this properly (in a technical and safe way) because I'm working on a project like that.
But for now the only solution I found is to share the IP address of my host clients to other guest clients. And I'm not proud of this. So I am looking for a method or technology like IP masking or another stuff like that would protect my customers from other malicious customers that could retrieve IP of my customers and maybe hack them?
EDIT:
But what I'm asking is if there is any solution like services like on the fly subdomains redirections with parameters for connecting to specific clients or anything like that? I mean
subdomain.mygame.com/clientname
If you want true peer-to-peer connections in your game there is no way around sharing the IP address. After all if they are to talk with one another then they need to know how to reach the others.
Alternatively you can route all their traffic through your server and each client connects to it independently. That way they do not have to know any information about each other except your in-game user id.

WebSocket thru Amazon ELB or directly (remote IP issue)

We use WebSockets to communicate with our EC2 instances.
Our script is served using nodejs and Express, and then initialize the WebSocket.
Right now ELB is used which makes life harder to identify the client IP.
Using x-forwarded-for header we can get the IP in the context of HTTP, but when it comes to WebSocket context in the server, it looks like it's not forwarded by Amazon.
We identified 2 options:
Communicate the WebSocket directly with the instance (using its public DNS).
Maintain some sort of sessionid, in which store the IP when in the context of HTTP and associate it with the sessionid. The client side will get its sessionid using the HTTP response, and will use it to on the WebSockets. The the server will be to identify the client and resolve its IP from the cache.
Both options are not great: 1 is not fault tolerant and 2 is complex.
Are there more solutions? Can Amazon somehow forward the IP? What is the best practice?
Thanks
I have worked with websockets and I have worked with ELB, but I've never worked with them together, so I didn't realize that an HTTP forwarder on an Elastic Load Balancer doesn't understand websocket requests...
So I take it you must be using a TCP forwarder, which explains why you're using a different port, and of course the TCP forwarder is protocol-unaware, so it won't be adding any headers at all.
An option that seems fairly generic and uncomplicated would be for the http side of your application to advise the websocket side by pushing the information across rather than storing it in a cache for retrieval. It's scalable and lightweight, assuming there's not an obstacle in your environment that makes it difficult or impossible to implement.
While generating the web page that loads the websocket, take the string "ipv4:" and the client's IP ("192.168.1.1," for example), concatenate and encrypt them, and make the result url-friendly:
/* pseudo-code */
base64_encode(aes_encrypt('ipv4:192.168.1.1','super_secret_key'))
Using that example key with 128 bit aes and that example IP address, I get:
/* actual value returned by pseudo-code above */
1v5n2ybJBozw9Vz5HY5EDvXzEkcz2A4h1TTE2nKJMPk=
Then when rendering the html for the page containing the websocket, dynamically build the url:
ws = new WebSocket('ws://example.com/sock?client=1v5n2ybJBozw9Vz5HY5EDvXzEkcz2A4h1TTE2nKJMPk=');
Assuming the querystring from the websocket is accessible to your code, you could base64_decode and then aes_decrypt the string found in the query parameter "client" using the super-secret key, and then verify that it begins with "ipv4:" ... if it doesn't, then it's not a legitimate value.
Of course, "ipv4:" (at the beginning of the string) and "client" (for the query parameter) were arbitrary choices and do not have any actual significance. My choice of 128 bit AES was also arbitrary.
The problem, of course, with this setup is that it is subject to a replay: a given client IP address will always generate the same value. If you only using the client IP address for "informational purposes" (such as logging or debugging) then this may be sufficient. If you are using it for anything more significant, you may want to expand this implementation -- for example, by adding a timestamp:
'ipv4:192.168.1.1;valid:1356885663;'
On the receiving end, decode the string and check the timestamp. If it is not +/- whatever interval in seconds that you deem safe, then don't trust it.
These suggestions all hinge on your ability to dynamically generate the websocket url, the browser's ability to connect with it, and you being able to access the querystring portion of the URL in the websocket request... but if those pieces will fall into place, maybe this will help.
Additional thoughts (from comments):
The timestamp I suggested, above, is seconds from the epoch, which gives you an incrementing counter that requires no statefulness in your platform -- it only requires that all of your server clocks are correct -- so it doesn't add unnecessary complexity. If the decrypted value contains a timestamp less than (for example) 5 seconds different (+/-) from the server's current time, then you know you're dealing with an authenticated client. The time interval permitted only needs to be as long as the maximum reasonable time for a client to attempt its websocket connection after loading the original page, plus the maximum skew of all your server clocks.
It is true, of course, that with NAT, multiple different users could be behind the same source IP address. It's also true, though far less less likely, that a user could actually make the websocket connection from a different source IP than the one where they originated the first http connection, and still be quite legitimate... and it sounds like the identity of the authenticate user may be a more important value for you than the actual source IP.
If you include the authenticated user's ID within the encrypted string as well, you have a value that is unique to origin IP, user account, and time, to a precision of 1 second. I think this is what you're referring to by additional salt. Adding the user account to the string should get you the information you're wanting.
'ipv4:192.168.1.1;valid:1356885663;memberid:32767;'
TLS should prevent discovery of the this encrypted string by an unauthorized party, but avoidance of replayability is also important because the generated URL is available in clear text in a user's browser's "view source" for the html page. You don't want a user who is authorized today but unauthorized tomorrow to be able to spoof their way in with a signed string that should be recognized as no longer valid. Keying to a timestamp and requiring it to fall in a very small valid window prevents this.
It depends on how serious the application is.
Basing any kind of decision on client IP address is a risky proposition. Basing security on it, even more so. While the suggestions offered so far work well within the given constraints, it would not be sufficient for a robust enterprise application.
Client IP addresses can be obscured by NATs, as already pointed out. So people accessing the Web from their place of work will often appear to have the same IP address. People's routers at home act as a NAT, so every family member at home accessing the Web will appear to the have the same IP address. Or even the same person accessing the application from a PC and a tablet...
Whether behind a NAT or not, using the application from two browsers on the same machine will appear to the have the same address. Similarly, multiple tabs in the same browser will appear to have the same address.
Other junction points like proxies or load balancers may also hide the original client IP address such that the thing behind the proxy/load balancers thinks they are the client. (More sophisticated or lower level intermediaries can prevent this, which is what makes them more sophisticated or expensive.)
Given all of the above, a serious application should not rely on client IP address for any kind of important decision, especially around security.

P2P using web browser

I've been told that some torrent sites like BITLET or MININOVA allow you to download from other users, and obviously other users to download from you while you have your browser open.
I would like to create something similar for a game, where:
1. User A and B are connected to a specific website
2. User A knows the IP and port of B
3. User A starts downloading some information from user B
Could anyone give me some tips or keywords to start?
Thanks!
Your game would have to be written as a browser plugin since browsers don't support this kind of thing. It looks like BITLET uses java, which would work, or FLASH 10 also supports socket connections so that would be another alternative. You'd probably want to have a central server to keep track of what different peers are available. Each client could connect to the server, get a list of clients, then create tcp socket connections to each client it wants to connect to. Each client could then additionally tell each other about other clients, and so on.

Resources