В предыдущей статье мы запустили Kafka с аутентификацией посредством протокола SASL_PLAIN с механизмом PLAIN.
Настало время разобраться с SSL.
В этой статье мы подготовим все необходимое для последующей настройки соединения SSL в Kafka.
Предыдущая статья.Следующая статья.
Полный список статей по теме тут.
Заходите в наш телеграмм канал — Enterprise Stack Helper! Делитесь опытом или задавайте вопросы, если что-то непонятно.
Репозитории с примерам из статей по способам аутентификаци и авторизации — https://github.com/BlockWit/kafka-security-examples.
SSL
Немного теории
Мы не будем детально рассматривать SSL. Отметим основные для нас вещи:
- SSL формирует шифрованный канал между клиентом и сервером
- Серверная сторона диалога всегда аутентифицируется перед клиентом. Т.е. клиент может проверить что сервер, тот за кого он себя выдает. Сервер тоже может проверить клиента, но это не обязательно.
Давайте разберем каким образом клиент проверяет что сервер является тем, за кого себя выдает. У сервера есть пара — открытый/закрытый ключ. При этом:
- Закрытым ключом сервер может расшифровать данные. Закрытый ключ находится только у сервера!
- Открытым ключом любой может зашифровать данные. Открытый ключ может распространяться свободно.
- Сервер отправляет публичный ключ клиенту.
Сервер, является тем, за кого себя выдает в том случае, если у него есть верный приватный ключ и публичные ключи. Как происходит взаимодействие клиента и сервера:
- Клиент запрашивает публичный ключ у сервера
- Клиент шифрует данные и отправляет серверу
- Сервер с помощью приватного ключа расшифровывает данные
Т.е. в этой схеме никто кроме обладателя приватного ключа не сможет расшифровать наши данные. Однако есть важная деталь.
Сначала сервер отправляет публичный ключ. А как же тогда определить, что именно интересный нам сервер отправил ключ, а не злоумышленник, который перехватил наш запрос до сервера. Ведь злоумышленник может отправить свой публичный ключ! На самом деле публичный ключ выдается в виде сертификата. В сертификате указано:
- Кому он выдан (IP или доменное имя). Представьте, что сертификат выдан Алисе. А Боб спрашивает у Алисы публичный сертификат. Допустим злоумышленник Вася перехватывает запрос Боба и отправляет Бобу свой сертификат. Боб увидит, что сертификат выдан на имя Васи. Т.е. Боб получил не тот сертификат, ведь он ожидал сертификат от Алисы. Поэтому хитрая схема Васи не пройдет.
- Кем он выдан и подписан! Из пункта 1 мы поняли, что сертификат выдается на конкретное имя. И чтобы злоумышленник не смог сделать свой сертификат, сертификаты подписываются доверенными лицами. Т.е. теми кому мы доверяем.
Сертификаты бывают двух типов:
- Подписанные и выданные сертификационными центрами — в этом случае сертификаты выдаются специальными сертификационными центрами и подписываются ключами этих центров. Таким образом любой может проверить что данный сертификат выдан авторизованным центром для данного домена или IP.
- Самоподписные — когда сертификат выпускается вами же, в этом случае доверять такому сертификату другие не могут.
Таким образом аутентификация происходит следующим образом:
- Клиент запрашивает сертификат у сервера
- Сервер отправляет сертификат с публичным ключом
- Клиент проверяет что сертификат выдан авторизованным центром. Т.е. запрашивает сертификат авторизованного центра с публичным ключом и проверяет что сертификат сервера подписан ключом авторизованного центра.
- Клиент проверяет что в сертификате указано имя сервера, к которому клиент обращается
- Клиент шифрует данные публичным ключом и отправляет серверу
- Сервер расшифровывает данные приватным ключом
Чего не хватает?
В этом алгоритме расшифровать данные может только сервер. Потому что только у него приватный ключ. И никому он передавать приватный ключ не может. Так а как же серверу отправлять шифрованные данные для клиента?
Очень просто. Клиент создает симметричный ключ. Им можно шифровать и расшифровывать сообщения. Этот ключ называется сеансовым. И уже этим ключ дальше клиент и сервер шифруют свою коммуникацию. Теперь наш алгоритм будет выглядеть так:
- Клиент запрашивает сертификат у сервера
- Сервер отправляет сертификат с публичным ключом
- Клиент проверяет что сертификат выдан авторизованным центром. Т.е. запрашивает сертификат авторизованного центра с публичным ключом и проверяет что сертификат сервера подписан ключом авторизованного центра.
- Клиент проверяет что в сертификате указано имя сервера, к которому клиент обращается
- Клиент создает сеансовый ключ
- Клиент шифрует сеансовый ключ публичным ключом сервера и отправляет серверу
- Сервер расшифровывает сеансовый ключ своим приватным ключом
- Теперь у клиента и у сервера есть сеансовый ключ. Клиент и сервер теперь шифруют и расшифровывают с помощью сеансового ключа передаваемые друг другу сообщения.
Где взять SSL сертификат
Если у Вас уже есть сертификат и приватный ключ то пропустите эту часть!
Из предыдущей части мы узнали, что нам нужен сертификат и приватный ключ сервера. Как мы уже знаем, сертификат должен быть выдан авторизованным центром. Однако, в целях разработки часто пользуются самоподписным сертификатом. Т.е. выпускают его самостоятельно. Однако, проверить такой сертификат нельзя . Но этого вполне достаточно для проверки корректности настройки SSL.
Стоит понимать, что при настройках по умолчанию клиент откажется устанавливать соединение с сервером на основании самоподписного сертификата. Ведь клиент не может проверить такой сертификат. Поэтому на клиенте потребуется выключить проверку. Однако, боевой сервер безусловно должен использовать сертификат, выпущенный авторизованным центром!
Итак, выпустим сертификат и приватный ключ:
1 |
openssl req -subj "/CN=localhost/" -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.pem |
Следует отметить, что сертификат должен содержать либо поле CN с hostname, либо SAN c IP или HOSTNAME. Порядок сверки сертификата:
- Берется имя или IP (в зависимости от того по IP обращались или по HOSTNAME) сервера
- Если есть SAN, то сверяем с ним, если нет то hostname с CA
Таким образом, если Вы обращались по IP а сертификат содержит только HOSTNAME, то сертификат будет считаться невалидным!
Не забывайте заменять localhost на свой если необходимо.
В результате у нас появятся два файла
- domain.pem — сертификат с публичным ключом
- domain.key — приватный ключ
Подготовим сертификат и приватный ключ к использованию в Kafka
У нас уже есть сертификат и приватный ключ. Казалось бы, можно на этом успокоиться. Однако, Kafka капризная и ей нужен свой формат сертификата и приватного ключа. А именно, Kafka поддерживает так называемые хранилища сертификатов в форматах JKS и PKCS12.
Хранилище сертификатов — это файл, который может в себе содержать ключи и сертификаты и шифруется паролем.
Итак, нам нужно два хранилища:
- Для сервера c приватным и публичным ключом
- Для клиента с публичным ключом
Создадим хранилища для клиента и сервера. Будем считать, что сертификат у нас в формате pem. Т.е. сертификат и приватный ключ создан, как описано в предыдущей части.
Сертификат в формате pem может также иметь расширения .pem, .crt, .cer, и .key. Что касается других форматов, то их можно конвертировать.
- DER в PEM
1 openssl x509 -inform der -in certificate.cer -out certificate.pem- P7B в PEM
1 openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer- PFX в PEM
1 openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
Создание хранилища сертификата и приватного ключа для сервера. Во время создания Вам нужно придумать и сохранить пароль для хранилища.
1 |
openssl pkcs12 -export -out server.keystore.p12 -in domain.pem -inkey domain.key |
Создание хранилища сертификата для клиента. Во время создания Вам нужно придумать и сохранить пароль для этого хранилища.
1 |
keytool -keystore client.truststore.jks -import -file domain.pem |
После выполнения всех команд у нас будут:
- server.keystore.p12 — хранилище сертификата и приватного ключа для сервера. И пароль к нему.
- client.truststore.jks — хранилище сертификата для клиента. И пароль к нему.
Резюме
В этой статье мы подготовили сертификат сервера, приватный ключ, хранилище для клиента и для сервера.
В следующей статье мы узнаем, как настраивать протокол SSL для защиты канала без аутентификации в Kafka.
Предыдущая статья. Следующая статья.
Полный список статей по теме тут.
Заходите в наш телеграмм канал — Enterprise Stack Helper! Делитесь опытом или задавайте вопросы, если что-то непонятно.
Репозитории с примерам из статей по способам аутентификаци и авторизации — https://github.com/BlockWit/kafka-security-examples.