Server peering fixes.
This commit is contained in:
parent
e0977eac22
commit
f36866b8fd
|
@ -60,7 +60,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
obj.connectionState = 1;
|
obj.connectionState = 1;
|
||||||
|
|
||||||
// Get the web socket setup
|
// Get the web socket setup
|
||||||
obj.ws = new WebSocket(obj.url + 'meshserver.ashx', { rejectUnauthorized: false, cert: obj.certificates.agent.cert, key: obj.certificates.agent.key });
|
obj.ws = new WebSocket(obj.url + 'meshserver.ashx', { rejectUnauthorized: false, servername: obj.certificates.CommonName, cert: obj.certificates.agent.cert, key: obj.certificates.agent.key });
|
||||||
obj.parent.parent.debug('peer', 'OutPeer ' + obj.serverid + ': Connecting to: ' + url + 'meshserver.ashx');
|
obj.parent.parent.debug('peer', 'OutPeer ' + obj.serverid + ': Connecting to: ' + url + 'meshserver.ashx');
|
||||||
|
|
||||||
// Register the connection failed event
|
// Register the connection failed event
|
||||||
|
@ -75,8 +75,14 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// Get the peer server's certificate and compute the server public key hash
|
// Get the peer server's certificate and compute the server public key hash
|
||||||
if (obj.ws._socket == null) return;
|
if (obj.ws._socket == null) return;
|
||||||
var serverCert = obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(obj.ws._socket.getPeerCertificate().raw.toString('binary')));
|
if (obj.url.toLowerCase().startsWith('wss://')) {
|
||||||
obj.serverCertHash = obj.forge.pki.getPublicKeyFingerprint(serverCert.publicKey, { encoding: 'binary', md: obj.forge.md.sha384.create() });
|
// We are using TLS, use the certificate hash
|
||||||
|
var serverCert = obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(obj.ws._socket.getPeerCertificate().raw.toString('binary')));
|
||||||
|
obj.serverCertHash = obj.forge.pki.getPublicKeyFingerprint(serverCert.publicKey, { encoding: 'binary', md: obj.forge.md.sha384.create() });
|
||||||
|
} else {
|
||||||
|
// We are not using TLS, blank out the TLS certificate hash
|
||||||
|
obj.serverCertHash = Buffer.alloc(48).toString('binary');
|
||||||
|
}
|
||||||
|
|
||||||
// Start authenticate the peer server by sending a auth nonce & server TLS cert hash.
|
// Start authenticate the peer server by sending a auth nonce & server TLS cert hash.
|
||||||
// Send 384 bits SHA384 hash of TLS cert public key + 384 bits nonce
|
// Send 384 bits SHA384 hash of TLS cert public key + 384 bits nonce
|
||||||
|
@ -98,13 +104,13 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if (msg.length != 98) { obj.parent.parent.debug('peer', 'OutPeer: BAD MESSAGE(A1)'); return; }
|
if (msg.length != 98) { obj.parent.parent.debug('peer', 'OutPeer: BAD MESSAGE(A1)'); return; }
|
||||||
|
|
||||||
// Check that the server hash matches the TLS server certificate public key hash
|
// Check that the server hash matches the TLS server certificate public key hash
|
||||||
if (obj.serverCertHash != msg.substring(2, 50)) { obj.parent.parent.debug('peer', 'OutPeer: Server hash mismatch.'); disconnect(); return; }
|
if (obj.url.toLowerCase().startsWith('wss://') && (obj.serverCertHash != msg.substring(2, 50))) { obj.parent.parent.debug('peer', 'OutPeer: Server hash mismatch.'); disconnect(); return; }
|
||||||
obj.servernonce = msg.substring(50);
|
obj.servernonce = msg.substring(50);
|
||||||
|
|
||||||
// Perform the hash signature using the server agent certificate
|
// Perform the hash signature using the server agent certificate
|
||||||
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) {
|
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) {
|
||||||
// Send back our certificate + signature
|
// Send back our certificate + signature
|
||||||
obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
|
if (obj.ws != null) { obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); } // Command 2, certificate + signature
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -196,7 +202,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if ((command.serverid != null) && (command.dbid != null)) {
|
if ((command.serverid != null) && (command.dbid != null)) {
|
||||||
if (command.serverid == obj.parent.serverid) { console.log('ERROR: Same server ID, trying to peer with self. (' + obj.url + ', ' + command.serverid + ').'); return; }
|
if (command.serverid == obj.parent.serverid) { console.log('ERROR: Same server ID, trying to peer with self. (' + obj.url + ', ' + command.serverid + ').'); return; }
|
||||||
if (command.dbid != obj.parent.parent.db.identifier) { console.log('ERROR: Database ID mismatch. Trying to peer to a server with the wrong database. (' + obj.url + ', ' + command.serverid + ').'); return; }
|
if (command.dbid != obj.parent.parent.db.identifier) { console.log('ERROR: Database ID mismatch. Trying to peer to a server with the wrong database. (' + obj.url + ', ' + command.serverid + ').'); return; }
|
||||||
if (obj.serverCertHash != command.serverCertHash) { console.log('ERROR: Outer certificate hash mismatch (2). (' + obj.url + ', ' + command.serverid + ').'); return; }
|
if (obj.url.toLowerCase().startsWith('wss://') && (obj.serverCertHash != command.serverCertHash)) { console.log('ERROR: Outer certificate hash mismatch (2). (' + obj.url + ', ' + command.serverid + ').'); return; }
|
||||||
obj.peerServerId = command.serverid;
|
obj.peerServerId = command.serverid;
|
||||||
obj.peerServerKey = Buffer.from(command.key, 'hex');
|
obj.peerServerKey = Buffer.from(command.key, 'hex');
|
||||||
obj.authenticated = 3;
|
obj.authenticated = 3;
|
||||||
|
@ -215,9 +221,10 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a mesh server module that received a connection to another server
|
// Create a mesh server module that received a connection to another server
|
||||||
obj.CreatePeerInServer = function (parent, ws, req) {
|
obj.CreatePeerInServer = function (parent, ws, req, tls) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
obj.ws = ws;
|
obj.ws = ws;
|
||||||
|
obj.tls = tls;
|
||||||
obj.parent = parent;
|
obj.parent = parent;
|
||||||
obj.common = require('./common.js');
|
obj.common = require('./common.js');
|
||||||
obj.forge = require('node-forge');
|
obj.forge = require('node-forge');
|
||||||
|
@ -267,7 +274,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
obj.receivedCommands += 1; // Peer server can't send the same command twice on the same connection ever. Block DOS attack path.
|
obj.receivedCommands += 1; // Peer server can't send the same command twice on the same connection ever. Block DOS attack path.
|
||||||
|
|
||||||
// Check that the server hash matches out own web certificate hash
|
// Check that the server hash matches out own web certificate hash
|
||||||
if (obj.webCertificateHash != msg.substring(2, 50)) { obj.close(); return; }
|
if ((obj.tls == true) && (obj.webCertificateHash != msg.substring(2, 50))) { obj.close(); return; }
|
||||||
obj.peernonce = msg.substring(50);
|
obj.peernonce = msg.substring(50);
|
||||||
|
|
||||||
// Perform the hash signature using the server agent certificate
|
// Perform the hash signature using the server agent certificate
|
||||||
|
@ -424,7 +431,8 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// We connected to a peer server, setup everything
|
// We connected to a peer server, setup everything
|
||||||
obj.SetupPeerServer = function (server, peerServerId) {
|
obj.SetupPeerServer = function (server, peerServerId) {
|
||||||
console.log('Connected to peer server ' + peerServerId + '.');
|
obj.parent.debug('peer', 'Connected to peer server ' + peerServerId + '.');
|
||||||
|
//console.log('Connected to peer server ' + peerServerId + '.');
|
||||||
obj.peerServers[peerServerId] = server;
|
obj.peerServers[peerServerId] = server;
|
||||||
|
|
||||||
// Send the list of connections to the peer
|
// Send the list of connections to the peer
|
||||||
|
@ -436,7 +444,8 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// We disconnected to a peer server, clean up everything
|
// We disconnected to a peer server, clean up everything
|
||||||
obj.ClearPeerServer = function (server, peerServerId) {
|
obj.ClearPeerServer = function (server, peerServerId) {
|
||||||
console.log('Disconnected from peer server ' + peerServerId + '.');
|
obj.parent.debug('peer', 'Disconnected from peer server ' + peerServerId + '.');
|
||||||
|
//console.log('Disconnected from peer server ' + peerServerId + '.');
|
||||||
|
|
||||||
// Clean up the connectivity state
|
// Clean up the connectivity state
|
||||||
delete obj.peerServers[peerServerId];
|
delete obj.peerServers[peerServerId];
|
||||||
|
@ -600,7 +609,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
peerTunnel.connect = function () {
|
peerTunnel.connect = function () {
|
||||||
// Get the web socket setup
|
// Get the web socket setup
|
||||||
peerTunnel.parent.parent.debug('peer', 'FTunnel ' + peerTunnel.serverid + ': Start connect to ' + peerTunnel.url);
|
peerTunnel.parent.parent.debug('peer', 'FTunnel ' + peerTunnel.serverid + ': Start connect to ' + peerTunnel.url);
|
||||||
peerTunnel.ws2 = new WebSocket(peerTunnel.url, { rejectUnauthorized: false });
|
peerTunnel.ws2 = new WebSocket(peerTunnel.url, { rejectUnauthorized: false, servername: this.parent.parent.certificates.CommonName, cert: this.parent.parent.certificates.agent.cert, key: this.parent.parent.certificates.agent.key });
|
||||||
|
|
||||||
// Register the connection failed event
|
// Register the connection failed event
|
||||||
peerTunnel.ws2.on('error', function (error) { peerTunnel.parent.parent.debug('peer', 'FTunnel ' + obj.serverid + ': Connection error'); peerTunnel.close(); });
|
peerTunnel.ws2.on('error', function (error) { peerTunnel.parent.parent.debug('peer', 'FTunnel ' + obj.serverid + ': Connection error'); peerTunnel.close(); });
|
||||||
|
@ -620,7 +629,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
var serverCertHashHex = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(serverCert.publicKey, { encoding: 'binary', md: obj.forge.md.sha384.create() }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
var serverCertHashHex = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(serverCert.publicKey, { encoding: 'binary', md: obj.forge.md.sha384.create() }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
|
|
||||||
// Check if the peer certificate is the expected one for this serverid
|
// Check if the peer certificate is the expected one for this serverid
|
||||||
if (obj.peerServers[serverid] == null || obj.peerServers[serverid].serverCertHash != serverCertHashHex) { console.log('ERROR: Outer certificate hash mismatch (1). (' + peerTunnel.url + ', ' + peerTunnel.serverid + ').'); peerTunnel.close(); return; }
|
if ((obj.peerServers[serverid] == null) || (obj.peerServers[serverid].serverCertHash != serverCertHashHex)) { console.log('ERROR: Outer certificate hash mismatch (1). (' + peerTunnel.url + ', ' + peerTunnel.serverid + ').'); peerTunnel.close(); return; }
|
||||||
|
|
||||||
// Connection accepted, resume the web socket to start the data flow
|
// Connection accepted, resume the web socket to start the data flow
|
||||||
peerTunnel.ws1._socket.resume();
|
peerTunnel.ws1._socket.resume();
|
||||||
|
|
|
@ -4875,7 +4875,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup all HTTP handlers
|
// Setup all HTTP handlers
|
||||||
if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req); }); }
|
if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req, obj.args.tlsoffload == null); }); }
|
||||||
for (var i in parent.config.domains) {
|
for (var i in parent.config.domains) {
|
||||||
if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed.
|
if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed.
|
||||||
var domain = parent.config.domains[i];
|
var domain = parent.config.domains[i];
|
||||||
|
|
Loading…
Reference in New Issue