Learning Platform
Глоссарий Troubleshooting
Урок 10.02 · 30 мин
Продвинутый
SSLTLSmTLSKeystoreTruststoreCertificateHandshake

SSL/TLS Mutual Authentication

Kafka использует TLS для двух целей: шифрования канала (никто не читает трафик в сети) и, опционально, взаимной аутентификации (mutual TLS, mTLS — обе стороны доказывают идентичность сертификатом). Понять разницу между этими режимами, а также как работают keystore и truststore — фундаментальный навык для любого Kafka operator.


TLS vs SSL: терминология

Название конфига в Kafka начинается с ssl.*, но реально используется TLS (Transport Layer Security). SSL был deprecated давно: SSL 2.0 — 1995, SSL 3.0 — 1996, TLS 1.0 — 1999. Kafka 4.0 поддерживает TLS 1.2 и TLS 1.3 (рекомендуется TLS 1.3).

Два режима работы:

  • One-way TLS: только брокер предоставляет сертификат. Клиент проверяет подлинность брокера (защита от MITM), но брокер не знает, кто клиент. Шифрование есть, аутентификации клиента — нет. ssl.client.auth=none.
  • Mutual TLS (mTLS): обе стороны предоставляют сертификат. Брокер аутентифицирует клиента по CN (Common Name) или SAN (Subject Alternative Name) сертификата — это становится Kafka principal. ssl.client.auth=required.

Keystore и Truststore: два хранилища

Каждая сторона (брокер и каждый клиент) поддерживает два JKS-хранилища:

Keystore vs Truststore
Каждая сторона — брокер и клиент — имеет собственный keystore и truststore
Keystore (JKS)Содержит приватный ключ и собственный сертификат стороны. Думайте об этом как о паспорте: это ваше удостоверение личности, которое вы предъявляете другой стороне для аутентификации. Приватный ключ НИКОГДА не покидает keystore. Брокер предъявляет keystore клиенту при любом TLS-соединении.
Truststore (JKS)Содержит сертификаты доверенных Certificate Authority (CA). Используется для проверки сертификата, предъявленного другой стороной. Думайте об этом как о списке признанных государств: если сертификат другой стороны подписан CA из вашего truststore — вы ему доверяете. Клиент использует truststore для проверки сертификата брокера.

При mTLS:

  • Брокер предъявляет свой keystore → клиент проверяет через свой truststore.
  • Клиент предъявляет свой keystore → брокер проверяет через свой truststore.
  • Оба truststore должны содержать сертификат CA, которым подписаны сертификаты обеих сторон.

Создание сертификатов: пошаговый гайд

Типичный workflow: создать собственный CA, подписать им сертификаты брокеров и клиентов. В production используйте корпоративный CA или управляемый сервис (AWS ACM, HashiCorp Vault).

Шаг 1: Создать CA (Certificate Authority)

openssl req -new -x509 \
  -keyout ca-key.pem -out ca-cert.pem \
  -days 3650 \
  -subj "/C=RU/O=KafkaCA/CN=kafka-ca" \
  -passout pass:ca-password

Шаг 2: Создать keystore для брокера (с самоподписанным сертификатом)

keytool -genkey \
  -keystore broker.keystore.jks \
  -alias broker \
  -validity 3650 \
  -keyalg RSA -keysize 2048 \
  -dname "CN=broker1.example.com,O=Kafka,C=RU" \
  -storepass keystore-password \
  -keypass key-password \
  -ext SAN=dns:broker1.example.com,dns:broker2.example.com

Шаг 3: Создать CSR (Certificate Signing Request)

keytool -certreq \
  -keystore broker.keystore.jks \
  -alias broker \
  -file broker.csr \
  -storepass keystore-password

Шаг 4: Подписать CSR сертификатом CA

openssl x509 -req \
  -CA ca-cert.pem -CAkey ca-key.pem \
  -in broker.csr -out broker-signed.pem \
  -days 3650 -CAcreateserial \
  -passin pass:ca-password

