Перейти к содержанию

TLS (SSL)

v18.x.x

Стабильность: 2 – Стабильная

АПИ является удовлетворительным. Совместимость с NPM имеет высший приоритет и не будет нарушена кроме случаев явной необходимости.

Модуль node:tls предоставляет реализацию протоколов Transport Layer Security (TLS) и Secure Socket Layer (SSL), построенных на базе OpenSSL. Доступ к модулю можно получить, используя:

1
const tls = require('node:tls');

Определение отсутствия поддержки криптографии

Возможно, что Node.js будет собран без поддержки модуля node:crypto. В таких случаях попытка импорта из tls или вызов require('node:tls') приведет к ошибке.

При использовании CommonJS возникшую ошибку можно перехватить с помощью try/catch:

1
2
3
4
5
6
let tls;
try {
    tls = require('node:tls');
} catch (err) {
    console.error('поддержка tls отключена!');
}

При использовании лексического ключевого слова ESM import ошибка может быть поймана только в том случае, если обработчик process.on('uncaughtException') зарегистрирован до любой попытки загрузить модуль (например, с помощью модуля предварительной загрузки).

При использовании ESM, если есть вероятность, что код может быть запущен на сборке Node.js, в которой не включена поддержка криптографии, используйте функцию import() вместо лексического ключевого слова import:

1
2
3
4
5
6
let tls;
try {
    tls = await import('node:tls');
} catch (err) {
    console.error('поддержка tls отключена!');
}

Концепции TLS/SSL

TLS/SSL - это набор протоколов, которые опираются на инфраструктуру открытых ключей (PKI) для обеспечения безопасной связи между клиентом и сервером. В большинстве случаев каждый сервер должен иметь закрытый ключ.

Закрытые ключи могут быть сгенерированы несколькими способами. В примере ниже показано использование интерфейса командной строки OpenSSL для генерации 2048-битного закрытого ключа RSA:

1
openssl genrsa -out ryans-key.pem 2048

При использовании TLS/SSL все серверы (и некоторые клиенты) должны иметь сертификат. Сертификаты - это общественные ключи, которые соответствуют закрытому ключу и имеют цифровую подпись либо центра сертификации, либо владельца закрытого ключа (такие сертификаты называются "самоподписанными"). Первым шагом к получению сертификата является создание файла Запроса на подписание сертификата (CSR).

Для создания CSR для закрытого ключа можно использовать интерфейс командной строки OpenSSL:

1
openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem

После создания файла CSR его можно отправить в центр сертификации для подписания или использовать для создания самоподписанного сертификата.

Создание самоподписанного сертификата с помощью интерфейса командной строки OpenSSL показано в примере ниже:

1
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem

Как только сертификат будет создан, его можно использовать для создания файла .pfx или .p12:

1
2
openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem \
      -certfile ca-cert.pem -out ryans.pfx

Где:

  • in: является подписанным сертификатом
  • inkey: связанный закрытый ключ
  • certfile: представляет собой объединение всех сертификатов центра сертификации (ЦС) в один файл, например, cat ca1-cert.pem ca2-cert.pem > ca-cert.pem.

Совершенная прямая секретность

Термин forward secrecy или perfect forward secrecy описывает особенность методов согласования ключей (т.е. обмена ключами). То есть, ключи сервера и клиента используются для согласования новых временных ключей, которые используются специально и только для текущего сеанса связи. Практически это означает, что даже если закрытый ключ сервера скомпрометирован, коммуникация может быть расшифрована подслушивающим лицом только в том случае, если злоумышленнику удастся получить пару ключей, специально сгенерированную для данной сессии.

Совершенная прямая секретность достигается путем случайной генерации пары ключей для согласования ключей при каждом рукопожатии TLS/SSL (в отличие от использования одного и того же ключа для всех сессий). Методы, реализующие эту технику, называются "эфемерными".

В настоящее время для достижения совершенной прямой секретности обычно используются два метода (обратите внимание на символ "E", добавленный к традиционным аббревиатурам):

  • ECDHE: Эфемерная версия протокола согласования ключей Эллиптической кривой Диффи-Хеллмана.
  • DHE: Эфемерная версия протокола согласования ключей Диффи-Хеллмана.

Совершенная передовая секретность с использованием ECDHE включена по умолчанию. Опция ecdhCurve может быть использована при создании TLS-сервера для настройки списка поддерживаемых кривых ECDH для использования. Дополнительную информацию смотрите в tls.createServer().

По умолчанию DHE отключен, но может быть включен наряду с ECDHE, если установить параметр dhparam в 'auto'. Пользовательские параметры DHE также поддерживаются, но не рекомендуется использовать автоматически выбираемые, хорошо известные параметры.

Совершенная прямая тайна была необязательной до версии TLSv1.2. Начиная с TLSv1.3, (EC)DHE используется всегда (за исключением соединений только с PSK).

ALPN и SNI

ALPN (Application-Layer Protocol Negotiation Extension) и SNI (Server Name Indication) являются расширениями квитирования TLS:

  • ALPN: Позволяет использовать один сервер TLS для нескольких протоколов (HTTP, HTTP/2).
  • SNI: позволяет использовать один сервер TLS для нескольких имен хостов с различными сертификатами.

Предварительно разделенные ключи

Поддержка TLS-PSK доступна в качестве альтернативы обычной аутентификации на основе сертификатов. Она использует предварительно разделенный ключ вместо сертификатов для аутентификации TLS-соединения, обеспечивая взаимную аутентификацию. TLS-PSK и инфраструктура открытых ключей не являются взаимоисключающими. Клиенты и серверы могут использовать оба варианта, выбирая любой из них на этапе согласования шифра.

TLS-PSK является хорошим выбором только там, где существуют средства для безопасного обмена ключом с каждой соединяющейся машиной, поэтому он не заменяет инфраструктуру открытых ключей (PKI) для большинства случаев использования TLS. В реализации TLS-PSK в OpenSSL за последние годы было обнаружено множество недостатков в безопасности, в основном потому, что она используется лишь меньшинством приложений. Пожалуйста, рассмотрите все альтернативные решения, прежде чем переходить на шифры PSK. При генерации PSK очень важно использовать достаточную энтропию, как описано в RFC 4086. Получение общего секрета из пароля или других источников с низкой энтропией небезопасно.

Шифры PSK отключены по умолчанию, поэтому для использования TLS-PSK необходимо явно указать набор шифров с помощью опции ciphers. Список доступных шифров можно получить с помощью команды openssl ciphers -v 'PSK'. Все шифры TLS 1.3 подходят для PSK, но в настоящее время поддерживаются только те, которые используют дайджест SHA256, их можно получить с помощью команды openssl ciphers -v -s -tls1_3 -psk.

Согласно RFC 4279, должны поддерживаться PSK-идентификаторы длиной до 128 байт и PSK длиной до 64 байт. Начиная с версии OpenSSL 1.1.0 максимальный размер идентификатора составляет 128 байт, а максимальная длина PSK - 256 байт.

Текущая реализация не поддерживает асинхронные обратные вызовы PSK из-за ограничений базового API OpenSSL.

Смягчение последствий атаки с инициированным клиентом перезаключением.

Протокол TLS позволяет клиентам перезаключать определенные аспекты TLS-сессии. К сожалению, пересмотр сеанса требует непропорционально большого количества ресурсов на стороне сервера, что делает его потенциальным вектором для атак типа "отказ в обслуживании".

Чтобы снизить риск, повторное согласование ограничено тремя разами каждые десять минут. При превышении этого порога на экземпляре tls.TLSSocket выдается событие ошибка. Пределы настраиваются:

  • tls.CLIENT_RENEG_LIMIT <number> Определяет количество запросов на повторное согласование. По умолчанию: 3.
  • tls.CLIENT_RENEG_WINDOW <number> Задает временное окно ренегоциации в секундах. По умолчанию: 600 (10 минут).

Не следует изменять установленные по умолчанию пределы повторного согласования без полного понимания последствий и рисков.

TLSv1.3 не поддерживает повторное согласование.

Возобновление сеанса

Установление сеанса TLS может быть относительно медленным. Этот процесс можно ускорить, сохранив и впоследствии повторно используя состояние сеанса. Для этого существует несколько механизмов, рассмотренных здесь от самого старого к самому новому (и предпочтительному).

Идентификаторы сеансов

Серверы генерируют уникальный идентификатор для новых соединений и отправляют его клиенту. Клиенты и серверы сохраняют состояние сеанса. При повторном подключении клиенты отправляют идентификатор сохраненного состояния сеанса, и если сервер также имеет состояние для этого идентификатора, он может согласиться использовать его. В противном случае сервер создаст новую сессию. Дополнительную информацию см. в RFC 2246, стр. 23 и 30.

Возобновление с использованием идентификаторов сеанса поддерживается большинством веб-браузеров при выполнении HTTPS-запросов.

