Timeout accessing Amazon EC2 machine from outside even with security group allowing everything - node.js

how are you?
I have a question regarding external access to my (dockerized or not) application.
I have a simple ping-pong socket communication using socket.io with the following code files:
server.js
let Server = require('socket.io')
const io = new Server().attach(8090)
io.on('connection', (socket) => {
console.log('connection')
socket.on('message', (msg) => {
console.log('< ' + msg)
console.log('> pong')
socket.emit('event', 'pong')
})
})
client.js
let host = process.argv[2]
let io = require("socket.io-client");
let client = io.connect(`http://${host}`)
let connected = false
client.on('connect', () => {
connected = true
})
client.on('event', (msg) => {
console.log('< ' + msg)
ping()
})
function ping () {
if (!connected) {
setTimeout(ping, 1000)
} else {
setTimeout(() => {
console.log('> ping')
client.emit('message', 'ping');
}, 1000)
}
}
ping()
with my server up and running, I can execute the client to test the communication like so:
$ node client.js localhost:8090
and the output is similar to this:
> ping
< pong
> ping
< pong
> ping
< pong
... and so on
Everything works normally when I test this (both client and server) outside my EC2 machine, but when I deploy the server.js to the cloud and run it, I can't reach it from outside.
When I bind a nginx web service on port 80 or 81 and proxy every request to the application, everything starts working fine from outside the cloud, but still does not work on other ports.
My security group is fully open (for testing purposes) (inbound and outbound allowing all traffic from and to anywhere (0.0.0.0/0, ::/0) on all ports) (screenshot attached).
Things that may be useful for troubleshooting:
When I try a NodeJS http server (without nginx) using node on the same port, it does not work either (works only on 80 and 81)
I am sure my machine is on the 'fully-open-insecure' security group with all traffic allowed.
My application is binding to all addresses because I can connect to it using the public address or localhost from inside the cloud machine.
It only works on port 80 and 81 when I proxy_pass connections from a nginx web server that is on the same machine as the NodeJS application
any help or troubleshooting suggestion will be very appreciated.
thank you very much for your time
Below is a screenshot with the security group definitions:

My problem was solved and this is embarrassing. My local network was not allowing outbound connections on the ports I mentioned.
If you have the same problem, I recommend to test your local network. Also, check your iptables rules

Related

Socket.IO with HTTPS over apache present?

I have a domain name.
I have a Raspberry Pi as a web-server.
I've edited domain's A record to point it to my server's IP.
Via letsencrypt I got myself a certificate and now website works on https protocol (keeping http on for debug purposes)
I'm working on a messenger app that uses socket.io but using apache+php for low level stuff
So basically apache listens to 80 and 443 and nodejs listens to 3000
Obviously if I visit my site over http - everything works fine and both server and client register connections.
If I visit it over https - Chrome throws net::ERR_CONNECTION_CLOSED error (in console when trying to connect to socket.io over port 3000. Site itself loads normally).
Client:
var socket = new io(window.location.host+":3000", { secure: true });
socket.on("connect", function() {
console.log('success')
});
Server:
const io = require("socket.io");
const server = io.listen(3000);
console.log("Server started");
server.on("connection", function (socket) {
console.log("+USER");
socket.emit("hello", "Connected");
});
I really don't want to use express or anything else for that matter to keep everything as small as possible, especially since I already have a web-server running.
How to properly set it up so users could connect to my socket.io server on port 3000 when they visit the site via https protocol?
Update:
From what it seems I think it's a CORS-thing type of a problem. User visiting website over https is trying to connect to an unsecured port (this case 3000) even though it's the same domain? I'd think that would be a no-no for a lot if not all browsers.
A solution comes to mind to just move the whole thing from apache to a nodejs server module and assign manually port 3000 as a secure one via https module but I've no idea how to do it, and I'd really want to keep my apache as a web-server because at least I'm more familiar with it than anything else.
Well I ended up creating a separate https server that I assume socket.io listens to (?)
Good thing I still have my apache as a main server. I partially answered my question using this post
https://serverfault.com/questions/745248/socket-io-combined-with-apache-ssl-server
Server
const fs = require("fs");
const https = require("https");
var options = {
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem')
};
var server = https.createServer(options);
server.listen(3000);
var io = require('socket.io').listen(server);
console.log("Server started");
io.on("connection", function (socket) {
console.log("+USER");
socket.emit("hello", "Connected");
socket.on("disconnect", () => {
console.log("-USER");
})
});
Client
var s = new io("https://example.com:3000", { secure: true } );
Hope this is the right way to do it

nodejs websockets connection from localhost works but remote doesnt