Шаг 5: Импортировать CA-сертификат в keystore брокера

keytool -importcert \
  -keystore broker.keystore.jks \
  -alias CARoot \
  -file ca-cert.pem \
  -storepass keystore-password \
  -noprompt

Шаг 6: Импортировать подписанный сертификат в keystore брокера

keytool -importcert \
  -keystore broker.keystore.jks \
  -alias broker \
  -file broker-signed.pem \
  -storepass keystore-password

Шаг 7: Создать truststore с CA-сертификатом

keytool -importcert \
  -keystore broker.truststore.jks \
  -alias CARoot \
  -file ca-cert.pem \
  -storepass truststore-password \
  -noprompt

Повторите аналогичный процесс для клиента: создайте client.keystore.jks и client.truststore.jks. Клиентский truststore содержит тот же CA-сертификат — клиент доверяет брокерам, подписанным этим CA.

TIP

В production используйте сертификаты с SAN (Subject Alternative Name), а не только CN. SAN позволяет указать несколько hostname и IP-адресов в одном сертификате. keytool поддерживает -ext SAN=dns:broker1.example.com,dns:broker2.example.com,ip:10.0.1.1. Без SAN hostname verification выдаёт предупреждение или ошибку в современных JDK.


Broker config для SSL

# Listener с SSL
listeners=SSL://0.0.0.0:9093
advertised.listeners=SSL://broker1.example.com:9093

# Broker keystore
ssl.keystore.location=/etc/kafka/ssl/broker.keystore.jks
ssl.keystore.password=keystore-password
ssl.key.password=key-password

# Broker truststore (для проверки клиентских сертификатов)
ssl.truststore.location=/etc/kafka/ssl/broker.truststore.jks
ssl.truststore.password=truststore-password

# Mutual TLS: клиент ОБЯЗАН предоставить сертификат
ssl.client.auth=required

# Минимальная версия TLS (рекомендуется TLSv1.3)
ssl.enabled.protocols=TLSv1.3,TLSv1.2

# Hostname verification (обязательно в production)
ssl.endpoint.identification.algorithm=https

Client config для SSL

# Клиент подключается через SSL
security.protocol=SSL

# Client keystore (для mTLS: клиент предъявляет свой сертификат)
ssl.keystore.location=/etc/kafka/ssl/client.keystore.jks
ssl.keystore.password=client-keystore-password
ssl.key.password=client-key-password

# Client truststore (для проверки сертификата брокера)
ssl.truststore.location=/etc/kafka/ssl/client.truststore.jks
ssl.truststore.password=client-truststore-password
WARNING

ssl.client.auth=required включает mutual TLS: клиент ОБЯЗАН предоставить сертификат. Если client keystore не настроен или пустой, соединение будет отклонено с ошибкой “peer not authenticated”. Для одностороннего TLS (только шифрование) используйте ssl.client.auth=none.


TLS Handshake: визуальный поток