Для Node.js клиенты ждут события 'session', чтобы получить данные сессии, и предоставляют эти данные в опцию session последующего tls.connect() для повторного использования сессии. Серверы должны реализовать обработчики событий 'newSession' и 'resumeSession' для сохранения и восстановления данных сессии, используя ID сессии в качестве ключа поиска для повторного использования сессий. Чтобы повторно использовать сеансы на балансировщиках нагрузки или рабочих кластерах, серверы должны использовать общий кэш сеансов (например, Redis) в своих обработчиках сеансов.

Билеты сессии

Серверы шифруют все состояние сессии и отправляют его клиенту в виде "билета". При повторном подключении состояние отправляется на сервер при первоначальном подключении. Этот механизм позволяет избежать необходимости в кэше сессий на стороне сервера. Если сервер не использует билет по какой-либо причине (не смог расшифровать его, он слишком старый и т.д.), он создаст новую сессию и отправит новый билет. Более подробную информацию смотрите в RFC 5077.

Возобновление с использованием билетов сессии широко поддерживается многими веб-браузерами при выполнении HTTPS-запросов.

Для Node.js клиенты используют те же API для возобновления с идентификаторами сессии, что и для возобновления с билетами сессии. Для отладки, если tls.TLSSocket.getTLSTicket() возвращает значение, данные сессии содержат билет, в противном случае они содержат состояние сессии на стороне клиента.

При использовании TLSv1.3 имейте в виду, что сервер может посылать несколько билетов, что приводит к нескольким событиям сессии, более подробную информацию смотрите в сессия.

Серверы с одним процессом не нуждаются в специальной реализации для использования билетов сессии. Чтобы использовать билеты сессии при перезагрузке сервера или балансировке нагрузки, все серверы должны иметь одинаковые ключи билетов. Внутри существует три 16-байтовых ключа, но для удобства tls API отображает их как один 48-байтовый буфер.

Можно получить ключи билетов, вызвав server.getTicketKeys() на одном экземпляре сервера, а затем распространить их, но разумнее безопасно сгенерировать 48 байт безопасных случайных данных и задать их с помощью опции ticketKeys в tls.createServer(). Ключи должны регулярно обновляться, а ключи сервера могут быть сброшены с помощью опции server.setTicketKeys().

Ключи сеансовых билетов являются криптографическими ключами, и они должны храниться безопасно. При использовании TLS 1.2 и ниже, если они будут скомпрометированы, все сессии, в которых использовались зашифрованные с их помощью билеты, могут быть расшифрованы. Их не следует хранить на диске, и они должны регулярно обновляться.

Если клиенты рекламируют поддержку билетов, сервер будет их отправлять. Сервер может отключить билеты, указав require('node:constants').SSL_OP_NO_TICKET в secureOptions.

Идентификаторы сеансов и билеты сеансов имеют таймаут, что заставляет сервер создавать новые сеансы. Таймаут может быть настроен с помощью опции sessionTimeout в tls.createServer().

Для всех механизмов, при неудачном возобновлении, серверы будут создавать новые сессии. Поскольку неспособность возобновить сеанс не вызывает сбоев TLS/HTTPS-соединения, легко не заметить излишне низкую производительность TLS. OpenSSL CLI можно использовать для проверки того, что серверы возобновляют сеансы. Используйте опцию -reconnect в openssl s_client, например:

1
$ openssl s_client -connect localhost:443 -reconnect

Просмотрите отладочный вывод. В первом соединении должно быть написано, например, "New":

1
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256

Последующие соединения должны содержать, например, надпись "Повторное использование":

1
Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256

Изменение набора шифров TLS по умолчанию

Node.js собран с набором включенных и выключенных шифров TLS по умолчанию. Этот список шифров по умолчанию может быть настроен при сборке Node.js, чтобы дистрибутивы могли предоставлять свой собственный список по умолчанию.

Следующая команда может быть использована для отображения набора шифров по умолчанию:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
node -p crypto.constants.defaultCoreCipherList | tr ':' '\n'
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-SHA256
DHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES256-SHA384
ECDHE-RSA-AES256-SHA256
DHE-RSA-AES256-SHA256
HIGH
!aNULL
!eNULL
!EXPORT
!DES
!RC4
!MD5
!PSK
!SRP
!CAMELLIA

Это значение по умолчанию можно полностью заменить с помощью ключа командной строки --tls-cipher-list (напрямую или через переменную окружения NODE_OPTIONS). Например, следующая команда делает ECDHE-RSA-AES128-GCM-SHA256:!RC4 набором шифров TLS по умолчанию:

1
2
3
4
node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' server.js

export NODE_OPTIONS=--tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4'
node server.js

Для проверки используйте следующую команду, чтобы показать установленный список шифров, обратите внимание на разницу между defaultCoreCipherList и defaultCipherList:

1
2
3
node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' -p crypto.constants.defaultCipherList | tr ':' '\n'
ECDHE-RSA-AES128-GCM-SHA256
!RC4

т.е. список defaultCoreCipherList устанавливается во время компиляции, а defaultCipherList - во время выполнения.

Чтобы изменить используемые по умолчанию наборы шифров из среды выполнения, измените переменную tls.DEFAULT_CIPHERS, это должно быть сделано до прослушивания любых сокетов, это не повлияет на уже открытые сокеты. Например:

1
2
3
4
5
// Remove Obsolete CBC Ciphers and RSA Key Exchange based Ciphers as they don't provide Forward Secrecy
tls.DEFAULT_CIPHERS +=
    ':!ECDHE-RSA-AES128-SHA:!ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES256-SHA:!ECDHE-RSA-AES256-SHA384' +
    ':!ECDHE-ECDSA-AES128-SHA:!ECDHE-ECDSA-AES128-SHA256:!ECDHE-ECDSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA384' +
    ':!kRSA';

Значение по умолчанию также может быть заменено для каждого клиента или сервера с помощью опции ciphers из tls.createSecureContext(), которая также доступна в tls. createServer(), tls.connect(), и при создании новых tls.TLSSocket`ов.

Список шифров может содержать смесь имен наборов шифров TLSv1.3, начинающихся с TLS_, и спецификаций наборов шифров TLSv1.2 и ниже. Шифры TLSv1.2 поддерживают унаследованный формат спецификации, подробности смотрите в документации OpenSSL cipher list format, но эти спецификации не применяются к шифрам TLSv1.3. Сьюты TLSv1.3 могут быть включены только путем включения их полного имени в список шифров. Они не могут быть включены или отключены, например, с помощью устаревшей спецификации TLSv1.2 'EECDH' или '!EECDH'.

Несмотря на относительную упорядоченность наборов шифров TLSv1.3 и TLSv1.2, протокол TLSv1.3 значительно более безопасен, чем TLSv1.2, и всегда будет выбираться вместо TLSv1.2, если рукопожатие указывает на его поддержку, и если включены какие-либо наборы шифров TLSv1.3.

Набор шифров по умолчанию, включенный в Node.js, был тщательно отобран, чтобы отразить текущие передовые методы обеспечения безопасности и снижения рисков. Изменение набора шифров по умолчанию может оказать значительное влияние на безопасность приложения. Переключатель --tls-cipher-list и опция ciphers должны использоваться только в случае крайней необходимости.

Набор шифров по умолчанию предпочитает шифры GCM для настройки Chrome 'modern cryptography', а также предпочитает шифры ECDHE и DHE для идеальной прямой секретности, обеспечивая некоторую обратную совместимость.

Старые клиенты, которые полагаются на небезопасные и устаревшие шифры на основе RC4 или DES (например, Internet Explorer 6), не могут завершить процесс квитирования с конфигурацией по умолчанию. Если эти клиенты должны поддерживаться, Рекомендации TLS могут предложить совместимый набор шифров. Более подробную информацию о формате см. в документации OpenSSL cipher list format.

Существует только пять наборов шифров TLSv1.3:

  • 'TLS_AES_256_GCM_SHA384'
  • 'TLS_CHACHA20_POLY1305_SHA256'
  • 'TLS_AES_128_GCM_SHA256'
  • 'TLS_AES_128_CCM_SHA256'
  • 'TLS_AES_128_CCM_8_SHA256'

Первые три набора включены по умолчанию. Два набора на основе CCM поддерживаются TLSv1.3, поскольку они могут быть более производительными на ограниченных системах, но они не включены по умолчанию, поскольку обеспечивают меньшую безопасность.

Коды ошибок сертификата X509

Многие функции могут не сработать из-за ошибок сертификата, о которых сообщает OpenSSL. В таком случае функция предоставляет <Error> через свой обратный вызов, имеющий свойство code, которое может принимать одно из следующих значений:

  • 'UNABLE_TO_GET_ISSUER_CERT': Невозможно получить сертификат эмитента.
  • 'UNABLE_TO_GET_CRL': Невозможно получить CRL сертификата.
  • 'UNABLE_TO_DECRYPT_CERT_SIGNATURE': Невозможно расшифровать подпись сертификата.
  • 'UNABLE_TO_DECRYPT_CRL_SIGNATURE': Невозможно расшифровать подпись CRL.
  • 'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY': Невозможно расшифровать открытый ключ эмитента.
  • 'CERT_SIGNATURE_FAILURE': Сбой подписи сертификата.
  • 'CRL_SIGNATURE_FAILURE': Сбой подписи СОС.
  • 'CERT_NOT_YET_VALID': Сертификат еще не действителен.
  • 'CERT_HAS_EXPIRED': Срок действия сертификата истек.
  • 'CRL_NOT_YET_VALID': CRL еще не действителен.
  • 'CRL_HAS_EXPIRED': Срок действия CRL истек.
  • 'ERROR_IN_CERT_NOT_BEFORE_FIELD': Ошибка формата в поле notBefore сертификата.
  • 'ERROR_IN_CERT_NOT_AFTER_FIELD': Ошибка форматирования в поле notAfter сертификата.
  • 'ERROR_IN_CRL_LAST_UPDATE_FIELD': Ошибка форматирования поля lastUpdate в CRL.
  • 'ERROR_IN_CRL_NEXT_UPDATE_FIELD': Ошибка формата в поле CRL nextUpdate.
  • 'OUT_OF_MEM': Закончилась память.
  • DEPTH_ZERO_SELF_SIGNED_CERT'`: Самоподписанный сертификат.
  • 'SELF_SIGNED_CERT_IN_CHAIN': Самоподписанный сертификат в цепочке сертификатов.
  • 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY': Невозможно получить локальный сертификат эмитента.
  • 'UNABLE_TO_VERIFY_LEAF_SIGNATURE': Невозможно проверить первый сертификат.
  • 'CERT_CHAIN_TOO_LONG': Слишком длинная цепочка сертификатов.
  • 'CERT_REVOKED': Сертификат отозван.
  • 'INVALID_CA': Недействительный сертификат центра сертификации.
  • 'PATH_LENGTH_EXCEEDED': Превышено ограничение длины пути.
  • 'INVALID_PURPOSE': Неподдерживаемое назначение сертификата.
  • 'CERT_UNTRUSTED': Сертификат не заслуживает доверия.
  • 'CERT_REJECTED': Сертификат отклонен.
  • 'HOSTNAME_MISMATCH': Несоответствие имени хоста.

