Node.js 服务器到服务器加密

Posted

技术标签:

【中文标题】Node.js 服务器到服务器加密【英文标题】:Node.js server-to-server encryption 【发布时间】:2014-05-09 10:40:53 【问题描述】:

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

编辑: 将 RSA 与“身份验证密码”结合使用是否安全?然后这个密码会随每个请求一起提交,整个消息(包括密码)将使用 RSA 公钥(无需加密即可下载)进行加密。

【问题讨论】:

【参考方案1】:

我认为正确的做法是通过 ssl 进行通信,请参见此处:

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

您还可以使用加密模块进行快速而肮脏的加密:

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');

;

两台服务器都需要公钥。

您可能希望在上述之上使用 JSON 字符串化和解析函数(我有这些函数)。您可以在解密传入请求并加密传出请求的中间件中执行此操作。

【讨论】:

文档链接已经很老了。这是一个更新的链接:nodejs.org/api/tls.html 在使用 TLS/SSL 时,如何在没有购买 SSL 证书的情况下验证其他服务器? 看起来它可能会默认拒绝自签名证书,但您可以像这样覆盖此行为: process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" 似乎有很多此类讨论互联网上的东西。 但这将允许每个人轻松伪造证书,从而允许中间人攻击。另外:您确定您提供的功能输出有效的 AES 吗?我无法在使用相同密钥时使用aesencryption.net 或类似网站进行验证。 这不是我的专业领域,但在我看来,默认情况下不允许使用自签名证书,所以你会很好,不是吗?不确定我的小函数是否产生有效的 AES,这里似乎说你想在加密模块中使用稍微不同的函数:***.com/questions/15193913/…【参考方案2】:

我通过在我的应用程序之外执行工作来采取不同的方法。一般来说,您不想重新发明***,而且安全加密是一件很难做到的事情。

我的情况是多个从属服务器需要与主服务器通信以运行队列中的作业。对于服务器到服务器的连接,我实际上只使用Socket.IO(使用socket.io client NPM package,并且所有传输都被禁用,Web 套接字除外)。这给了我一个可靠的 RPC,它可以很好地满足我的需求。 (从那以后我发现了rpc-stream,它可以为您提供任意流上的 RPC。对于 Socket.IO 过大的服务器到服务器通信,这将更加轻量级。)

现在,对于加密部分...我只是在我的服务器之间使用 *** 设置。我采取了惰性方法并为此使用了Hamachi,但您当然可以使用Open*** 或其他任何方法。

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

简而言之,不要做任何不必要的工作。选择速度、简单性和安全性。为此使用现成的东西。

【讨论】:

对于您的特定情况,它可能是正确的,但不幸的是我不能使用这种方法,因为“我的”服务器无法配置为使用 ***。这个应用程序的结果应该更像是一个点对点消息系统,而不是预定义的服务器,它们之间有预先配置的 *** 连接。 @FlorianW。啊,有道理。在这种情况下,直接使用 SSL 可能更合适。如果可能,我仍然会考虑使用 SSH 隧道。 这也不可能,因为服务器应该在多个操作系统上。 @FlorianW。 SSH 在所有操作系统上都运行良好。但是,是的,如果您将这一切都保留在您的应用程序中,它会更加独立。【参考方案3】:

一个可能更容易实现的选项是加密和解密通过普通套接字连接(net.createServernet.connect)发送的所有消息,通过使用 node-gpg 的预共享 gpg 密钥。这要求您在客户端和服务器上的$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() 
);

client.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 证书时可能遇到的任何问题,并且至少在我的基准测试中它要快得多。不过,它可能不那么安全。

【讨论】:

以上是关于Node.js 服务器到服务器加密的主要内容,如果未能解决你的问题,请参考以下文章

RSA Java 加密和 Node.js 解密不起作用

使用Node.js中的TLS / SSL隐式加密连接到FTP服务器

在 iOS 上加密和在 Node.js 上使用 RAW RSA 解密时遇到问题

在 PHP 中加密字符串并在 Node.js 中解密

HTTP 服务器可以接收 HTTPS 请求(node.js)吗?

Node.js(十三)——Promise重构爬虫代码