Running https not on 443 how is this possible? - javascript

If I hit my domain on any other port other than 443 I get the error below. How is it possible then to use nodejs https on different port?
Secure Connection Failed
An error occurred during a connection to mysite:8080. SSL received a record that exceeded the maximum permissible length. (Error code: ssl_error_rx_record_too_long)
For example, in the example given in the documentation they use port 8000.
// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
Using CentOS 6.

record_too_long often/usually means you sent non-SSL-data to a client expecting SSL.
Try to visit your site and port via HTTP (not HTTPS). If it works, you have accidentally bound an HTTP server to it, not an HTTPS server.

At this very moment I have a Node.js server running on port 3000 using HTTPS.
SSL_ERROR_RX_RECORD_TOO_LONG seems to indicate that there's a problem with the hostname (Source)
The error you've included mentions mysite:8080 which tells me that you're trying to connect to mysite:8080 and that that address doesn't exist.
To debug this, try accessing the URL through a browser or by setting up a regular HTTP and see whether it's accessible.

Related

ERR_SSL_SSLV3_ALERT_CERTIFICATE_UNKNOWN thrown by wss server when client tries to connect to it

recently I've been trying to create a WebSocket server (using the ws library for node.js). At first I used the ws unencrypted protocol, but then I had to switch to wss. This brought some client authentication issues. When the client (running on a browser)
(client.js)
this.socket = new WebSocket(`wss://ipv4.address:port`);
... tries to connect to the Node.js-based server
(server.mjs:)
const server = createServer({
cert: readFileSync('/path/to/ssl_certificate.cer'),
key: readFileSync('/path/to/private_key.key'),
ca: [
readFileSync('/etc/ssl/certs/ca-certificates.crt'),
readFileSync('/path/to/ssl_certificate_INTERMEDIATE.cer')
],
rejectUnauthorized: false
});
const wss = new WebSocketServer({ server });
server.listen(port, "hostname", () => {
//the server actually listens, so this line of code is printed
console.log(`listening on wss://${wss.address().address}:${server.address().port}`);
});
server.on("tlsClientError", (err, tlsSocket) => {
console.error("TLS client error", err);
tlsSocket.destroy();
});
... it goes into "tlsClientError", printing this:
TLS client error [Error: C0D71E8ECB7F0000:error:0A000416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:../deps/openssl/openssl/ssl/record/rec_layer_s3.c:1584:SSL alert number 46
] {
library: 'SSL routines',
reason: 'sslv3 alert certificate unknown',
code: 'ERR_SSL_SSLV3_ALERT_CERTIFICATE_UNKNOWN'
}
This looks like the server isn't willing to accept the client's certificates. How do I set them? Is there something I'm not understanding about WebSockets over TLS?
I tried following the advice of many answers from StackOverflow, disabling rejectUnauthorized, but the node https server is still failing, even after adding the same SSL certificates my website is using (same hostname, different port)
EDIT:
I forgot to mention, that connecting from the same host as the server works (i.e. using the ws client part on the node side), as per https://github.com/websockets/ws/blob/master/examples/ssl.js, and even when disabling rejectUnauthorized (because I'm not using a self-signed certificate)

Why can i not connect to NodeJS express server from any network?

Lets say that i have a web server running on port 3001 and my ip is 23.512.531.56 (not an actual ip address btw) and i go onto another network, like my neighbours or something, if i type in chrome 23.512.531.56:3001why can i not get a response from the server? here is my nodeJS code.
//"Imports" libraries reqired.
const express = require("express");
const fs = require("fs");
//Starts express
const svr = express();
//Main
svr.get("/", (req, res)=>{
fs.createReadStream("./html/index.html").pipe(res);
});
svr.get("/image0.png", (req, res) => {
fs.createReadStream("./html/image0.png").pipe(res);
});
//Sets port to host on
svr.listen(3001);
You need to be in the same network. For example, if you are using different wifi (from your neighbors) you can't access your local NodeJs server. You can get to your server if your devices are under the same default gateway.
If you want to access it from any network, you might want to deploy it to a global network.
One thing to add, even for illustration don't use an IP address that is not right
You must open port 3001 to the outside and bind to your local machine (Port forwarding). Have a look into your router! And if it is not a fixed IP use a DynDNS service.

Node.js client can't see data from Express server