Класс: tls.CryptoStream.

Стабильность: 0 – устарело или набрало много негативных отзывов

Вместо него используйте tls.TLSSocket.

Класс tls.CryptoStream представляет поток зашифрованных данных. Этот класс устарел и больше не должен использоваться.

cryptoStream.bytesWritten

Свойство cryptoStream.bytesWritten возвращает общее количество байт, записанных в базовый сокет, включая байты, необходимые для реализации протокола TLS.

Класс: tls.SecurePair

Стабильность: 0 – устарело или набрало много негативных отзывов

Используйте tls.TLSSocket вместо этого.

Возвращается tls.createSecurePair().

Событие: 'secure'

Событие 'secure' испускается объектом SecurePair' после установления безопасного соединения.

Как и при проверке события сервера 'secureConnection', следует проверить pair.cleartext.authorized, чтобы убедиться, что используемый сертификат должным образом авторизован.

Класс: tls.Server

  • Расширяет: {net.Server}

Принимает зашифрованные соединения с использованием TLS или SSL.

Событие: соединение

  • socket {stream.Duplex}

Это событие возникает при установлении нового TCP-потока, до начала квитирования TLS. socket обычно является объектом типа net.Socket, но не будет получать события, в отличие от сокета, созданного из события net.Server 'connection'. Обычно пользователи не хотят обращаться к этому событию.

Это событие также может быть явно вызвано пользователями для установки соединений с сервером TLS. В этом случае может быть передан любой поток Duplex.

Событие: keylog

  • line <Buffer> Строка ASCII текста, в формате NSS SSLKEYLOGFILE.
  • tlsSocket {tls.TLSSocket} Экземпляр tls.TLSSocket, на котором оно было сгенерировано.

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

Типичный случай использования - добавление полученных строк в общий текстовый файл, который впоследствии используется программами (например, Wireshark) для расшифровки трафика:

1
2
3
4
5
6
7
8
const logFile = fs.createWriteStream('/tmp/ssl-keys.log', {
    flags: 'a',
});
// ...
server.on('keylog', (line, tlsSocket) => {
    if (tlsSocket.remoteAddress !== '...') return; // Регистрируются только ключи для определенного IP-адреса
    logFile.write(line);
});

Событие: 'newSession'

Событие 'newSession' генерируется при создании новой TLS-сессии. Оно может использоваться для хранения сессий во внешнем хранилище. Данные должны быть предоставлены обратному вызову 'resumeSession'.

При вызове обратного вызова слушателю передаются три аргумента:

  • sessionId <Buffer> Идентификатор TLS-сессии
  • sessionData <Buffer> Данные TLS-сессии
  • callback <Function> Функция обратного вызова без аргументов, которая должна быть вызвана, чтобы данные были отправлены или получены через защищенное соединение.

Прослушивание этого события будет иметь эффект только для соединений, установленных после добавления слушателя события.

Событие: 'OCSPRequest'

Событие 'OCSPRequest' генерируется, когда клиент отправляет запрос на статус сертификата. При вызове обратного вызова слушателя ему передаются три аргумента:

  • certificate <Buffer> сертификат сервера
  • issuer <Buffer> Сертификат эмитента
  • callback <Function> Функция обратного вызова, которая должна быть вызвана для предоставления результатов запроса OCSP.

Текущий сертификат сервера может быть разобран для получения OCSP URL и ID сертификата; после получения OCSP ответа вызывается callback(null, resp), где resp - экземпляр Buffer, содержащий OCSP ответ. И certificate, и issuer являются Buffer DER-представлениями основного сертификата и сертификата эмитента. Они могут быть использованы для получения ID сертификата OCSP и URL конечной точки OCSP.

В качестве альтернативы может быть вызван callback(null, null), указывающий на отсутствие ответа OCSP.

Вызов callback(err) приведет к вызову socket.destroy(err).

Типичный поток OCSP-запроса выглядит следующим образом:

  1. Клиент подключается к серверу и отправляет OCSPRequest' (через расширение status info в ClientHello).
  2. Сервер получает запрос и испускает событие 'OCSPRequest', вызывая слушателя, если он зарегистрирован.
  3. Сервер извлекает OCSP URL из certificate или issuer и выполняет OCSP запрос к CA.
  4. Сервер получает 'OCSPResponse' от ЦС и отправляет его обратно клиенту через аргумент callback.
  5. Клиент проверяет ответ и либо уничтожает сокет, либо выполняет квитирование.

Аргумент issuer может быть null, если сертификат самоподписанный или эмитента нет в списке корневых сертификатов. (Эмитент может быть указан с помощью опции ca при установлении TLS-соединения).

Прослушивание этого события будет иметь эффект только для соединений, установленных после добавления слушателя события.

Для разбора сертификатов можно использовать модуль npm, например asn1.js.

Событие: 'resumeSession'

Событие 'resumeSession' генерируется, когда клиент запрашивает возобновление предыдущей TLS-сессии. При вызове обратного вызова слушателю передаются два аргумента:

  • sessionId <Buffer> Идентификатор TLS-сессии
  • callback <Function> Функция обратного вызова, которая будет вызвана после восстановления предыдущей сессии: callback([err[, sessionData]]).

Слушатель событий должен выполнить поиск во внешнем хранилище sessionData, сохраненных обработчиком события 'newSession', используя заданный sessionId. Если он найден, вызовите callback(null, sessionData) для возобновления сессии. Если не найден, сессия не может быть возобновлена. callback() должен быть вызван без sessionData, чтобы можно было продолжить квитирование и создать новую сессию. Можно вызвать callback(err), чтобы прервать входящее соединение и уничтожить сокет.

Прослушивание этого события будет иметь эффект только для соединений, установленных после добавления слушателя события.

Ниже показано возобновление сеанса TLS:

1
2
3
4
5
6
7
8
const tlsSessionStore = {};
server.on('newSession', (id, data, cb) => {
    tlsSessionStore[id.toString('hex')] = data;
    cb();
});
server.on('resumeSession', (id, cb) => {
    cb(null, tlsSessionStore[id.toString('hex')] || null);
});

Событие: 'secureConnection'

Событие 'secureConnection' генерируется после успешного завершения процесса передачи данных для нового соединения. При вызове обратного вызова слушателя ему передается один аргумент:

  • tlsSocket {tls.TLSSocket} Установленный сокет TLS.

Свойство tlsSocket.authorized представляет собой булево, указывающее, был ли клиент проверен одним из предоставленных центров сертификации для сервера. Если tlsSocket.authorized равно false, то устанавливается socket.authorizationError для описания того, как произошла ошибка авторизации. В зависимости от настроек TLS-сервера, неавторизованные соединения могут быть приняты.

