I create a TCP IVP4 socket server in Node.js using the 'net' module, and it works great for almost all of my clients, but one client has an IP similar to (I won't disclose the real one):
180.190.154.97
but when they connect to my socket server and I console.log(socket.remoteAddress), the value is this:
180.190.193.2
Why would this be happening?
// Import dependencies
let net = require('net')
// Create socket server.
const SERVER = net.createServer(socketConnection)
function socketConnection(client) {
console.log(client.remoteAddress)
}
// Server code snippet
let SERVER_LISTEN_ADDRESS = '0.0.0.0'
if (Game.local) {
SERVER_LISTEN_ADDRESS = '127.0.0.1'
Game.port = 42480
}
SERVER.listen(Game.port, SERVER_LISTEN_ADDRESS, () => {
console.log('Listening on port ' + Game.port)
if (!Game.local)
postServer()
else
console.log('Running server locally.')
})
Expected result is that it should print their IPV4 value from a site like:
https://whatismyipaddress.com/
But instead it says something completely different.
The result shown by whatipmyaddress it is not always the public IP of the single host. It could be rather also the IP of the subnet or if there's a proxy the IP of the proxy server. The fact that the address differs by a few units suggests that those particular hosts are in a subnet where a NAT service is active, or protected by a proxy or where the router acts as a VPN to the outside, encapsulating and sending the message to the server. In this case probably the entire subnet is seen as a single host.
In case you're using Express, you may want to use request-ip package in order to retrieve the IP in a more robust way. Since it seems you're not using express you should implement something similar to the first example shown in the link. For your specific case according the code you give:
const requestIp = require('request-ip');
function socketConnection(client) {
const clientIp = requestIp.getClientIp(client);
console.log(client);
}
Related
When starting an http server in Node.js, developers can listen on a randomly available port by passing 0 like so:
const http = require('http')
const service = require('../my/service);
const server = http.createServer(service)
server.listen(process.env.PORT || 0) // <-- Random port by default!
I wonder how I can do the same thing with gRPC? Something like...
const grpc = require('grpc')
const services = require('./service_grpc_pb')
const server = new grpc.Server()
server.addService(services.MyService, { ... })
server.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure())
server.start()
Does that work? I've yet to find out. My goal is to get a random port and then query the server to get the assigned port in order to register the service with a central microservice registry.
Thanks for your help in advance.
Yes, you can use a port number of 0 to assign a random port to a gRPC server. The server.bind method returns the port number that was actually assigned. If you want to use the bindAsync method instead, the assigned port number will be passed to the callback.
This question already has answers here:
How do I host multiple Node.js sites on the same IP/server with different domains?
(13 answers)
Closed 4 years ago.
I would like to create a system of multiple web applications (probably around 3-5 node.js + express applications) on one server. I also only have one domain. So I figured that I need to create subdomains for each of my application apart from the main one.
My question is - how do I redirect users coming to certain subdomains to the right application? Do I need to use virtual machines and then redirect each user to a different VM (ip address) depending on their subdomain? How would I even do that?
Or could I just run every application on the same server just with a different port number? Or is there any other way that I'm not really thinking of?
Which way would be the cleanest and how would I implement it?
A very common way to achieve this is to run each of your node servers on a different port, and then set up a reverse proxy like nginx to have it forward requests based on matching the host header of incoming HTTP requests.
You could of course handle this manually with node, by checking the host header yourself and forwarding each request to the proper node server on the associated port.
Here is some Node code which illustrates what I'm referring to:
const http = require('http')
const url = require('url')
const port = 5555
const sites = {
exampleSite1: 544,
exampleSite2: 543
}
const proxy = http.createServer( (req, res) => {
const { pathname:path } = url.parse(req.url)
const { method, headers } = req
const hostname = headers.host.split(':')[0].replace('www.', '')
if (!sites.hasOwnProperty(hostname)) throw new Error(`invalid hostname ${hostname}`)
const proxiedRequest = http.request({
hostname,
path,
port: sites[hostname],
method,
headers
})
proxiedRequest.on('response', remoteRes => {
res.writeHead(remoteRes.statusCode, remoteRes.headers)
remoteRes.pipe(res)
})
proxiedRequest.on('error', () => {
res.writeHead(500)
res.end()
})
req.pipe(proxiedRequest)
})
proxy.listen(port, () => {
console.log(`reverse proxy listening on port ${port}`)
})
I'm in the process of trying to get an application which I'd built on the old OpenShift Online 2 free service up and running on the new OpenShift Online 3 Starter, and I'm having a bit of trouble.
The application uses websocket, and in the old system all that was required was for the client to connect to my server on port 8443 (which was automatically routed to my server). That doesn't seem to work in the new setup however - the connection just times out - and I haven't been able to find any documentation about using websocket in the new system.
My first thought was that I needed an additional rout, but 8080 is the only port option available for routing as far as I can see.
The app lives here, and the connection is made on line 21 of this script with the line:
this.socket = new WebSocket( 'wss://' + this.server + ':' + this.port, 'tabletop-protocol' );
Which becomes, in practice:
this.socket = new WebSocket( 'wss://production-instanttabletop.7e14.starter-us-west-2.openshiftapps.com:8443/', 'tabletop-protocol' );
On the back end, the server setup is unchanged from what I had on OpenShift 2, aside from updating the IP and port lookup from env as needed, and adding logging to help diagnose the issues I've been having.
For reference, here's the node.js server code (with the logic trimmed out):
var http = require( "http" );
var ws = require( "websocket" ).server;
// Trimmed some others used by the logic...
var ip = process.env.IP || process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var port = process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 8080;
/* FILE SERVER */
// Create a static file server for the client page
var pageHost = http.createServer( function( request, response ){
// Simple file server that seems to be working, if a bit slowly
// ...
} ).listen( port, ip );
/* WEBSOCKET */
// Create a websocket server for ongoing communications
var wsConnections = [];
wsServer = new ws( { httpServer: pageHost } );
// Start listening for events on the server
wsServer.on( 'request', function( request ){
// Server logic for the app, but nothing in here ever gets hit
// ...
} );
In another question it was suggested that nearly anything - including this -
could be related to the to the ongoing general issues with US West 2, but other related problems I was experiencing seem to have cleared, and that issue has been posted for a week with no update, so I figured I'd dig deeper into this on the assumption that it's something I'm doing wrong instead of them.
Anyone know more about this and what I need to do to make it work?
I am using socket.io for a project that requires me to stream live data to a browser. Now the server part is fine, but on socket.io client io.connect() call, I have had a few problems in the past, without proper resolution. I have tried the usual suspects, but I am not getting through.
My client call to looks like this:
var socket = io.connect('http://10.95.xx.xx:5002');
where 10.95. .. is the IP address of the server on the LAN. Using this IP I can access the server from inside the LAN, on any machine in the LAN, but this doesn't work from outside the LAN. Problem being, most probably, that this IP is for LAN only and not the public IP. As per university's network settings, the public IP is 128.95 ...and if I change it to this IP, then it will be accessible from outside, but not from inside.
One way to resolve this, is that I try to read the client's IP address and based on that decide the parameter IP. But this doesn't feel robust. Also, I tried using io.connect("/") . It had worked for me in previous circumstance, but it did not this time. Also, the empty call did not work io.connect() did not work.
As you said you can use the clients IP address, this here always worked for me:
var port = window.location.port,
host = window.location.hostname,
protocol = window.location.protocol,
path = '/',
url,
options = { };
if( protocol.indexOf( 'https' ) > -1 ) {
protocol = 'wss:';
} else {
protocol = 'ws:'
}
url = protocol + "//" + host + ":" + port + path;
options = { };
/*
// If you wanted to add an access token, "Session" is where I store this
if( Session.token ) {
options.query = 'access_token=' + Session.token;
}
*/
socket = io( url, options );
I have requirement where my NodeJS http server (on Windows) has to listen on the hostname instead of localhost/127.0.0.1.
For this I need the full hostname (including the domain name) of my Windows machine and I am not able to get the full hostname.
I tried using
require('os').hostname()
but it does not give me the full hostname.
So I tried the below:
var dns = require('dns');
var os = require('os');
var hostname = os.hostname();
console.log("Short hostname = ", hostname);
dns.lookup(hostname, function (err, add, fam) {
if (err)
{
console.log("The error = ", JSON.stringify(err));
return;
}
console.log('addr: '+add);
console.log('family: ' + fam);
dns.reverse(add, function(err, domains){
if (err)
{
console.log("The reverse lookup error = ", JSON.stringify(err));
return;
}
console.log("The full domain name ", domains);
});
})
The above code works fine and I get the below output when I am on the ethernet of my enterprise
C:\>node getFullHostname.js
Short hostname = SPANUGANTI
addr: 16.190.58.214
family: 4
The full domain name [ 'spanuganti.abc.xyz.net' ]
But the same code does not work when I am connected to the wireless network of the enterprise
C:\>node getFullHostname.js
Short hostname = SPANUGANTI
addr: 16.183.204.47
family: 4
The reverse lookup error =
{"code":"ENOTFOUND","errno":"ENOTFOUND","syscall":"getHostByAddr"}
So need help on the below
Is there a simple way to get the full machine name (Windows) in Node.js
Or please let me know what is the problem with my code above
Servers don't listen on hostnames, they listen on IP addresses. You should never rely on the contents of the external DNS to figure out where to bind.
The easiest solution is to have it bind to the INADDR_ANY address, which is numerically equivalent to 0.0.0.0.
This would then allow queries on any interface, including the loopback.
You don't need the full hostname to listen on, you actually need your IP address. Check out the os.networkInterfaces() function.