443 apache SSL Port and 8888 https listening Port doesn't work - Node.js - socket.io - node.js

currently i have the following problem:
i have an apache server, running SSL on Port 443 and standard (http) on 80.
Additionally a installed a Node.js server with socket.io module.
I wrote an socket.io javascript with a http server that listened to the port 3000, so in the client (browser) i include the socket.io.js like this
<script type="text/javascript" src="http://www.example.com:3000/socket.io/socket.io.js"></script>
This works very fine, when i execute my site via http://www.example.com . The browser finds the socket.io.js properly.
If i execute my site via https like https://www.example.com , i adjust the script part above like this:
<script type="text/javascript" src="https://www.example.com:8888/socket.io/socket.io.js"></script>
I changed the src to https:// and the port to 8888. Now i have to adapt my socket.io script also.
var https = require('https');
var fs = require('fs');
var socketio = require('socket.io');
// The server options
var svrPort = 8888; // This is the port of service
var svrOptions = {
key: fs.readFileSync('/path/to/example.key'),
cert: fs.readFileSync('/path/to/example-ca.crt'),
ca: fs.readFileSync('/path/to/example-server.pem')
};
// Create a Basic server and response
var servidor = https.createServer( svrOptions , function( req , res ){
res.writeHead(200);
res.end('Hi! Code here...');
});
// Create the Socket.io Server over the HTTPS Server
io = socketio.listen( servidor );
// Now listen in the specified Port
servidor.listen( svrPort );
If i execute the file with node, the socket.io started properly:
info - socket.io started
But here comes the problem: if i execute the URL of the socket.io.js file in the browser, nothing happens:
https://www.example.com:8888/socket.io/socket.io.js
Firefox answers with: data communication interrupted
The node server also gets no requests. socket.io doesn't react.
What i have to do?
Thx!

There are two js scripts needed here, one for the node.js server (I assume that is the one you posted) and one embedded in the html page.
The <source> Tag has nothing to do with the execution of your node.js server script. It states where the client will download the client js script, when loading your HTML page. It therefore needs to be downloadable from your browser - just try entering that URL yourself.
The address, where the client side of the socket.io code is receiving its content (the address of the node.js Server) must be updated in the client side js.
Depending on the size of your project, why not also use node.js as the only server for the static content?

Related

Setting up react and nodejs servers on same machine

I am setting up a reactjs application on port 3000 as well as a nodejs API server on port 3500 on the same box on the internet. Assume the box has a domain name example.com, and I am using nginx in reverse proxy to receive the end users over https, and internally direct it to the port 3000 of the reactjs server.
On the react code, while calling axios API for a get command, which of the following should I be using:
localhost:3500
http://localhost:3500
https://localhost:3500
example.com:3500
http://example.com:3500
https://example.com:3500
Few tests I did:
Access from my browser the reactjs application successfully as example.com (nginx does the mapping to port 3000)
Using https://reqbin.com/ I was able to access the nodejs server API and get the correct result using: http://example.com:3500/users
Using https instead of http causes an error: SSL connection error Error code: 10035
If end user is supposed to connect over https to the react server, then the react server as well as the nodejs server should be running in https mode, or the browser will block the request and it will never reach the server.
Here is how to:
Run the react server in https mode:
Change nginx reverse proxy configuration to be:
proxy_pass https://localhost:3000;
Changed the URL for the nodejs server that axios is calling from http://localhost:3500 to https://example.com:3500
After npm run build, and upload the build directory to the server, run the following commands:
su
serve -s build --listen 3000 --ssl-cert "/etc/letsencrypt/live/example.com/fullchain.pem" --ssl-key "/etc/letsencrypt/live/example.com/privkey.pem"
Run the nodejs server in https mode:
Change the code of server.js with the following:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem')
};
https.createServer(options, app).listen(PORT, ()=>{
console.log(`Server running https on port ${PORT}`)
});
Run the following commands:
su
node server

Socket.io client not connecting