Свойство tlsSocket.alpnProtocol представляет собой строку, содержащую выбранный протокол ALPN. Если протокол ALPN не выбран, поскольку клиент или сервер не отправили расширение ALPN, tlsSocket.alpnProtocol равно false.

Свойство tlsSocket.servername представляет собой строку, содержащую имя сервера, запрошенное через SNI.

Событие: 'tlsClientError'

Событие 'tlsClientError' генерируется при возникновении ошибки до установления безопасного соединения. При вызове обратного вызова слушателю передаются два аргумента:

  • exception <Error> объект Error, описывающий ошибку
  • tlsSocket {tls.TLSSocket} Экземпляр tls.TLSSocket, с которого произошла ошибка.

server.addContext(hostname, context)

  • hostname <string> Имя хоста SNI или подстановочный знак (например, '*')
  • context <Object> Объект, содержащий любое из возможных свойств из аргументов tls.createSecureContext() options (например, key, cert, ca и т.д.).

Метод server.addContext() добавляет защищенный контекст, который будет использоваться, если имя SNI клиентского запроса совпадает с указанным именем hostname (или подстановочным знаком).

При наличии нескольких совпадающих контекстов используется последний добавленный.

server.address()

Возвращает связанный адрес, имя семейства адресов и порт сервера, как об этом сообщает операционная система. Дополнительную информацию смотрите в net.Server.address().

server.close([callback])

  • callback <Function> Обратный вызов слушателя, который будет зарегистрирован для прослушивания события `'close'' экземпляра сервера.
  • Возвращает: {tls.Server}

Метод server.close() останавливает сервер от приема новых соединений.

Эта функция работает асинхронно. Событие `'close'' будет вызвано, когда у сервера больше не будет открытых соединений.

server.getTicketKeys()

  • Возвращает: <Buffer> 48-байтовый буфер, содержащий ключи билетов сессии.

Возвращает ключи билетов сеанса.

Дополнительную информацию смотрите в разделе Возобновление сеанса.

server.listen()

Запускает сервер, прослушивающий зашифрованные соединения. Этот метод идентичен server.listen() из net.Server.

server.setSecureContext(options)

  • options <Object> Объект, содержащий любое из возможных свойств из аргументов tls.createSecureContext() options (например, key, cert, ca и т.д.).

Метод server.setSecureContext() заменяет безопасный контекст существующего сервера. Существующие соединения с сервером не прерываются.

server.setTicketKeys(keys)

  • keys {Buffer|TypedArray|DataView} 48-байтовый буфер, содержащий ключи билетов сессии.

Устанавливает ключи билетов сеанса.

Изменения в ключах билетов действительны только для будущих подключений к серверу. Существующие или ожидающие подключения к серверу будут использовать предыдущие ключи.

Дополнительную информацию см. в разделе Возобновление сеанса.

Класс: tls.TLSSocket

Выполняет прозрачное шифрование записываемых данных и все необходимые переговоры TLS.

Экземпляры tls.TLSSocket реализуют дуплексный интерфейс Stream.

Методы, возвращающие метаданные TLS-соединения (например, tls.TLSSocket.getPeerCertificate()), будут возвращать данные, только пока соединение открыто.

new tls.TLSSocket(socket[, options])

  • socket {net.Socket|stream.Duplex} На стороне сервера, любой поток Duplex. На стороне клиента, любой экземпляр net.Socket (для общей поддержки потока Duplex на стороне клиента, необходимо использовать tls.connect()).
  • options <Object>
    • enableTrace: См. tls.createServer()
    • isServer: Протокол SSL/TLS является асимметричным, TLSSockets должны знать, должны ли они вести себя как сервер или как клиент. Если true, то TLS-сокет будет создан как сервер. По умолчанию: false.
    • server {net.Server} Экземпляр net.Server.
    • requestCert: Следует ли проверять подлинность удаленного аналога, запрашивая сертификат. Клиенты всегда запрашивают сертификат сервера. Серверы (isServer равно true) могут установить requestCert в true, чтобы запросить сертификат клиента.
    • rejectUnauthorized: См. tls.createServer()
    • ALPNProtocols: См. tls.createServer()
    • SNICallback: См. tls.createServer()
    • session <Buffer> Экземпляр Buffer, содержащий сессию TLS.
    • requestOCSP <boolean> Если true, указывает, что расширение запроса статуса OCSP будет добавлено в клиентский привет и событие 'OCSPResponse' будет испущено на сокете перед установлением безопасного соединения.
    • secureContext: Объект TLS контекста, созданный с помощью tls.createSecureContext(). Если secureContext не предоставлен, он будет создан путем передачи всего объекта options в tls.createSecureContext().
    • ...: tls.createSecureContext() опции, которые используются, если опция ecureContext отсутствует. В противном случае они игнорируются.

Создайте новый объект tls.TLSSocket из существующего TCP-сокета.

Событие: keylog

  • line <Buffer> Строка ASCII текста, в формате NSS SSLKEYLOGFILE.

Событие keylog испускается на tls.TLSSocket, когда ключевой материал генерируется или принимается сокетом. Этот ключевой материал может быть сохранен для отладки, поскольку он позволяет расшифровать перехваченный трафик TLS. Он может генерироваться несколько раз, до или после завершения квитирования.

Типичный случай использования - добавление полученных строк в общий текстовый файл, который впоследствии используется программами (например, Wireshark) для расшифровки трафика:

1
2
3
4
5
const logFile = fs.createWriteStream('/tmp/ssl-keys.log', {
    flags: 'a',
});
// ...
tlsSocket.on('keylog', (line) => logFile.write(line));

Событие: 'OCSPResponse'

Событие 'OCSPResponse' генерируется, если при создании tls.TLSSocket была установлена опция requestOCSP и был получен ответ OCSP. При вызове обратного вызова слушателя ему передается один аргумент:

  • response <Buffer> OCSP-ответ сервера.

Обычно ответ представляет собой объект с цифровой подписью от ЦС сервера, содержащий информацию о статусе отзыва сертификата сервера.

Событие: 'secureConnect'

Событие 'secureConnect' происходит после успешного завершения процесса передачи данных для нового соединения. Обратный вызов слушателя будет вызван независимо от того, был ли авторизован сертификат сервера или нет. Клиент обязан проверить свойство tlsSocket.authorized, чтобы определить, был ли сертификат сервера подписан одним из указанных CA. Если tlsSocket.authorized === false, то ошибку можно найти, проверив свойство tlsSocket.authorizationError. Если использовался ALPN, то свойство tlsSocket.alpnProtocol может быть проверено для определения согласованного протокола.

Событие 'secureConnect' не испускается, когда {tls.TLSSocket} создается с помощью конструктора new tls.TLSSocket().

Событие: сессия

Событие 'session' выдается на клиенте tls.TLSSocket, когда доступна новая сессия или билет TLS. Это может произойти до завершения квитирования, в зависимости от версии протокола TLS, который был согласован. Событие не испускается на сервере, или если новая сессия не была создана, например, когда соединение было возобновлено. Для некоторых версий протокола TLS событие может быть вызвано несколько раз, в этом случае все сессии могут быть использованы для возобновления.

На клиенте, session можно указать в опции session опции tls.connect() для возобновления соединения.

Дополнительную информацию смотрите в разделе Возобновление сеанса.

Для TLSv1.2 и ниже, tls.TLSSocket.getSession() может быть вызван после завершения квитирования. Для TLSv1.3 протоколом разрешено только возобновление на основе билетов, отправляется несколько билетов, и билеты отправляются только после завершения рукопожатия. Поэтому для получения возобновляемой сессии необходимо дождаться события 'session'. Приложения должны использовать событие 'session' вместо getSession(), чтобы гарантировать, что они будут работать для всех версий TLS. Приложения, которые рассчитывают получить или использовать только одну сессию, должны прослушать это событие только один раз:

1
2
3
4
5
6
7
tlsSocket.once('session', (session) => {
    // Сессия может быть использована сразу или позже.
    tls.connect({
        session: session,
        // Другие параметры подключения...
    });
});

tlsSocket.address()

Возвращает связанный адрес, имя семейства адресов и порт базового сокета, как сообщает операционная система: { port: 12346, семейство: 'IPv4', адрес: '127.0.0.1' }.

tlsSocket.authorizationError

Возвращает причину, по которой сертификат пира не был проверен. Это свойство устанавливается только тогда, когда tlsSocket.authorized === false.

tlsSocket.authorized

Это свойство равно true, если сертификат пира был подписан одним из CA, указанных при создании экземпляра tls.TLSSocket, иначе false.

tlsSocket.disableRenegotiation()

Отключает повторное согласование TLS для данного экземпляра TLSSocket. После вызова попытки повторного согласования вызовут событие ошибка на TLSSocket.

tlsSocket.enableTrace()

Когда эта функция включена, информация о трассировке пакетов TLS записывается в stderr. Это может быть использовано для отладки проблем с TLS-соединением.

Формат вывода идентичен выводу openssl s_client -trace или openssl s_server -trace. Хотя он создается функцией OpenSSL SSL_trace(), его формат не документирован, может измениться без предупреждения, и на него не следует полагаться.