I am setting up a Client/Server communication between my tablet and my PC. My Client cant get any data from the server, what am I doing wrong.
My PC is running a Node.js server (using Express) and my tablet runs a client written in Node.js (using Express). I can access the server via the browser and get the data, but not through the javascript code.
My SERVER code is:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('App requested a connection');
});
app.listen(3000, () => console.log('Listening on port 3000!'));
app.get("/boxes", function (req, res)
{
//res.send(req.params[0]);
res.send("All boxes are in the basement");
});
My CLIENT code is:
const express = require('express');
const app = express();
console.log("Client working ...");
app.get("http://127.0.0.1:3000/boxes", function (req, res)
{
console.log("inside...");
console.log(res);
});
The CLIENT should return "All boxes are in the basement" and I get this when I use a browser but it doesn't work if I run the client code. The only message I get from client is "Client working ...".
Does anybody know what I am doing wrong?
Cheers
Express is a library for setting up and configuring an http server for incoming requests. It does not make outgoing requests to other servers. So, your client code is not a client at all.
Several problems here:
127.0.0.1 refers to your local device so your client is referring to itself when it uses 127.0.0.1.
In your client app.get("http://127.0.0.1:3000/boxes") is not a request for data. That attempts to set up an Express route for incoming requests as if you were declaring a second server. But, it's not even done correctly because you would only use the path there.
For a client to make a request of some other server, you would need to use a library call that actually does http requests. For example, you could do something like this:
Code:
const rp = require('request-promise');
rp.get("http://ipaddressOfServer:3000/boxes").then(data => {
// have response here
}).catch(err => {
// error here
});
I chose to use the request-promise library, but there are multiple different ways to make an http request. You can also use http.get() (lower level), request() (from the request library) or axios() from the axios library, etc...
Note, the computer your server is on (assuming it's running a desktop OS) will also have to probably turn of it's local firewall (e.g. windows firewall) or set up a specific rule to allow incoming connections on port 3000. Without that, the incoming connection will be blocked (for security reasons).

info - unhandled socket.io url

I'm trying to use sockets to connect to a Node server I'm running localy
but I keep on getting 'info - unhandled socket.io url' on the server side
+
"XMLHttpRequest cannot load http://localhost:8080/socket.io/?EIO=3&transport=polling&t=1424356590540-0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access." on chrome (using address localhost:8000/index.html)
// top six lines of code to see setup
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
server.listen(8080);
also I'm using python SimpleHTTPServer on port 8000
client code is:
var socket = io.connect('http://localhost:8080');
socket.on('connection', function(){
console.log("connected")
});
using https://cdn.socket.io/socket.io-1.3.4.js" version of sockets.io
I'm assuming the html is irrelevant since I don't have any javascript code in it (except references to angular and jquery)
That's a problem with CORS.
Since your web page is on localhost:8000 and the Socket.io server is on localhost:8080 (two different ports, so two different servers), to allow async requests between the two of them you need to enable CORS. Browsers require that for security reasons.
Your server seems to be using Express. Enabling CORS in Express is quite easy, thanks to NPM packages like cors. Alternatively, look at some questions on SO, like: How to allow CORS?

Can I configure expressjs to serve some pages over http and others over https?

Based on the response to this question:
How do I configure nodejs/expressjs to serve pages over https?
I've been trying to set up the equivalent of:
var express = require('express');
var fs = require("fs");
var crypto = require('crypto');
var app = express.createServer();
var appSecure = express.createServer();
var privateKey = fs.readFileSync('privatekey.pem').toString();
var certificate = fs.readFileSync('certificate.pem').toString();
var credentials = crypto.createCredentials({key: privateKey, cert: certificate});
appSecure.setSecure(credentials);
app.get('/secretStuff', function(req,res) {
//redirect to https
}
appSecure.get('/secretStuff', function(req, res) {
//show you the secret stuff
}
Is this something that's doable with the current release of expressjs and node 2.4?
Yes, this can be done and it looks like you already have most of what you need. Just send the redirect in your app.get handler
app.get('/secretStuff', function(req,res) {
res.redirect('https://' + req.header('Host') + req.url);
}
Also make sure you do something like app.listen(80) and appSecure.listen(443) to actually start the servers on the appropriate port. Otherwise be sure to construct the HTTPS URL with the correct port. For production, this thing is typically handled outside of your app server (node.js) with a reverse proxy like nginx. It is trivial to do this in nginx which will let your node.js process run as non-root and remove the need to have clients directly connecting to node.js, which is not as battle-hardened as nginx for serving live internect TCP connections (I'm paraphrasing Ryan Dahl himself here).
You can only serve a web page over the connection that the request came in. If the request did not come in over https, you can't send the response that way.
So, first you have to be listening for both http and https requests. If a request comes in over http that you want to answer over a secure connection, do not do any processing but immediately redirect it to an https url. Then when the client reissues the request, process as normally.
If the framework uses JSGI then you can probably use the redirect module from Jack otherwise you will have to do it yourself. The details are at the link, i.e. response code 301 and Location: header with the https URL.

Categories