SSL/TLS Mutual Authentication: Handshake
Kafka ClientКлиент (producer или consumer). Хранит: client.keystore.jks (приватный ключ + сертификат клиента) и client.truststore.jks (CA-сертификат для проверки сервера). Конфиг: security.protocol=SSL, ssl.keystore.location, ssl.truststore.location.
Kafka BrokerБрокер. Хранит: server.keystore.jks (приватный ключ + сертификат брокера) и server.truststore.jks (CA-сертификат для проверки клиентов). ssl.client.auth=required включает mTLS. ssl.endpoint.identification.algorithm=https — проверка hostname (по умолчанию включена в Kafka 3.0+).
1
ClientHello
Клиент отправляет: поддерживаемые версии TLS (TLSv1.2, TLSv1.3), список cipher suites (TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, ...), случайное число (client random). Это первый пакет handshake — инициирует согласование параметров.
ClientHelloКлиент отправляет: поддерживаемые версии TLS (TLSv1.2, TLSv1.3), список cipher suites (TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, ...), случайное число (client random). Это первый пакет handshake — инициирует согласование параметров.
2
ServerHello + Certificate (+ CertificateRequest)Брокер отвечает: выбранная версия TLS и cipher suite, сертификат брокера из server.keystore.jks, случайное число (server random). Если ssl.client.auth=required, брокер также отправляет CertificateRequest — запрос сертификата клиента. Без mTLS CertificateRequest не отправляется.
3
Client verifies broker certificateКлиент проверяет сертификат брокера: (1) Подпись CA из client.truststore.jks — если CA не в truststore, handshake прерывается. (2) Срок действия — если сертификат истёк, отказ. (3) Hostname verification (ssl.endpoint.identification.algorithm=https) — CN или SAN сертификата должен совпадать с hostname брокера. Отключить: ssl.endpoint.identification.algorithm='' (не рекомендуется в production).
4
ClientCertificate + ClientKeyExchange
mTLS: клиент отправляет свой сертификат из client.keystore.jks (ответ на CertificateRequest). Также отправляет ClientKeyExchange для установки pre-master secret (при RSA) или DH key share (при ECDHE). CertificateVerify доказывает владение приватным ключом. Без ssl.client.auth=required этот шаг пропускается — one-way TLS.
ClientCertificate + ClientKeyExchangemTLS: клиент отправляет свой сертификат из client.keystore.jks (ответ на CertificateRequest). Также отправляет ClientKeyExchange для установки pre-master secret (при RSA) или DH key share (при ECDHE). CertificateVerify доказывает владение приватным ключом. Без ssl.client.auth=required этот шаг пропускается — one-way TLS.
5
Broker verifies client certificateБрокер проверяет сертификат клиента: (1) Подпись CA из server.truststore.jks. (2) Срок действия. CN или SAN из сертификата клиента становится Kafka principal для ACL авторизации — например, CN=alice → User:alice. Это bridge между TLS identity и Kafka ACL principal.
6
Encrypted Channel (Finished)Handshake завершён. Обе стороны обменялись Finished сообщениями (зашифрованными session key). Все дальнейшие данные (ProduceRequest, FetchRequest, metadata) передаются через зашифрованный канал. Cipher suite определяет алгоритм шифрования (AES-256-GCM) и MAC. Session resumption (TLS session tickets) позволяет повторно использовать ключи без полного handshake.
Encrypted Channel (Finished)Handshake завершён. Обе стороны обменялись Finished сообщениями (зашифрованными session key). Все дальнейшие данные (ProduceRequest, FetchRequest, metadata) передаются через зашифрованный канал. Cipher suite определяет алгоритм шифрования (AES-256-GCM) и MAC. Session resumption (TLS session tickets) позволяет повторно использовать ключи без полного handshake.
Keystore (JKS)ssl.keystore.locationJava KeyStore: хранит приватный ключ и сертификат владельца. Защищён паролем (ssl.keystore.password). Каждая сторона (клиент и брокер) имеет свой keystore. keytool -genkey создаёт пару ключей. keytool -certreq создаёт CSR для подписи CA. При ротации сертификата: создайте новый keystore, обновите брокер/клиент без downtime (rolling restart).
Truststore (JKS)ssl.truststore.locationJava TrustStore: хранит сертификаты доверенных CA (Certificate Authority). Используется для проверки сертификатов другой стороны. keytool -importcert -alias ca-root -file ca-cert.pem добавляет CA. Если truststore не содержит CA, подписавший сертификат другой стороны — handshake fails с SSLHandshakeException. Общий CA для клиентов и брокеров упрощает управление.
ssl.client.authrequired | requested | noneУправляет mTLS на брокере. none: one-way TLS (только сервер аутентифицируется). requested: брокер запрашивает клиентский сертификат, но не требует. required: mTLS — клиент ОБЯЗАН предоставить сертификат, иначе handshake failed. В production с ACL: используйте required для строгой аутентификации клиентов.