tlsSocket.encrypted

Всегда возвращает true. Это может использоваться для отличия TLS-сокетов от обычных экземпляров net.Socket.

tlsSocket.getCertificate()

Возвращает объект, представляющий локальный сертификат. Возвращаемый объект имеет некоторые свойства, соответствующие полям сертификата.

Пример структуры сертификата смотрите в tls.TLSSocket.getPeerCertificate().

Если локальный сертификат отсутствует, будет возвращен пустой объект. Если сокет был уничтожен, будет возвращен null.

tlsSocket.getCipher()

  • Возвращает: <Object>
    • name <string> Имя OpenSSL для набора шифров.
    • standardName <string> Имя IETF для набора шифров.
    • version <string> Минимальная версия протокола TLS, поддерживаемая этим набором шифров. Фактический согласованный протокол см. в tls.TLSSocket.getProtocol().

Возвращает объект, содержащий информацию о согласованном наборе шифров.

Например, протокол TLSv1.2 с шифром AES256-SHA:

1
2
3
4
5
{
    "name": "AES256-SHA",
    "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA",
    "version": "SSLv3"
}

Смотрите SSL_CIPHER_get_name для получения дополнительной информации.

tlsSocket.getEphemeralKeyInfo()

Возвращает объект, представляющий тип, имя и размер параметра эфемерного обмена ключами в режиме perfect forward secrecy на клиентском соединении. Возвращает пустой объект, если обмен ключами не является эфемерным. Так как эта функция поддерживается только на клиентском сокете; null возвращается, если вызывается на серверном сокете. Поддерживаемые типы: 'DH' и 'ECDH'. Свойство name доступно только при типе 'ECDH'.

Например: { type: 'ECDH', name: 'prime256v1', size: 256 }.

tlsSocket.getFinished()

  • Возвращает: {Buffer|undefined} Последнее сообщение Finished, которое было отправлено сокету в рамках квитирования SSL/TLS, или undefined, если сообщение Finished еще не было отправлено.

Поскольку сообщения Finished представляют собой дайджесты сообщений полного рукопожатия (с общим количеством 192 бита для TLS 1.0 и более для SSL 3.0), они могут быть использованы для внешних процедур аутентификации, когда аутентификация, обеспечиваемая SSL/TLS, нежелательна или недостаточна.

Соответствует процедуре SSL_get_finished в OpenSSL и может использоваться для реализации привязки канала tls-unique из RFC 5929.

tlsSocket.getPeerCertificate([detailed])

  • detailed <boolean> Включает полную цепочку сертификатов, если true, в противном случае включает только сертификат пира.
  • Возвращает: <Object> Объект сертификата.

Возвращает объект, представляющий сертификат сверстника. Если пир не предоставил сертификат, будет возвращен пустой объект. Если сокет был уничтожен, будет возвращен null.

Если была запрошена полная цепочка сертификатов, каждый сертификат будет включать свойство issuerCertificate, содержащее объект, представляющий сертификат его эмитента.

tlsSocket.getPeerFinished()

  • Возвращает: {Buffer|undefined} Последнее сообщение Finished, которое ожидается или фактически было получено от сокета как часть рукопожатия SSL/TLS, или undefined, если до сих пор нет сообщения Finished.

Поскольку сообщения Finished представляют собой дайджесты сообщений полного рукопожатия (с общим количеством 192 бита для TLS 1.0 и более для SSL 3.0), они могут использоваться для внешних процедур аутентификации, когда аутентификация, обеспечиваемая SSL/TLS, нежелательна или недостаточна.

Соответствует процедуре SSL_get_peer_finished в OpenSSL и может использоваться для реализации привязки канала tls-unique из RFC 5929.

tlsSocket.getPeerX509Certificate()

  • Возвращает: {X509Certificate}

Возвращает сертификат пира в виде объекта {X509Certificate}.

Если сертификат пира отсутствует, или сокет был уничтожен, будет возвращено undefined.

tlsSocket.getProtocol()

Возвращает строку, содержащую согласованную версию протокола SSL/TLS текущего соединения. Значение 'unknown'' будет возвращено для подключенных сокетов, которые не завершили процесс квитирования. Значениеnull` будет возвращено для серверных сокетов или отключенных клиентских сокетов.

Версии протокола:

  • SSLv3
  • TLSv1
  • TLSv1.1
  • TLSv1.2
  • TLSv1.3.

Более подробную информацию смотрите в документации OpenSSL SSL_get_version.

tlsSocket.getSession()

Возвращает данные сессии TLS или undefined, если сессия не была согласована. На клиенте эти данные могут быть переданы в опцию session опции tls.connect() для возобновления соединения. На сервере это может быть полезно для отладки.

Дополнительную информацию смотрите в разделе Возобновление сеанса.

Примечание: getSession() работает только для TLSv1.2 и ниже. Для TLSv1.3 приложения должны использовать событие 'session' (оно также работает для TLSv1.2 и ниже).

tlsSocket.getSharedSigalgs()

  • Возвращает: <Array> Список алгоритмов подписи, разделяемых между сервером и клиентом, в порядке убывания предпочтений.

Смотрите SSL_get_shared_sigalgs для получения дополнительной информации.

tlsSocket.getTLSTicket()

Для клиента возвращает билет сессии TLS, если он доступен, или undefined. Для сервера всегда возвращает undefined.

Это может быть полезно для отладки.

Дополнительную информацию см. в Возобновление сеанса.

tlsSocket.getX509Certificate()

  • Возвращает: {X509Certificate}

Возвращает локальный сертификат в виде объекта {X509Certificate}.

Если локального сертификата нет, или сокет был уничтожен, будет возвращено undefined.

tlsSocket.isSessionReused()

  • Возвращает: <boolean> true, если сессия была использована повторно, false в противном случае.

Дополнительную информацию смотрите в Возобновление сессии.

tlsSocket.localAddress

Возвращает строковое представление локального IP-адреса.

tlsSocket.localPort

Возвращает числовое представление локального порта.

tlsSocket.remoteAddress

Возвращает строковое представление удаленного IP-адреса. Например, 74.125.127.100 или 2001:4860:a005::68.

tlsSocket.remoteFamily

Возвращает строковое представление семейства удаленных IP-адресов. IPv4 или IPv6.

tlsSocket.remotePort

Возвращает числовое представление удаленного порта. Например, 443.

tlsSocket.renegotiate(options, callback)

  • options <Object>

    • rejectUnauthorized <boolean> Если не false, сертификат сервера проверяется по списку предоставленных CA. При неудачной проверке выдается событие 'error'; err.code содержит код ошибки OpenSSL. По умолчанию: true.
    • requestCert
  • callback <Function> Если renegotiate() возвращает true, обратный вызов присоединяется один раз к событию 'secure'. Если renegotiate() вернула false, callback будет вызван в следующем тике с ошибкой, если только tlsSocket не был уничтожен, в этом случае callback не будет вызван вообще.

  • Возвращает: <boolean> true, если пересогласование было инициировано, false в противном случае.

Метод tlsSocket.renegotiate() инициирует процесс TLS renegotiation. По завершении, функции callback будет передан единственный аргумент, который является либо Error (если запрос не прошел), либо null.

Этот метод можно использовать для запроса сертификата партнера после установления безопасного соединения.

При работе в качестве сервера сокет будет уничтожен с ошибкой по истечении времени handshakeTimeout.

Для TLSv1.3 повторное согласование не может быть инициировано, оно не поддерживается протоколом.

tlsSocket.setMaxSendFragment(size)

  • size <number> Максимальный размер фрагмента TLS. Максимальное значение - 16384. По умолчанию: 16384.
  • Возвращает: <boolean>

Метод tlsSocket.setMaxSendFragment() устанавливает максимальный размер фрагмента TLS. Возвращает true, если установка лимита прошла успешно; false в противном случае.

Меньшие размеры фрагментов уменьшают задержку буферизации на клиенте: большие фрагменты буферизируются уровнем TLS до тех пор, пока не будет получен весь фрагмент и не будет проверена его целостность; большие фрагменты могут охватывать несколько обходов, и их обработка может быть отложена из-за потери или перенаправления пакетов. Однако меньшие фрагменты добавляют дополнительные байты обрамления TLS и накладные расходы процессора, что может снизить общую пропускную способность сервера.

tls.checkServerIdentity(hostname, cert)

  • hostname <string> Имя хоста или IP-адрес для проверки сертификата.
  • cert <Object> объект сертификата, представляющий сертификат сверстника.
  • Возвращает: {Error|undefined}

Проверяет, что сертификат cert выдан для hostname.

Возвращает объект <Error>, заполняя его reason, host и cert при неудаче. При успехе возвращает <undefined>.

Эта функция предназначена для использования в сочетании с опцией checkServerIdentity, которая может быть передана в tls.connect() и как таковая работает с объектом сертификата. Для других целей вместо нее используйте x509.checkHost().

