Node.js шифрование между серверами
Я хочу создать демон Node.js, который работает на нескольких компьютерах и может обмениваться сообщениями между различными демонами. Конечно, связь должна быть зашифрована, но я действительно не знаю, какой тип шифрования мне следует использовать для шифрования между серверами. Протокол, который я сейчас использую, - это TCP через net.createServer. Как мне зашифровать связь, если у меня уже есть обмененный пароль на обоих устройствах? Как мне защитить его от наиболее известных атак?
Изменить: Безопасно ли использование RSA в сочетании с "паролем аутентификации"? Этот пароль затем будет передаваться при каждом запросе, все сообщение (включая пароль) будет зашифровано открытым ключом RSA (который можно загрузить без шифрования).
3 ответа
Я думаю, что правильный способ сделать это - общаться через ssl, смотрите здесь:
http://nodejs.org/docs/v0.4.2/api/tls.html
Вы также можете сделать быстрое и грязное шифрование с помощью модуля crypto:
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 stringify и разобрать функции поверх вышеперечисленного (у меня были такие). Вы можете сделать это в промежуточном программном обеспечении, которое расшифровывает входящие запросы и шифрует исходящие.
Я использую другой подход к этому, выполняя работу вне моего приложения. Вообще говоря, вы не хотите изобретать велосипеды, а безопасное шифрование - непростая задача.
У меня есть ситуация, когда нескольким подчиненным серверам необходимо связаться с главным сервером для запуска заданий из очереди. Для соединения сервер-сервер я на самом деле просто использую Socket.IO (используя пакет клиента NPM socket.io и все транспорты отключены, кроме веб-сокетов). Это дает мне хороший RPC, который хорошо подходит для моих нужд. (С тех пор я обнаружил rpc-stream, который может дать вам RPC по произвольным потокам. Это было бы немного проще для межсерверного взаимодействия, когда Socket.IO является избыточным.)
Теперь, что касается шифрования... Я просто использую VPN, установленную между моими серверами. Я выбрал ленивый подход и использовал Hamachi для этого, но вы, конечно, можете использовать OpenVPN или любой другой.
Второй метод, который вы можете использовать, это туннелировать ваши соединения через SSH.
Короче, не делай никакой работы, которая тебе не нужна. Выбирайте скорость, простоту и безопасность. Используйте что-то готовое для этого.
Один из вариантов, который может быть проще реализовать, - это шифрование и дешифрование всех сообщений, отправляемых через обычное сокетное соединение (net.createServer
а также net.connect
), через предварительно общие ключи gpg, используя node-gpg. Это требует от вас gpg
в вашем $PATH
на клиенте и сервере с закрытым ключом 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, и, по крайней мере, с моими тестами это происходит намного быстрее. Хотя, это может быть не так безопасно.