Я строю простой, способный к STARTTLS POP3-прокси в Node.JS, и мне очень тяжело.NodeJS STARTTLS Использовать SNI
Прокси-сервер служит интерфейсом для многих серверных серверов, поэтому он должен динамически загружать свои сертификаты в зависимости от подключения Клиента.
Я пытаюсь использовать SNICallback, который приносит мне имя сервера, которое использует клиент, но после этого я не могу установить правильный сертификат, потому что мне нужен один сертификат, прежде чем я получу этот вызов, когда создам безопасный контекст.
Код как ниже:
// Load libraries
var net = require('net');
var tls = require('tls');
var fs = require('fs');
// Load certificates (created with openssl)
var certs = [];
for (var i = 1; i <= 8; i++) {
var hostName = 'localhost' + i;
certs[hostName] = {
key : fs.readFileSync('./private-key.pem'),
cert : fs.readFileSync('./public-cert' + i + '.pem'),
}
}
var server = net.createServer(function(socket) {
socket.write('+OK localhost POP3 Proxy Ready\r\n');
socket.on('data', function(data) {
if (data == "STLS\r\n") {
socket.write("+OK begin TLS negotiation\r\n");
upgradeSocket(socket);
} else if (data == "QUIT\r\n") {
socket.write("+OK Logging out.\r\n");
socket.end();
} else {
socket.write("-ERR unknown command.\r\n");
}
});
}).listen(10110);
и upgradeSocket() выглядит следующим образом:
function upgradeSocket(socket) {
// I need this 'details' or handshake will fail with a message:
// SSL routines:ssl3_get_client_hello:no shared cipher
var details = {
key : fs.readFileSync('./private-key.pem'),
cert : fs.readFileSync('./public-cert1.pem'),
}
var options = {
isServer : true,
server : server,
SNICallback : function(serverName) {
return tls.createSecureContext(certs[serverName]);
},
}
sslcontext = tls.createSecureContext(details);
pair = tls.createSecurePair(sslcontext, true, false, false, options);
pair.encrypted.pipe(socket);
socket.pipe(pair.encrypted);
pair.fd = socket.fd;
pair.on("secure", function() {
console.log("TLS connection secured");
});
}
Это правильно рукопожатия, но сертификат я использую статический один в «деталях», не тот, который я получаю в SNICallback.
Чтобы проверить это я бегу сервер и использовать GnuTLS-Cli в качестве клиента:
~$ gnutls-cli -V -s -p 10110 --crlf --insecure -d 5 localhost3
STLS
^D (Control+D)
Вышеприведенная команда, как предполагается получить мне сертификат «localhost3», но это получение «localhost1», потому что он определен в «details» var;
Существует слишком много примеров в Интернете с помощью HTTPS или для клиентов TLS, которые сильно отличаются от того, что у меня есть, и даже для серверов, но они не используют SNI. Любая помощь будет оценена.
Заранее спасибо.
Я только что видел эту открытую ошибку в Node.js GitHub, мне интересно, если это, по сути, проблема: https://github.com/nodejs/node/issues/4878 –