Эта функция может быть перезаписана путем предоставления альтернативной функции в качестве опции options.checkServerIdentity, которая передается в tls.connect(). Перезаписывающая функция может вызывать tls.checkServerIdentity(), конечно, чтобы дополнить выполненную проверку дополнительной верификацией.

Эта функция вызывается только в том случае, если сертификат прошел все остальные проверки, например, был выпущен доверенным ЦС (options.ca).

Ранние версии Node.js неправильно принимали сертификаты для заданного hostname, если присутствовало соответствующее альтернативное имя субъекта uniformResourceIdentifier (см. CVE-2021-44531). Приложения, которые хотят принимать альтернативные имена субъектов uniformResourceIdentifier, могут использовать пользовательскую функцию options.checkServerIdentity, которая реализует желаемое поведение.

tls.connect(options[, callback])

  • options <Object>

    • enableTrace: См. tls.createServer()

    • host <string> Хост, к которому должен подключиться клиент. По умолчанию: 'localhost'.

    • port <number> Порт, к которому должен подключиться клиент.

    • path <string> Создает соединение Unix сокета с путем. Если указана эта опция, host и port игнорируются.

    • socket {stream.Duplex} Устанавливает безопасное соединение на заданном сокете вместо создания нового сокета. Обычно это экземпляр net.Socket, но допускается любой поток Duplex. Если указана эта опция, path, host и port игнорируются, за исключением проверки сертификата. Обычно сокет уже подключен, когда передается в tls.connect(), но он может быть подключен позже. За подключение/отключение/уничтожение socket отвечает пользователь; вызов tls.connect() не приведет к вызову net.connect().

    • allowHalfOpen <boolean> Если установлено значение false, то сокет будет автоматически завершать доступную для записи сторону, когда завершится доступная для чтения сторона. Если установлена опция socket, эта опция не имеет никакого эффекта. Подробнее см. опцию allowHalfOpen в net.Socket. По умолчанию: false.

    • rejectUnauthorized <boolean> Если не false, сертификат сервера проверяется по списку предоставленных CA. При неудачной проверке выдается событие 'error'; err.code содержит код ошибки OpenSSL. По умолчанию: true.

    • pskCallback <Function>

      • hint: <string> необязательное сообщение, отправляемое с сервера, чтобы помочь клиенту решить, какой идентификатор использовать во время переговоров. Всегда null, если используется TLS 1.3.
      • Возвращает: <Object> в форме { psk: <Buffer|TypedArray|DataView>, identity: <строка> } или null для остановки процесса согласования. psk должен быть совместим с дайджестом выбранного шифра. identity должен использовать кодировку UTF-8.

      При согласовании TLS-PSK (pre-shared keys) эта функция вызывается с необязательным идентификатором hint, предоставленным сервером, или null в случае TLS 1.3, где hint был удален. Для соединения необходимо будет предоставить собственный tls.checkServerIdentity(), так как по умолчанию он будет пытаться проверить имя хоста/IP сервера по сертификату, но это не применимо для PSK, так как сертификата не будет. Более подробную информацию можно найти в RFC 4279.

      • ALPNProtocols: {string[]|Buffer[]|TypedArray[]|DataView[]|Buffer| TypedArray|DataView} Массив строк, Buffer, TypedArray или DataView, или один Buffer, TypedArray или DataView, содержащий поддерживаемые протоколы ALPN. Буфер должен иметь формат [len][name][len][name]..., например, '\x08http/1.1\x08http/1.0', где len байт - это длина следующего имени протокола. Передача массива обычно намного проще, например, ['http/1.1', 'http/1.0']. Протоколы, расположенные раньше в списке, имеют большее предпочтение, чем протоколы, расположенные позже.
    • servername: <string> Имя сервера для расширения SNI (Server Name Indication) TLS. Это имя узла, к которому осуществляется подключение, и оно должно быть именем узла, а не IP-адресом. Оно может использоваться сервером с несколькими хостами для выбора правильного сертификата для предоставления клиенту, см. опцию SNICallback в tls.createServer().

    • checkServerIdentity(servername, cert) <Function> Функция обратного вызова, которая будет использоваться (вместо встроенной функции tls.checkServerIdentity()) при проверке имени хоста сервера (или предоставленного servername, если оно задано явно) на соответствие сертификату. Метод должен возвращать <Error> при неудачной проверке. Метод должен возвращать undefined, если servername и cert проверены.

    • session <Buffer> Экземпляр Buffer, содержащий TLS-сессию.

    • minDHSize <number> Минимальный размер параметра DH в битах для принятия TLS-соединения. Если сервер предлагает параметр DH с размером меньше, чем minDHSize, TLS-соединение разрушается и выдается ошибка. По умолчанию: 1024.

    • highWaterMark: <number> Соответствует параметру читаемого потока highWaterMark. По умолчанию: 16 * 1024.

    • secureContext: Объект контекста TLS, созданный с помощью tls.createSecureContext(). Если secureContext не предоставлен, он будет создан путем передачи всего объекта options в tls.createSecureContext().

    • onread <Object> Если опция socket отсутствует, входящие данные хранятся в одном буфере и передаются в указанный callback, когда данные поступают на сокет, в противном случае опция игнорируется. Подробнее см. опцию onread в net.Socket.

    • ...: tls.createSecureContext() параметры, которые используются, если отсутствует параметр secureContext, в противном случае они игнорируются.

    • ...: Любая опция socket.connect(), которая еще не перечислена.

  • callback <Function>

  • Возвращает: {tls.TLSSocket}

Функция callback, если она указана, будет добавлена в качестве слушателя для события 'secureConnect'.

Функция tls.connect() возвращает объект tls.TLSSocket.

В отличие от API https, tls.connect() по умолчанию не включает расширение SNI (Server Name Indication), что может привести к тому, что некоторые серверы вернут неверный сертификат или вообще отклонят соединение. Чтобы включить SNI, установите параметр servername в дополнение к host.

Ниже показан клиент для примера сервера echo из tls.createServer():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Assumes an echo server that is listening on port 8000.
const tls = require('node:tls');
const fs = require('node:fs');

const options = {
    // Necessary only if the server requires client certificate authentication.
    key: fs.readFileSync('client-key.pem'),
    cert: fs.readFileSync('client-cert.pem'),

    // Necessary only if the server uses a self-signed certificate.
    ca: [fs.readFileSync('server-cert.pem')],

    // Necessary only if the server's cert isn't for "localhost".
    checkServerIdentity: () => {
        return null;
    },
};

const socket = tls.connect(8000, options, () => {
    console.log(
        'client connected',
        socket.authorized ? 'authorized' : 'unauthorized'
    );
    process.stdin.pipe(socket);
    process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', (data) => {
    console.log(data);
});
socket.on('end', () => {
    console.log('server ends connection');
});

tls.connect(path[, options][, callback])

Аналогично tls.connect(), за исключением того, что path может быть предоставлен в качестве аргумента вместо опции.

Опция path, если она указана, будет иметь приоритет над аргументом path.

tls.connect(port[, host][, options][, callback]).

Аналогично tls.connect(), за исключением того, что port и host могут быть предоставлены в качестве аргументов вместо опций.

Опция порта или хоста, если она указана, будет иметь приоритет над любым аргументом порта или хоста.