I have a Socket.io server running on port 3000 and when running it (and the website / client) locally everything works fine. But when I push it to the server the client can't connect anymore.
The production server is running over SSL so I assumed that I need the Socket.io server to run over SSL as well. I've setup it up like this:
var app = express();
var fs = require('fs');
var is_production = process.env.NODE_ENV === 'production';
if(is_production){
var options = {
key: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/cert.pem'),
requestCert: true
};
var server = require('https').createServer(options, app);
}else{
var server = require('http').createServer(app);
}
var io = require('socket.io')(server);
server.listen(3000);
This still doesn't work. I don't have much experience with Socket.io so any help would be appreciated. Also note that everything worked fine before I got an SSL certificate setup on the web server.
The client is connecting to ws://mywebsite.com:3000. I've tried using http://, https:// and wss:// as well, but nothing works.
EDIT: I've tried making a request through curl and I get the following error:
curl: (35) gnutls_handshake() failed: The TLS connection was non-properly terminated.
I couldn't figure out what the problem was, so here's what I did.
I have Nginx running on the same server to serve my website so what I ended up doing was configuring Nginx to proxy all SSL connections to port 3000 and forward them to the node.js server running on port 8080. This way Nginx takes care of the SSL so the node.js server doesn't need any additional configuration.

socket.io cannot communicate with back-end through express

I am using socket.io for fetching some data from the express app. Everything works fine on localhost:8080 but when i deploy my code to the server, client side socket.io cannot communicate with back-end socket.io through express server. I've an apache on the server that forwards everything to localhost:8080 including domain.com/socket.io/?transform=polling... and it extends the request to the express server but express returns a 404 (it comes from the express, not from apache). I am out of ideas, what could be the problem? Here is my code:
express = require "express"
jade = require "jade"
fs = require "fs"
class Bootstrap
_self = undefined
routes:
DEFAULT_PATH: "/"
TEMPLATE_PATH: "/load/:view"
DIRECTIVE_PATH: "/directive/:template"
options:
templatePath: "#{__dirname}/../src/templates"
isDev: "#{__dirname}/../dev"
contentPath: "#{__dirname}/../frontend"
libraryPath: "#{__dirname}/../bower_components"
port: 8080
status:
notFound: 404
isDev: undefined
constructor: ->
_self = #
#isDev = fs.existsSync #options.isDev
#app = express()
#app.use "/frontend", express.static(#options.contentPath)
#app.use "/bower_components", express.static(#options.libraryPath)
#app.set "views", #options.templatePath
#app.set "view engine", "jade"
#app.engine "jade", jade.__express
#app.get #routes.DEFAULT_PATH, (request, response)->
appData =
data:
isDev: _self.isDev
response.render "index", appData
#app.get #routes.TEMPLATE_PATH, (request, response)->
view = request.param "view"
response.render view
#app.get #routes.DIRECTIVE_PATH, (request, response)->
template = request.param("template").replace ".html", ""
response.render "directives/"+template
#app.use (request, response, next)->
_self.logger.warning "404 Not Found!: " + request.originalUrl
response.status(_self.options.status.notFound)
appData =
data:
isDev : _self.isDev
request: request
response.render "404", appData
#server = #app.listen #options.port
#io = require("socket.io").listen #server
#logger = require("./logger.js")
#logger.init #isDev
#socketConnector = require("./live.js")
#socketConnector.init #io
#
new Bootstrap()
You can find the entire code here: https://github.com/eyurdakul/ejder.be
Since you specifically said it works locally and I don't see anything special in your code, I really think the issue resides in your Apache config.
There is a module called mod_proxy_wstunnel you need to have and enable in order to get your WebSocket traffic to work and get proxied correctly to your express application. Either you have Apache 2.4 or, you'll need to apply this patch found in this blogpost and compile again. There is also another blog detailing step by step what you should do under Ubuntu.
After making sure you have the module and its loaded, you'll have to tweak your config to add some WebSocket proxying using the ProxyPass directive
ProxyRequests Off
ProxyPass "/socket-io/" "ws://localhost:8080/socket.io/"
ProxyPassReverse "/socket-io/" "ws://localhost:8080/socket.io/"
You might also want to try to use a rewrite condition on the Upgrade header that is sent with WebSockets:
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteRule /(.*) ws://localhost:8000/$1 [P,L]
ProxyPass / http://localhost:8000/
has seen in this comment or this specific thread in general, which exposes a few other possible solutions you can try.
A debugging step that you should take is to have a mock client run in your express app and try to connect to the server port using localhost, or whatever the loopback IP address is. In other words (purely as a temporary testing tool) you place a socket.io Node client into your Express app that gets instantiated and immediately tries to connect to the Socket.io server (which is also in the express app). This should work.
If it does work, you've established that your express server is not the problem. Then, on the client you just added to your express app, you should change the connection address from the local IP to the actual IP address of the server.
If it doesn't work, your problem is probably server side.
My guess is that your apache server is forwarding the polling requests properly, but when Socket.io tries to make the handoff to websockets, Apache is denying the WS request and socket.io is handling this denial internally -- which is why the 404 seems to come from express.
Even I had same issue. The port on which the server is listening , is that open on server. As on local all the ports are open but on server , it's not the case.