I'm running a simple websocket server in nodejs
const WebSocket = require('ws');
const wss = new WebSocket.Server({ host: '0.0.0.0', port: 13000 });
wss.on('connection', function connection(ws) {
console.log("new connection");
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.on('error', function(e) {
console.log('error', e);
});
ws.on('close', function(e) {
console.log('close', e);
});
ws.send('something');
});
I can connect to the server using:
s=new WebSocket('ws://localhost:13000')
and everything is fine. But if I try to connect from another computer:
s=new WebSocket('ws://serveripaddress:13000')
The server shows
new connection
close 1006
So I know that the client connects, but it then immediately disconnects. I am totally lost here, don't know how to diagnose my problem. Any ideas?
UPDATE
These scenarios work:
two ec2 instances: works
two linux VMs communicating over a host-only network: works
And these fail:
windows host machine and VM (host only network): fail
an ec2 instance and one of my VM's: fail
Here's the weird part, if I make a simple socket server using 'net', ALL scenarios above work! So it seems like its still a networking issue (since websockets work in some scenarios) but it is a networking issue specific to websockets (because socket server works where websocket doesnt)!
I dont have access to the firewall that my windows host machine is on so if that's the issue then I'm stuck. But I will try this all on a different host machine where I have access to the firewall.
But if it was the firewall, I would except it to work between the windows host and the VM because they are on their own virtual network...

NodeJs text file writing

I am trying to write a text file from NodeJs. I have server running on my laptop. Currently, i am running client on my laptop and it works fine. But if i run same NodeJs client on Linux running on raspberrypi, it doesn't write on file or neither it gives any error.
I have the following code for client
var ioC = require('socket.io-client'),
ioClient = ioC.connect('http://localhost:4000'),
fs = require('fs'),
os = require('os');
ioClient.on('connect', function () { console.log("socket connected"); });
ioClient.on('ChangeState', function(msg){
console.log(msg);
fs.writeFile('server.txt', JSON.stringify(msg), function (err){
if (err) return console.log(err);
});
});
Can anybody please help me what can be the issue with this?
You are connecting to localhost which won't work if the client is on a different machine. You need to change the server to listen to the ip address your server has in your network, and also need to let your client connect to this ip. You can get the ip by running ifconfig in your terminal. Then (depending on wireless or wired connection) look for something like (usually the last paragraph):
and create the server on this ip. E.g.
192.168.178.30:4000
and connect to the same address from your client.
To find your ip on windows, refer to this guide

Socket.io client doesn't connect to server

I have developed a simple chat using socket.io on a vagrant environment and it works correctly.
When I try to run the chat on the production environment, the nodejs/socket.io server runs but the client doesn't even fire the connect event.
The only thing I've modified is, in the client side:
var socket = io.connect('http://localhost:3000');
to:
var socket = io.connect('http://ip_address:3000');
This is the server code:
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
app.listen(3000, function() {
console.log('Server is running');
});
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {
socket.on('subscribe', function() {
console.log('subscribe request has arrived');
console.log(socket.id);
});
});
If it worked locally and stopped working after deployment, it's probably a network issue - firewall, blocked port, linux enforcing or something of that sort.
To find the source, go to the host server and try connecting the port
telnet 127.0.0.1 3000
Did you get 'Connection refused' error? if so which server is running the code? make sure firewall service is either off or with exceptions for port 3000. on linux check enforcing .
If the connection succeed, test the connection from your local pc
telnet ip_address 3000
If it fails than test access to external service (for example portquiz.net) This way you will know if the issue is with your local pc or network, or the remove server.

Connecting a Node JS Socket Server on Heroku to a front end client

I am having trouble getting a front end client to connect to my back end Node JS server on HEROKU. I am aware that heroku uses process.env.PORT to decide which port you can route socket traffic through, but due to the fact that my client will not be hosted on the same server I will not be able to access this ever-changing environment variable. I was wondering if there is any workaround for this problem which would let my front end client connect to my socket on Heroku without having to know the port ahead of time.
Relevent Node Code
var net = require('net');
var port = process.env.PORT || 9001
var mySocket;
var serverF = net.createServer(function(socket) {
mySocket = socket;
mySocket.on("connect", onConnect);
mySocket.on("data", onData);
});
function onConnect()
{
console.log("Connected to Flash");
}
serverF.listen(port);
function onData(d)
{
if(d == "exit\0")
{
console.log("exit");
mySocket.end();
server.close();
}
else
{
console.log(d);
mySocket.write(d, 'utf8');
}
}
I am trying to use flash as my front-end client, but I tried to simplify and wrote a basic client in node to run to isolate the problem and ran into the same issue.
This is a continuation of an ongoing problem I have that can be found here: https://stackoverflow.com/questions/32601186/creating-a-socket-server-with-nodejs-on-heroku-with-flash-as-the-client
No, you can not just "know" where it's running. You can, however set up a central registry somewhere with the port information listed. sort of a service registry 'lite'.
Just publish a static site somewhere with the port information, then request that static source first. Once you've parsed the info there, you're good to go.
Or, if you have the resources, set up a reverse proxy somewhere that will always be available, and that you can use to change your dynamic back-end.

Resources