tls.createSecureContext([options])

  • options <Object>
    • ca {string|string[]|Buffer|Buffer[]} Опционально переопределяет доверенные сертификаты CA. По умолчанию доверяем известным ЦС, курируемым Mozilla. ЦС Mozilla полностью заменяются, если ЦС явно указаны с помощью этой опции. Значение может быть строкой или буфером, или массивом строк и/или буферов. Любая строка или Буфер может содержать несколько PEM CA, объединенных вместе. Для аутентификации соединения сертификат пирата должен быть связан цепочкой с ЦС, которому доверяет сервер. При использовании сертификатов, не имеющих цепочки с известным ЦС, ЦС сертификата должен быть явно указан как доверенный, иначе соединение не пройдет аутентификацию. Если пир использует сертификат, который не совпадает или не привязан к одному из ЦС по умолчанию, используйте опцию ca, чтобы предоставить сертификат ЦС, с которым сертификат пира может совпасть или привязаться. Для самоподписанных сертификатов сертификат является собственным ЦС и должен быть предоставлен. Для сертификатов в кодировке PEM поддерживаются следующие типы: "TRUSTED CERTIFICATE", "X509 CERTIFICATE" и "CERTIFICATE". См. также tls.rootCertificates.
    • cert {string|string[]|Buffer|Buffer[]} Цепочки сертификатов в формате PEM. Для каждого закрытого ключа должна быть предоставлена одна цепочка сертификатов. Каждая цепочка сертификатов должна состоять из сертификата в формате PEM для предоставленного закрытого ключа, за которым следуют промежуточные сертификаты в формате PEM (если они есть), по порядку, не включая корневой CA (корневой CA должен быть заранее известен peer, см. раздел ca). При предоставлении нескольких цепочек сертификатов, они не должны располагаться в том же порядке, что и их закрытые ключи в key. Если промежуточные сертификаты не будут предоставлены, peer не сможет проверить сертификат, и рукопожатие завершится неудачей.
    • sigalgs <string> Список поддерживаемых алгоритмов подписи, разделенный двоеточием. Список может содержать алгоритмы дайджеста (SHA256, MD5 и т.д.), алгоритмы открытого ключа (RSA-PSS, ECDSA и т.д.), комбинацию обоих (например, 'RSA+SHA384') или имена схем TLS v1.3 (например, rsa_pss_pss_sha512). Более подробную информацию смотрите в OpenSSL man pages.
    • ciphers <string> Спецификация набора шифров, заменяющая набор по умолчанию. Для получения дополнительной информации смотрите Изменение набора шифров TLS по умолчанию. Разрешенные шифры можно получить через tls.getCiphers(). Имена шифров должны быть написаны в верхнем регистре, чтобы OpenSSL мог их принять.
    • clientCertEngine <string> Имя механизма OpenSSL, который может предоставить сертификат клиента.
    • crl {string|string[]|Buffer|Buffer[]} CRL (списки отзыва сертификатов) в формате PEM.
    • dhparam <string> | <Buffer> 'auto' или пользовательские параметры Диффи-Хеллмана, необходимые для не-ECDHE perfect forward secrecy. Если параметры опущены или недействительны, они будут молча отброшены, и шифры DHE будут недоступны. ECDHE-базированный perfect forward secrecy будет по-прежнему доступен.
    • ecdhCurve <string> Строка, описывающая именованную кривую или список NID или имен кривых через двоеточие, например P-521:P-384:P-256, для использования при согласовании ключей ECDH. Установите значение auto для автоматического выбора кривой. Используйте crypto.getCurves() для получения списка доступных имен кривых. В последних выпусках openssl ecparam -list_curves будет также отображать имя и описание каждой доступной эллиптической кривой. По умолчанию: tls.DEFAULT_ECDH_CURVE.
    • honorCipherOrder <boolean> Попытка использовать предпочтения набора шифров сервера вместо предпочтений клиента. Когда true, вызывает установку SSL_OP_CIPHER_SERVER_PREFERENCE в secureOptions, подробнее см. в OpenSSL Options.
    • key {string|string[]|Buffer|Buffer[]|Object[]} Закрытые ключи в формате PEM. PEM позволяет шифровать закрытые ключи. Зашифрованные ключи будут расшифрованы с помощью options.passphrase. Несколько ключей, использующих различные алгоритмы, могут быть предоставлены либо как массив незашифрованных ключевых строк или буферов, либо как массив объектов в виде {pem: <string|buffer>[, passphrase: <string>]}. Форма объекта может встречаться только в массиве. Объект object.passphrase является необязательным. Зашифрованные ключи будут расшифрованы с помощью object.passphrase, если он указан, или options.passphrase, если его нет.
    • privateKeyEngine <string> Имя механизма OpenSSL для получения закрытого ключа. Должно использоваться вместе с privateKeyIdentifier.
    • privateKeyIdentifier <string> Идентификатор закрытого ключа, управляемого движком OpenSSL. Должен использоваться вместе с privateKeyEngine. Не следует задавать вместе с key, поскольку обе опции определяют закрытый ключ по-разному.
    • maxVersion <string> Опционально задает максимальную разрешенную версию TLS. Одна из TLSv1.3, TLSv1.2, TLSv1.1 или TLSv1. Не может быть указан вместе с опцией secureProtocol; используйте либо одно, либо другое. По умолчанию: tls.DEFAULT_MAX_VERSION.
    • minVersion <string> Опционально задает минимальную разрешенную версию TLS. Одна из TLSv1.3, TLSv1.2, TLSv1.1 или TLSv1. Не может быть указан вместе с опцией secureProtocol; используйте либо одно, либо другое. Избегайте установки значения меньше, чем TLSv1.2, но это может потребоваться для совместимости. По умолчанию: tls.DEFAULT_MIN_VERSION.
    • passphrase <string> Общая парольная фраза, используемая для одного закрытого ключа и/или PFX.
    • pfx {string|string[]|Buffer|Buffer[]|Object[]} PFX или PKCS12 кодированный закрытый ключ и цепочка сертификатов. pfx является альтернативой предоставлению key и cert по отдельности. PFX обычно зашифрован, если это так, passphrase будет использоваться для его расшифровки. Несколько PFX могут быть предоставлены либо как массив незашифрованных буферов PFX, либо как массив объектов в форме {buf: <string|buffer>[, passphrase: <string>]}. Форма объекта может встречаться только в массиве. Объект object.passphrase является необязательным. Зашифрованный PFX будет расшифрован с помощью object.passphrase, если он указан, или options.passphrase, если его нет.
    • secureOptions <number> Опционально влияет на поведение протокола OpenSSL, что обычно не является необходимым. Это следует использовать осторожно, если вообще возможно! Значение - числовая битовая маска опций SSL_OP_* из OpenSSL Options.
    • secureProtocol <string> Устаревший механизм выбора используемой версии протокола TLS, не поддерживает независимый контроль минимальной и максимальной версии, а также не поддерживает ограничение протокола до TLSv1.3. Вместо этого используйте minVersion и maxVersion. Возможные значения перечислены как SSL_METHODS, используйте имена функций как строки. Например, используйте 'TLSv1_1_method' для принудительного использования TLS версии 1.1, или 'TLS_method' для разрешения любой версии протокола TLS вплоть до TLSv1.3. Не рекомендуется использовать TLS версии менее 1.2, но это может потребоваться для совместимости. По умолчанию: нет, см. minVersion.
    • sessionIdContext <string> Непрозрачный идентификатор, используемый серверами для того, чтобы состояние сеанса не было общим для разных приложений. Не используется клиентами.
    • ticketKeys: <Buffer> 48 байт криптографически сильных псевдослучайных данных. Дополнительную информацию см. в Возобновление сеанса.
    • sessionTimeout <number> Количество секунд, после которого TLS-сессия, созданная сервером, больше не будет возобновляться. Дополнительную информацию смотрите в разделе Возобновление сеанса. По умолчанию: 300.

tls.createServer() устанавливает значение опции honorCipherOrder по умолчанию на true, другие API, создающие безопасные контексты, оставляют его без установки.

tls.createServer() использует 128-битное усеченное значение хэша SHA1, сгенерированное из process.argv в качестве значения по умолчанию опции sessionIdContext, другие API, создающие безопасные контексты, не имеют значения по умолчанию.

Метод tls.createSecureContext() создает объект SecureContext. Он может использоваться в качестве аргумента в некоторых API tls, таких как server.addContext(), но не имеет публичных методов. Конструктор tls.Server и метод tls.createServer() не поддерживают опцию secureContext.

Ключ необходим для шифров, использующих сертификаты. Для его получения можно использовать либо key, либо pfx.

Если опция ca не указана, то Node.js по умолчанию будет использовать публично доверенный список CA от Mozilla.

Пользовательские параметры DHE не рекомендуется использовать в пользу новой опции dhparam: 'auto'. При установке значения 'auto', известные параметры DHE достаточной силы будут выбираться автоматически. В противном случае, при необходимости, можно использовать openssl dhparam для создания пользовательских параметров. Длина ключа должна быть больше или равна 1024 битам, иначе будет выдана ошибка. Хотя 1024 бита допустимо, используйте 2048 бит или больше для более надежной защиты.

tls.createSecurePair([context][, isServer][, requestCert][, rejectUnauthorized][, options])

Стабильность: 0 – устарело или набрало много негативных отзывов

Используйте tls.TLSSocket вместо этого.

  • context <Object> Объект безопасного контекста, возвращаемый функцией tls.createSecureContext().
  • isServer <boolean> true для указания того, что данное TLS-соединение должно быть открыто как сервер.
  • requestCert <boolean> true для указания того, должен ли сервер запрашивать сертификат у подключающегося клиента. Применяется, только если isServer равно true.
  • rejectUnauthorized <boolean> Если не false, сервер автоматически отклоняет клиентов с недействительными сертификатами. Применяется только в том случае, если isServer имеет значение true.
  • options
    • enableTrace: См. tls.createServer()
    • secureContext: Объект контекста TLS из tls.createSecureContext()
    • isServer: Если true, то TLS сокет будет инстанцирован в серверном режиме. По умолчанию: false.
    • server {net.Server} Экземпляр net.Server
    • requestCert: См. tls.createServer()
    • rejectUnauthorized: См. tls.createServer()
    • ALPNProtocols: См. tls.createServer()
    • SNICallback: См. tls.createServer()
    • session <Buffer> Экземпляр Buffer, содержащий сессию TLS.
    • requestOCSP <boolean> Если true, указывает, что расширение запроса статуса OCSP будет добавлено в клиентский привет и событие 'OCSPResponse' будет испущено на сокете перед установлением безопасного соединения.

