SNI - это расширение TLS протокола, которое позволяет клиенту указать имя хоста (домен) при установке безопасного соединения. Это критически важно для виртуальных хостов, когда несколько доменов обслуживаются одним IP-адресом.
Node.js поддерживает SNI через модуль tls
и https
. Пример сервера с SNI:
const tls = require('tls');
const fs = require('fs');
const options = {
// Общие настройки для всех доменов
SNICallback: (servername, cb) => {
console.log(`Client requested: ${servername}`);
// Можно загрузить разные сертификаты для разных доменов
const ctx = tls.createSecureContext({
key: fs.readFileSync(`${servername}.key`),
cert: fs.readFileSync(`${servername}.crt`)
});
cb(null, ctx);
},
// Fallback контекст если SNI не указан
key: fs.readFileSync('default.key'),
cert: fs.readFileSync('default.crt')
};
const server = tls.createServer(options, (socket) => {
socket.write('Hello with SNI!\n');
socket.end();
});
https.createServer()
SNICallback
ALPN - это TLS расширение, позволяющее клиенту и серверу договориться о протоколе приложения (например, HTTP/2 или HTTP/1.1) во время рукопожатия TLS, без дополнительного round-trip.
Пример сервера с ALPN для HTTP/2:
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
allowHTTP1: true, // Разрешает fallback на HTTP/1.1
ALPNProtocols: ['h2', 'http/1.1'] // Приоритетный порядок
});
server.on('stream', (stream) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('<h1>Hello HTTP/2!</h1>');
});
http2
модулеALPNProtocols
Пример комбинированного использования:
const tls = require('tls');
const http2 = require('http2');
const fs = require('fs');
const server = tls.createServer({
SNICallback: (servername, cb) => {
const ctx = tls.createSecureContext({
key: fs.readFileSync(`${servername}.key`),
cert: fs.readFileSync(`${servername}.crt`),
ALPNProtocols: ['h2', 'http/1.1']
});
cb(null, ctx);
}
});
server.on('secureConnection', (socket) => {
console.log(`Negotiated protocol: ${socket.alpnProtocol}`);
});
openssl s_client
)Node.js предоставляет полную поддержку как SNI (для виртуальных хостов), так и ALPN (для согласования протоколов). Эти технологии критически важны для современных безопасных и высокопроизводительных веб-приложений. Правильное использование этих возможностей позволяет значительно улучшить безопасность и производительность вашего приложения.