Running a forward proxy server in nodejitsu using node js

I am new to proxy server. What I want to do is: I want to write some node.js code, and then upload to my nodejitsu account to run as a proxy server. Then I would like to use my nodejitsu proxy server on my computer, by configuring the http proxy as "abc.jit.su" (my jitsu URL), and the port as "80" in Chrome, Firefox or IE. That's to say, I want my nodejitsu proxy server to have the same function as the proxies listed here: http://www.freeproxylists.net/. Any ideas?
You can write a simple proxy using the request module, like this:
var http = require('http'),
request = require('request');
// For nodejitsu, this will be port 80 externally
var port = process.env.PORT || 8000;
http.createServer(function(req,res) {
req.pipe(request(req.url)).pipe(res)
}).listen(port);
However, this will only work with http, not https.
Nodejitsu also produces a proxy module, you may get some ideas on what to do next by looking at that.

Installing SSL Certificate On Node Server

I created a self-signed certificate and installed it on apache as well as on node.js(port 3000). On localhost both https://localhost and https://localhost:3000 works well.
So, I bought GoDaddy Standard SSL certificate and installed it on the server(http://gatherify.com). Now https://gatherify.com works well, but ssl on node isn't working.
When I access https://gatherify.com:3000 i get "The connection was interrupted".
I executed curl:
root#host [~]# curl -v -s -k https://gatherify.com:3000
* About to connect() to gatherify.com port 3000 (#0)
* Trying 108.160.156.123... connected
* Connected to gatherify.com (108.160.156.123) port 3000 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* warning: ignoring value of ssl.verifyhost
* NSS error -5938
* Closing connection #0
* SSL connect error
Any suggestions to fix this?
UPDATE
*SERVER SIDE :*
var io = require('socket.io'),
connect = require('connect'),
fs = require('fs'),
var privateKey = fs.readFileSync('cert/server.key').toString();
var certificate = fs.readFileSync('cert/server.crt').toString();
var options = {
key: privateKey,
cert: certificate
};
var app = connect(options).use(connect.static('../htdocs/node/'));
app.listen(3000);
var server = io.listen(app);
server.sockets.on('connection', function(socket) {
console.log("Connected");
});
CLIENT SIDE:
<html> <head>
<script type = "text/javascript" src = "https://gatherify.com:3000/socket.io/socket.io.js"></script>
<script type = "text/javascript">
var socket = io.connect('https://gatherify.com:3000', {secure:true});
</script>
</head><body></body></html>
If you want to run a node.js app on port 3000 with (behind) HTTPS, then you need to set up a proxy service on port 443 to proxy HTTPS requests to port 3000.
You didn't mention what server you have running on port 443 right now (is it Apache?) but you might want to
move that service to a new port (e.g. 4000), then run a node http proxy on port 443 that handles HTTPS.
Then set up a subdomain for the node.js app that you have running on port 3000 (e.g. blah.gatherify.com).
Then, using node http proxy, you will proxy all requests that are made to "gatherify.com" to port 4000, and all requests that are made to "blah.gatherify.com" to port 3000.
When all is set up properly, users can visit "https://gatherify.com" or "https://blah.gatherify.com" (without using :port numbers) and it'll all be secured with SSL. ;)
Install certificates Client Side (in Node.js)
If you need a node.js client to be able to recognize your self-assigned or cheaply-bought SSL certificates you can use ssl-root-cas, which is available on npm.
'use strict';
var https = require('https')
, cas
;
// This will add the well-known CAs
// to `https.globalAgent.options.ca`
require('ssl-root-cas').inject();
cas = https.globalAgent.options.ca;
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '01-cheap-ssl-intermediary-a.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '02-cheap-ssl-intermediary-b.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '03-cheap-ssl-site.pem')));
This will make your certs available to the core https module as well as modules that depend on it such as request and socket.io-client without deleting the normal ssl certs (which is the default behavior for some odd reason).

Resources