Создает новый объект защищенной пары с двумя потоками, один из которых читает и записывает зашифрованные данные, а другой читает и записывает данные с открытым текстом. Как правило, зашифрованный поток направляется в/из входящего потока зашифрованных данных, а поток с открытым текстом используется в качестве замены исходного зашифрованного потока.

tls.createSecurePair() возвращает объект tls.SecurePair со свойствами cleartext и encrypted потоков.

Использование cleartext имеет тот же API, что и tls.TLSSocket.

Метод tls.createSecurePair() теперь устарел в пользу tls.TLSSocket(). Например, код:

1
2
3
pair = tls.createSecurePair(/* ... */);
pair.encrypted.pipe(socket);
socket.pipe(pair.encrypted);

может быть заменен на:

1
secureSocket = tls.TLSSocket(socket, options);

где secureSocket имеет тот же API, что и pair.cleartext.

tls.createServer([options][, secureConnectionListener])

  • options <Object>

    • ALPNProtocols: {string[]|Buffer[]|TypedArray[]|DataView[]|Buffer| TypedArray|DataView} Массив строк, Buffer, TypedArray или DataView, или один Buffer, TypedArray или DataView, содержащий поддерживаемые протоколы ALPN. Буфер должен иметь формат [len][name][len][name]..., например, 0x05hello0x05world, где первый байт - это длина следующего имени протокола. Передача массива обычно намного проще, например, ['hello', 'world']. (Протоколы должны быть упорядочены по их приоритету).

    • clientCertEngine <string> Имя механизма OpenSSL, который может предоставить сертификат клиента.

    • enableTrace <boolean> Если true, то tls.TLSSocket.enableTrace() будет вызываться при новых соединениях. Трассировка может быть включена после установления защищенного соединения, но эта опция должна быть использована для отслеживания установки защищенного соединения. По умолчанию: false.

    • handshakeTimeout <number> Прервать соединение, если SSL/TLS квитирование не завершится за указанное количество миллисекунд. Ошибка 'tlsClientError выдается на объект tls.Server всякий раз, когда квитирование завершается. По умолчанию: 120000 (120 секунд).

    • rejectUnauthorized <boolean> Если не false, то сервер будет отклонять любое соединение, которое не авторизовано с помощью списка предоставленных CA. Эта опция действует, только если requestCert имеет значение true. По умолчанию: true.

    • requestCert <boolean> Если true, сервер будет запрашивать сертификат у подключающихся клиентов и пытаться проверить этот сертификат. По умолчанию: false.

    • sessionTimeout <number> Число секунд, после которого TLS-сессия, созданная сервером, больше не будет возобновляться. Дополнительную информацию смотрите в Возобновление сеанса. По умолчанию: 300.

    • SNICallback(servername, callback) <Function> Функция, которая будет вызвана, если клиент поддерживает расширение SNI TLS. При вызове будут переданы два аргумента: servername и callback. callback - это обратный вызов по ошибке, который принимает два необязательных аргумента: error и ctx. ctx, если предоставлен, является экземпляром SecureContext. tls.createSecureContext() можно использовать для получения соответствующего SecureContext. Если callback будет вызван с фальшивым аргументом ctx, будет использован безопасный контекст сервера по умолчанию. Если SNICallback не был предоставлен, будет использован стандартный обратный вызов с высокоуровневым API (см. ниже).

    • ticketKeys: <Buffer> 48 байт криптографически сильных псевдослучайных данных. Дополнительную информацию см. в Возобновление сеанса.

    • pskCallback: <Function>

      • сокет: {tls.TLSSocket} экземпляр сервера tls.TLSSocket для этого соединения.
      • identity: <string> параметр идентификации, отправленный клиентом.
      • Возвращает: {Buffer|TypedArray|DataView} предварительный общий ключ, который должен быть либо буфером, либо null для остановки процесса согласования. Возвращаемый PSK должен быть совместим с дайджестом выбранного шифра.

      При согласовании TLS-PSK (pre-shared keys) эта функция вызывается с идентификатором, предоставленным клиентом. Если возвращаемое значение равно null, то процесс переговоров будет остановлен, а другой стороне будет отправлено сообщение "unknown_psk_identity". Если сервер хочет скрыть тот факт, что идентификатор PSK не был известен, обратный вызов должен предоставить некоторые случайные данные в качестве psk, чтобы соединение не было установлено с сообщением "decrypt_error" до завершения переговоров. Шифры PSK отключены по умолчанию, и использование TLS-PSK требует явного указания набора шифров с помощью опции ciphers. Более подробную информацию можно найти в RFC 4279.

    • pskIdentityHint <string> необязательная подсказка для отправки клиенту, чтобы помочь с выбором идентификатора во время согласования TLS-PSK. Будет игнорироваться в TLS 1.3. При неудачной попытке установить pskIdentityHint будет выдана ошибка 'tlsClientError' с кодом 'ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED'.

    • ...: Может быть предоставлена любая опция tls.createSecureContext(). Для серверов обычно требуются опции идентификации (pfx, key/cert или pskCallback).

    • ...: Может быть предоставлена любая опция net.createServer().

  • secureConnectionListener <Function>

  • Возвращает: {tls.Server}

Создает новый tls.Server. Слушатель secureConnectionListener, если он указан, автоматически устанавливается в качестве слушателя события 'secureConnection'.

Параметры ticketKeys автоматически разделяются между работниками модуля node:cluster.

Ниже показан простой эхо-сервер:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const tls = require('node:tls');
const fs = require('node:fs');

const options = {
    key: fs.readFileSync('server-key.pem'),
    cert: fs.readFileSync('server-cert.pem'),

    // This is necessary only if using client certificate authentication.
    requestCert: true,

    // This is necessary only if the client uses a self-signed certificate.
    ca: [fs.readFileSync('client-cert.pem')],
};

const server = tls.createServer(options, (socket) => {
    console.log(
        'server connected',
        socket.authorized ? 'authorized' : 'unauthorized'
    );
    socket.write('welcome!\n');
    socket.setEncoding('utf8');
    socket.pipe(socket);
});
server.listen(8000, () => {
    console.log('server bound');
});

Сервер можно протестировать, подключившись к нему с помощью примера клиента из tls.connect().

tls.getCiphers().

Возвращает массив с именами поддерживаемых шифров TLS. Имена приведены в нижнем регистре по историческим причинам, но должны быть приведены в верхнем регистре для использования в опции ciphers в tls.createSecureContext().

Не все поддерживаемые шифры включены по умолчанию. Смотрите Изменение набора шифров TLS по умолчанию.

Имена шифров, начинающиеся с tls_, предназначены для TLSv1.3, все остальные - для TLSv1.2 и ниже.

1
console.log(tls.getCiphers()); // ['aes128-gcm-sha256', 'aes128-sha', ...]

tls.rootCertificates

Неизменяемый массив строк, представляющих корневые сертификаты (в формате PEM) из хранилища ЦС Mozilla, поставляемого текущей версией Node.js.

Хранилище CA, поставляемое Node.js, представляет собой снимок хранилища Mozilla CA, который фиксируется на момент выпуска. Он идентичен на всех поддерживаемых платформах.

tls.DEFAULT_ECDH_CURVE

Имя кривой по умолчанию, используемое для согласования ключей ECDH на сервере tls. Значение по умолчанию - 'auto'. Дополнительную информацию смотрите в tls.createSecureContext().

tls.DEFAULT_MAX_VERSION

  • <string> Значение по умолчанию опции maxVersion в tls.createSecureContext(). Ей может быть присвоена любая из поддерживаемых версий протокола TLS, TLSv1.3, TLSv1.2, TLSv1.1 или TLSv1. По умолчанию: 'TLSv1.3', если не изменено с помощью опций CLI. Использование --tls-max-v1.2 устанавливает значение по умолчанию 'TLSv1.2'. Использование --tls-max-v1.3 устанавливает значение по умолчанию 'TLSv1.3'. Если указано несколько опций, используется максимальная.

tls.DEFAULT_MIN_VERSION

  • <string> Значение по умолчанию опции minVersion в tls.createSecureContext(). Ей может быть присвоена любая из поддерживаемых версий протокола TLS, TLSv1.3, TLSv1.2, TLSv1.1 или TLSv1. По умолчанию: 'TLSv1.2', если не изменено с помощью опций CLI. Использование --tls-min-v1.0 устанавливает значение по умолчанию 'TLSv1'. Использование --tls-min-v1.1 устанавливает значение по умолчанию 'TLSv1.1'. Использование --tls-min-v1.3 устанавливает значение по умолчанию TLSv1.3. Если указано несколько опций, то используется наименьшая минимальная.

tls.DEFAULT_CIPHERS

  • <string> Значение по умолчанию опции ciphers в tls.createSecureContext(). Ему может быть присвоен любой из поддерживаемых шифров OpenSSL. По умолчанию используется содержимое crypto.constants.defaultCoreCipherList, если не изменено с помощью опций CLI с помощью --tls-default-ciphers.

Комментарии