2014-03-30 176 views
2

我想创建一个在多台计算机上运行并且能够在不同守护进程之间交换消息的Node.js守护进程。当然,通信应该是加密的,但我真的不知道我应该使用什么样的加密来进行服务器到服务器的加密。我现在使用的协议是TCP通过net.createServer。假设我已经在两台设备上交换了密码,我应该如何加密通信?我如何才能确保最为人所知的攻击?Node.js服务器到服务器加密

编辑: 正在使用RSA与“验证密码”结合使用安全吗?然后这个密码会随着每个请求一起提交,整个消息(包括密码)将用RSA公钥加密(可以在没有加密的情况下下载)。

回答

3

我认为这样做的正确的方法是通过SSL进行沟通,在这里看到:

var crypto = require('crypto'); 
var algorithm = 'aes256'; // or any other algorithm supported by OpenSSL 

exports.encryptString = function(text) { 

var cipher = crypto.createCipher(algorithm, key); 
return cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); 

}; 

var key = "123456"; 

exports.decryptString = function(text) { 

var decipher = crypto.createDecipher(algorithm, key); 
return decipher.update(text, 'hex', 'utf8') + decipher.final('utf8'); 

}; 

http://nodejs.org/docs/v0.4.2/api/tls.html

您还可以使用密码模块做一个快速和肮脏的加密

两台服务器都需要公钥。

你可能会想在上面使用JSON stringify和parse函数(我有那些躺着的)。您可以在中间件中解密传入的请求并加密传出的请求。

+2

文档链接相当陈旧。以下是更新后的链接:http://nodejs.org/api/tls.html – Brad

+0

如何在使用TLS/SSL时验证其他服务器而不购买SSL证书? – Dodekeract

+0

看起来它可以拒绝deault自签名的证书,但是你可以重写此行为,像这样: process.env.NODE_TLS_REJECT_UNAUTHORIZED =“0” 似乎有很多这样的事情的讨论互联网。 –

1

通过在我的应用程序之外完成这项工作,我采取了不同的方法。一般来说,你不想重新发明轮子,安全加密是一件困难的事情。

我有几个从服务器需要与主服务器通信以从队列运行作业的情况。对于服务器到服务器的连接,我实际上只使用Socket.IO(使用socket.io client NPM package和除网络套接字以外的所有传输禁用)。这给了我一个坚实的RPC,它适合我的需求。 (我已经发现了rpc-stream,它可以让你通过任意流实现RPC,这对于Socket.IO过度杀毒的服务器到服务器通信来说会更轻一些。)

现在,对于加密部分..我只是使用我的服务器之间建立的VPN。我采取了懒惰的做法,并使用Hamachi这个,但你当然可以使用OpenVPN或任何其他。

您可以使用的第二种方法是tunnel your connections through SSH

总之,不要做任何你不必做的工作。选择速度,简单性和安全性。为此使用现成的东西。这可能是更容易实现

+1

对于您的特定情况,它可能是正确的,但不幸的是我不能使用这种方法,因为“我的”服务器无法配置为使用vpn。这个应用程序的结果应该更像是一个对等消息系统,而不是预先配置的vpn连接的预定义服务器。 – Dodekeract

+0

@FlorianW。啊,这是有道理的。在这种情况下,直接使用SSL可能更合适。如果可能,我仍然会考虑SSH隧道。 – Brad

+0

这也不可能,因为服务器应该在多个操作系统上。 – Dodekeract

1

一种选择是经由使用node-gpg预共享GPG密钥,加密和解密发送的正常套接字连接(net.createServernet.connect)的所有消息。这要求您在客户端和服务器上的$PATH中有gpg,服务器上有一个无密码的私人gpg密钥'Server',客户端上有相应的'Client',另一端安装有相应的公钥。

server.js:

var socketServer = net.createServer(function (c) { 
    // example of send to client 
    var output = JSON.stringify({"msg": "Stuff to send to client."}); 
    encrypt(output, 'Client', function (error, cryptdata) { 
    c.write(cryptdata.toString()); 
    }); 
    // receive data sent from client 
    c.on('data', function (cryptdata) { 
    decrypt(cryptdata.toString(), 'Server', function (error, data) { 
     data = JSON.parse(data.toString()); 
     // handle incoming data 
    }); 
    }); 
}); 
socketServer.listen(port, function() { 
}); 

客户端。js:

var socketClient = net.connect({"port": port}, function() { 
    // Send data to server 
    var data = JSON.stringify({"msg": "Data to server"}); 
    encrypt(data, 'Server', function (error, cryptdata) { 
    socketClient.write(cryptdata.toString()); 
    }); 
}); 
// Receive data from server 
socketClient.on('data', function(cryptdata) { 
    decrypt(cryptdata.toString(), 'Client', function (error, data) { 
    data = JSON.parse(data.toString()); 
    // handle data 
    }); 
}); 

这些是我在server.js和client.js中用于加密/解密的函数。

function encrypt(str, receiver, callback) { 
    gpg.encrypt(str, ['-r ' + receiver, '-a'], callback); 
} 
function decrypt(str, receiver, callback) { 
    gpg.decrypt(str, ['-u ' + receiver, '-a'], callback); 
} 

这消除了您可以使用自签名SSL证书碰上,并至少与我的基准,它是快了很多任何问题。虽然它可能不是安全的。