Расскажите про ALPN и SNI и их поддержку в ноде.nodejs-40

1. SNI

Что это?

SNI - это расширение TLS протокола, которое позволяет клиенту указать имя хоста (домен) при установке безопасного соединения. Это критически важно для виртуальных хостов, когда несколько доменов обслуживаются одним IP-адресом.

Как работает в Node.js?

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();
});

Поддержка в Node.js:

  • Полноценная поддержка с версии 0.10.0
  • Автоматически используется в https.createServer()
  • Можно кастомизировать через SNICallback

2. ALPN

Что это?

ALPN - это TLS расширение, позволяющее клиенту и серверу договориться о протоколе приложения (например, HTTP/2 или HTTP/1.1) во время рукопожатия TLS, без дополнительного round-trip.

Как работает в Node.js?

Пример сервера с 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>');
});

Поддержка в Node.js:

  • Полноценная поддержка с версии 5.7.0
  • Используется автоматически в http2 модуле
  • Можно настроить список поддерживаемых протоколов через ALPNProtocols

3. Совместное использование SNI и ALPN

Пример комбинированного использования:

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}`);
});

4. Практическое применение

  1. Виртуальные хосты: SNI позволяет обслуживать разные домены с разными сертификатами
  2. Протоколы приложений: ALPN помогает выбрать оптимальный протокол (HTTP/2 vs HTTP/1.1)
  3. Оптимизация производительности: Снижение задержек при установке соединения

5. Ограничения и подводные камни

  • Старые клиенты: Некоторые старые клиенты не поддерживают SNI/ALPN
  • Отладка: Требуются специальные инструменты (Wireshark, openssl s_client)
  • Совместимость: Нужно внимательно проверять поддерживаемые протоколы

Резюмируем:

Node.js предоставляет полную поддержку как SNI (для виртуальных хостов), так и ALPN (для согласования протоколов). Эти технологии критически важны для современных безопасных и высокопроизводительных веб-приложений. Правильное использование этих возможностей позволяет значительно улучшить безопасность и производительность вашего приложения.