2014-03-30 223 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證書碰上,並至少與我的基準,它是快了很多任何問題。雖然它可能不是安全的。