Диаграмма выше показывает полный TLS handshake с mTLS. Ключевые моменты:

  1. ClientHello: клиент отправляет список поддерживаемых версий TLS и cipher suites.
  2. ServerHello + Certificate: брокер выбирает cipher suite и отправляет свой сертификат из keystore. При mTLS — запрашивает сертификат клиента (CertificateRequest).
  3. Проверка брокерского сертификата: клиент проверяет подпись через свой truststore.
  4. ClientCertificate: при mTLS клиент отправляет свой сертификат из keystore.
  5. Проверка клиентского сертификата: брокер проверяет подпись через свой truststore. CN/SAN сертификата становится Kafka principal (например, User:alice).
  6. Encrypted channel: после завершения handshake весь Kafka-трафик зашифрован.

ssl.endpoint.identification.algorithm: hostname verification

По умолчанию Kafka 3.0+ включает hostname verification. Это означает, что hostname в сертификате брокера (CN или SAN) должен совпадать с hostname, к которому подключается клиент. Без этого возможна атака Man-in-the-Middle: злоумышленник подменяет брокер своим сервером с другим сертификатом.

# Hostname verification включена (рекомендуется)
ssl.endpoint.identification.algorithm=https

# Отключить hostname verification (ТОЛЬКО для локального dev с self-signed cert на localhost)
ssl.endpoint.identification.algorithm=

Troubleshooting SSL

Три самые частые ошибки и их причины:

“SSL handshake failed”

  • Причины: несовместимые TLS версии (брокер требует TLSv1.3, клиент поддерживает только TLSv1.2); несовместимые cipher suites; сертификат истёк.
  • Диагностика: openssl s_client -connect broker1:9093 -tls1_3 — увидите handshake подробно.

“peer not authenticated”

  • Причины: ssl.client.auth=required на брокере, а клиент не предоставил сертификат (keystore не настроен или пустой).
  • Решение: убедитесь, что client keystore содержит валидный сертификат, подписанный CA из broker truststore.

“certificate unknown” / “PKIX path building failed”

  • Причины: CA-сертификат не добавлен в truststore; промежуточные CA не включены в цепочку сертификатов.
  • Решение: добавьте весь chain (CA + intermediate CAs) в truststore обеих сторон.

Ключевые выводы

  1. SSL в Kafka = TLS. Поддерживаются TLS 1.2 и TLS 1.3. Config-ключи начинаются с ssl.*.
  2. Keystore — ваш “паспорт” (приватный ключ + сертификат). Truststore — “список признанных паспортов” (сертификаты доверенных CA).
  3. ssl.client.auth=required включает mTLS: клиент аутентифицируется по CN/SAN своего сертификата.
  4. ssl.endpoint.identification.algorithm=https обязателен в production для защиты от MITM.
  5. При ошибке SSL: проверьте keystore/truststore обеих сторон, истечение сертификата, hostname verification.
Проверка знанийKnowledge check
Команда настроила SSL на Kafka-кластере. Один producer получает ошибку 'SSL handshake failed: peer not authenticated'. Какие три вещи нужно проверить?
ОтветAnswer
1. ssl.client.auth на брокере: если установлен required, а producer не предоставил client keystore (ssl.keystore.location не задан или keystore пустой) — broker отклоняет соединение. 2. Валидность и trust chain клиентского сертификата: CA, подписавший client keystore сертификат, должен быть в broker truststore. Без этого broker не может верифицировать подпись. 3. Срок действия сертификата: проверьте keytool -list -v -keystore client.keystore.jks — убедитесь, что сертификат не истёк (Valid from/until).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 3. Команда настраивает mTLS для Kafka-кластера. Брокер сконфигурирован с ssl.client.auth=required. Producer получает ошибку 'SSL handshake failed: peer not authenticated'. Конфигурация producer: security.protocol=SSL, ssl.truststore.location=... (корректный). ssl.keystore.location не указан. Почему ошибка и что исправить?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6