Если бы кто-то создал кнопку «Сделать безопасно», то заработал бы миллиарды. Но увы — такой не существует, приходится всё делать вручную.

Привет, Хабр! Меня зовут Анна Лучник. Последние два десятилетия я реализую сложные и безопасные ИТ-проекты — прошла путь от консультанта и архитектора, до директора по ИБ и CIO. Была на стороне интегратора, вендора, заказчика. Видела с разных ракурсов, как всё может работать и ломаться, и где могут скрываться опасности.

Эта статья написана по мотивам моего доклада для DevOps Conf. Сразу честно: рецептов вроде «вот конфиг, скопируй и будет безопасно» здесь не будет. В отличие от Midjourney, где уже почти внедрили кнопку «Сделать красиво», кнопки «Сделать безопасно» у нас всё ещё нет, и вряд ли появится. Зато в этом тексте будет практика, ситуации из жизни, архитектурные компромиссы и неочевидные уязвимости в конфигурациях. Конкретные команды вы и сами нагуглите — моя задача описать принципы работы и объяснить, какие конфиги нужно искать в разных ситуациях.

В этой статье расскажу:

  • От каких угроз может защитить внедрение Service Mesh в теории и на практике.

  • Какие конфигурации и решения обесценивают включение mTLS, на какие конфигурации стоит обратить внимание, чтобы всё корректно работало.

  • Поговорим о том, чем mTLS отличается от обычного TLS.

  • К каким сбоям и проблемам может привести режим strict mTLS. И что делать, чтобы безопасность на стала причиной того, что у нас ничего не работает. 

Зачем внедряют Service Mesh

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

Service Mesh это — инфраструктурный уровень, обеспечивающий взаимодействие между сервисами, и позволяющий реализовать дополнительные функции, без изменения кода микросервисов. И чаще всего Service Mesh определяют через функции, которые он реализует:

  • Безопасность (Zero Trust). 

  • Управление трафиком.

  • Наблюдаемость и мониторинг.

  • Устойчивость.

  • Поэтапное развёртывание разных версий приложений.

  • ...

Если вам Service Mesh нужен только для шифрования трафика, а всё остальное — ни к чему, то лучше использовать более эффективную и простую в конфигурировании альтернативу. Service Mesh стоит рассматривать как комплексное решение.

Варианты развёртывания Istio Service Mesh

Последние несколько лет существует два варианта развёртывания Service Mesh:

  1. Классический вариант, который существовал с самого начала. В этом варианте в каждый под добавляется дополнительный прокси (обычно Envoy).  Весь сетевой трафик пода (входящий и исходящий) проходит через этот прокси. На уровне Sidecar Proxy осуществляется установка защищённого соединения (mTLS), фильтрация трафика, аутентификация, авторизация, маршрутизация на уровне L7 (HTTP, gRPC и др.) и другие функции.

  1. Второй вариант был анонсирован в 2022 году. Он позволяет не добавлять Sidecar Proxy к каждому поду. Вместо этого используются ztunnel и Waypoint Proxy. Ztunnel (zero-trust tunnel) — работает на уровне L4, устанавливает mTLS-соединения между рабочими нагрузками и обеспечивает базовую маршрутизацию и безопасность. Waypoint Proxy — развертывается опционально для обработки L7-трафика, например, если требуется HTTP-маршрутизация или авторизация на основе контента.

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

В этой статье мы будем рассматривать коляски мотоцикла (sidecars), потому что более новый режим Ambient Mesh пока работает не во всех сложных сценариях, например, в мультикластерных и мультисетевых конфигурациях.

Mutual TLS

Большинство вопросов, связанных с безопасностью, касаются аутентификации и шифрования, а это всегда про ключи: где они хранятся, как выдаются, как могут быть скомпрометированы. Именно эти детали зачастую определяют уровень безопасности всей системы.

Mutual TLS (или mTLS) обеспечивает взаимную аутентификация, проверяя обе стороны соединения, а не только сервер, как в обычном TLS.

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

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

Сертификат — это просто файл, в котором лежит открытый ключ и определённый набор полей. Под всем этим стоит подпись удостоверяющего центра.

Для оценки подлинности сертификата проверяются такие атрибуты:

  1. Имя. Когда мы говорим об аутентификации, в первую очередь проверяется имя — это может быть что угодно: DNS-имя, email, URI. В контексте Service Mesh чаще всего это будет SPIFFE ID — уникальное имя сервиса в формате spiffe://... Мы проверяем, что это имя соответствует ожидаемому. А ещё по имени можно фильтровать запросы в рамках Service Mesh.

  2. Срок действия сертификата. До контейнеров это был ключевой атрибут, который всегда проверялся. На основании проверки принималось решение, валиден ли сертификат.

  3. Статус сертификата. Это внешнее по отношению к сертификату свойство. Сертификат можно отозвать, и это особенно важно, когда мы выдаём сертификаты пользователям, а не только сервисам. Пользователи — существа непредсказуемые: теряют токены, смарт-карты, сами сертификаты и закрытые ключи. С сервисами всё обычно спокойнее — они реже теряют сертификаты, но их могут украсть. И вот тут возникает проблема: в большинстве реализаций Service Mesh ограничена или вообще не предусмотрена проверка сертификатов на отзыв, особенно для сертификатов, используемых в mTLS при аутентификации микросервисов. Это важный момент, и к нему мы ещё вернёмся.

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

Что обеспечивают TLS и MTLS

Три базовые вещи:

Конфиденциальность — никто по дороге не подсмотрит содержимое.

Целостность — никто не сможет подменить данные по пути.

Аутентификация — мы знаем, кто на том конце соединения.

Конфиденциальность и целостность обеспечиваются шифрованием. Аутентификация — за счёт имени, записанного в сертификате.

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

В классической аутентификации через Active Directory, например, используется Kerberos — там в тикете сразу указаны группы пользователя. А вот в сертификате есть только имя. Все остальные права и доступы должен хранить и проверять внешний сервис, потому что сам по себе сертификат их не содержит. Поэтому очень важно, включив mTLS, обеспечить внешними средствами реализацию какой-либо модели доступа и контроль доступа.

С фильтрацией трафика и разделением ролей — аналогично. Можем обеспечить внешними средствами, например в связке с Istio, который все эти задачи берёт на себя.

Zero Trust. Магическое словосочетание Zero Trust должно обеспечить нам полную безопасность, нулевое доверие и так далее.

Идея в чём? Раньше всё было просто: защищённый офис, внутренний ЦОД, все пользователи сидят внутри периметра — можно строить безопасность по границе. Сегодня всё иначе: сотрудники работают откуда угодно, сервисы разбросаны по облакам, и никакого «периметра» больше нет. В таких условиях подход Zero Trust (нулевое доверие) становится основой: любому запросу нельзя доверять по умолчанию, его нужно аутентифицировать и авторизовать, независимо от того, откуда он пришёл — извне или изнутри.

Разумеется, это отчасти маркетинговое упрощение. Абсолютного нуля доверия в природе не бывает. Мы всё равно доверяем вендору, который предоставил нам Zero Trust-решение. Доверяем удостоверяющему центру (CA), который подписывает сертификаты. И это критически важно — мы должны быть уверены, что CA подпишет только то, что действительно можно. 

А ещё есть генерация ключей. История знает случаи, когда закрытые ключи генерировались так плохо, что по одной подписи можно было восстановить весь ключ. Это недопустимо. Поэтому, когда мы используем криптографические библиотеки, мы должны быть уверены в их качестве. В противном случае любой сертификат может обернуться бомбой замедленного действия, и злоумышленник получит доступ ко всем переданным данным.

В целом, Zero Trust — это огромная тема. Есть две основные архитектуры от Open Group и от NIST

По ссылкам подробно описано, как технически на практике это реализовать:

https://csrc.nist.gov/pubs/sp/800/207/final
https://pubs.opengroup.org/security/zero-trust-principles/ 

Использование сертификатов

Перейдем на уровень ниже и посмотрим на Service Mesh на примере Istio.

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

Шифрование и аутентификация происходит абсолютно на всех путях коммуникации, но сертификаты — разные, получаемые от разных удостоверяющих центров. Есть входящий и исходящий трафик (ingress и egress), где обычно используются сертификаты публичных удостоверяющих центров (прозрачные замочки). Они нужны, чтобы внешние сервисы и пользователи могли взаимодействовать с нашими системами. Управление этими сертификатами за рамками данной статьи. 

В рамках межсервисного взаимодействия и реализации Zero Trust нас интересует чёрный замочек посередине, который отвечает за трафик между внутренними сервисами.

Важный момент, про который надо помнить — шифрование и защита включаются и отключаются одним параметром конфигурации. Можно раздать сертификаты, настроить политики безопасности, но если на уровне управляющего сервера Control Plane эту конфигурацию отключить, то никакого смысла в танцах с раздачей сертификатов не будет. Так что не забывайте про защищённые коммуникации между управляющим сервером и трафиком внутри соответствующей сети (рыжий замочек).

В обеспечении защищённого соединения есть два ключевых момента:

  1. Где, как и кто может получить сертификат? 

Если у сервиса уже есть сертификат, он может его использовать для аутентификации. Но до этого момента возникает важный вопрос: как сервис получает этот сертификат, если у него ещё нет никакого сертификата? Как происходит его первоначальная аутентификация?

Обычно в Kubernetes и Istio для этого используют JWT-токены. Но здесь возникают несколько зон риска: насколько безопасно передаются эти токены при первоначальной настройке (bootstrapping)? Кто и как следит за их безопасностью? Можно ли такой токен перехватить и использовать повторно? Можно ли подделать такой токен и получить сертификат на неавторизованный сервис?

2.

Сертификат — публичен и не является секретом, в отличии от закрытого ключа

Сертификаты — это публичная информация. Их можно свободно увидеть, например, на любом HTTPS-сайте. Поэтому защищать сам сертификат после получения необходимости нет — он не является секретом.

Но есть гораздо более важная часть — закрытый ключ, связанный с этим сертификатом. Именно он используется для аутентификации и установки защищённого соединения. Сертификат содержит имя и подтверждение его подлинности, но предъявить сертификат может кто угодно. Главное — у кого есть соответствующий закрытый ключ. Только он даёт возможность использовать сертификат по назначению.

В контейнерах и в Service Mesh сертификаты и ключи могут храниться двумя способами:

В виде файлов на диске — например, в подключаемом томе. В этом случае нужно отдельно заботиться о безопасности: шифровать диск и резервные копии, чтобы ключ не утёк.

В памяти — это более безопасный подход, часто используется для ключей, используемых во внутреннем трафике. Такие ключи не сохраняются на диск и исчезают при перезапуске пода. Однако это создаёт дополнительную нагрузку: ключи приходится генерировать заново при каждом запуске пода, что может повлиять на производительность.

Важно понимать, где именно и как хранятся закрытые ключи в конкретной системе — от этого зависят меры безопасности, которые необходимо принять.

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

Как это происходит в Istio? При старте пода Istio-агент генерируется открытый и закрытый ключи. Дальше на базе сгенерированного ключа формируется запрос на сертификат CSR (Certificate Signing Request). Этот запрос аутентифицируется с помощью JWT токена и отправляется на CA, откуда возвращается подписанный сертификат. Закрытый ключ при этом не покидает систему, где будет использоваться, и не передаётся на CA.

Отдельно стоит подчеркнуть, где и как генерируется закрытый ключ, а также какие алгоритмы используются. Важный нюанс: в России под криптографией официально понимаются только алгоритмы, определённые в ГОСТ. Однако контейнеры и Service Mesh пока не поддерживают ГОСТ как следует, несмотря на отдельные попытки интеграции. Поэтому на практике всё строится на алгоритмах RSA или ECDSA.

С точки зрения реальной безопасности — это нормально, если всё правильно настроено. Но с точки зрения формальных требований, например, при защите КИИ или персональных данных, такие сертификаты не подходят, потому что не соответствуют отечественным стандартам.

Угрозы и атаки

Разберёмся, от каких угроз и атак нас всё это защищает.

Нам всегда нужно чётко понимать, зачем мы внедряем ту или иную меру безопасности. Если это делается без ясной цели, то мы просто расходуем ресурсы — процессорное время, память — и не получаем реальной пользы. Поэтому сначала стоит задуматься о модели угроз: от кого и от чего мы хотим защититься. И только после этого — выбирать и внедрять конкретные меры.

Я очень люблю простую модель STRIDE, которую более 25 лет назад предложили в Microsoft (https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats).  Суть подхода в том, что в любой точке, где данные пересекают границу доверия, мы анализируем возможные риски. С одной стороны, стремимся обеспечить аутентификацию, целостность, недоказуемость, конфиденциальность, доступность и авторизацию. С другой — оцениваем, как эти свойства могут быть нарушены: через подмену (Spoofing), незаконное изменение данных (Tampering), отказ от действий (Repudiation), раскрытие информации (Information Disclosure), отказ в обслуживании (Denial of Service) и несанкционированное получение привилегий (Elevation of Privilege).

Возьмём простой и известный пример — стандартную демонстрационную микросервисную архитектуру от Google. Это онлайн-магазин, в котором пользователи добавляют товары в корзину и оформляют покупки. Этот пример отлично подходит для обсуждения типовых угроз и способов их устранения.

Важно понимать: при взаимодействии разных сервисов — особенно если они разнесены по инфраструктуре или принадлежат разным организациям — потенциальные векторы атак могут существенно различаться. Каждое соединение, каждый запрос — это потенциальная точка атаки, и набор угроз зависит от контекста: кто управляет сервисом, где он размещён, какие каналы связи используются. Поэтому типы атак, риски и контрмеры нужно рассматривать для каждого канала взаимодействия отдельно.

Например, если речь идет о платежах и доставке — это как раз тот случай, где критически важно всё сразу:

  • Конфиденциальность, потому что передаются чувствительные данные, например, номер кредитной карты.

  • Целостность, чтобы запрос на списание $10 не превратился в списание $1000 — важно, чтобы данные не были изменены в пути.

  • Устойчивость к повторной атаке (replay attack) — чтобы один и тот же запрос нельзя было отправить повторно сотню раз и продолжать списывать деньги с клиента.

С точки зрения шифрования трафика есть важный нюанс, о котором часто забывают. Когда мы что-то шифруем, нам кажется, что мы защищены: злоумышленник не может расшифровать трафик прямо сейчас — и это уже хорошо. Но если он сможет записать этот зашифрованный трафик и сохранить его, он получит возможность расшифровать его позже.

Особенно критично это для данных, сохраняющих свою ценность во времени. Например, номера банковских карт. Раньше карты выпускали со сроком действия до пяти лет, теперь срок может быть бессрочным или долгосрочным. Если кто-то перехватил трафик с данными карт сегодня, а через несколько лет появилась возможность его расшифровать — данные всё ещё актуальны.

Отсюда вывод: алгоритм шифрования должен быть устойчив в течение того срока, пока важны защищаемые данные. И это особенно важно с учётом будущих угроз — например, появления квантовых компьютеров и посткватновой криптографии. Даже если сейчас всё зашифровано «надёжно», это не значит, что останется таким через пять лет.

Следующий этап в примере с магазином — доставка. Допустим, пользователь оплатил заказ, а злоумышленник каким-то образом подменил адрес. Это уже не просто неприятность, а реальный инцидент безопасности. Здесь критично обеспечить целостность данных — чтобы информация, которую передал один сервис другому, не была изменена в процессе.

В то же время есть и другие категории сервисов, например, каталоги товаров или рекомендательные системы. В этих случаях требования к безопасности иные: конфиденциальность и целостность информации могут быть менее критичными. Потеря или искажение данных здесь вряд ли приведёт к катастрофе, хотя тоже нежелательно.

Разумеется, найдутся те, кто возмутится, если публично станет известно, какие товары или контент ему рекомендовали сервисы. Это может затрагивать приватность и вызывать неприятные вопросы. Но если смотреть глубже, то в таких сценариях куда важнее защищать сам алгоритм рекомендаций, чем данные трафика. Это интеллектуальная собственность, от которой напрямую зависит бизнес.

Тем не менее, в эпоху гиперперсонализации и digital-профилирования, есть множество тонких моментов, связанных с рекламой и утечкой персональных данных. Даже банальный лог запроса может содержать чувствительную информацию, которую легко агрегировать и использовать против пользователя. Поэтому, несмотря на кажущуюся безобидность, вопросы безопасности в рекомендательных системах и рекламе становятся всё более актуальными, особенно на фоне растущего внимания к защите персональных данных и нормативным требованиям.

В случае с email-рассылками, нежелательной рекламой и вообще любыми коммуникациями, затрагивающими персональные данные, ситуация становится все более чувствительной — и с точки зрения законодательства, и с точки зрения репутации бизнеса.

Сегодня действуют оборотные штрафы за утечки и нелегальное использование персональных данных. Это значит, что компания рискует потерять процент от оборота, если допустит утечку или нарушение, связанное с данными пользователей. В частности, рассылки — это зона повышенного риска. Если злоумышленник перехватит доступ к email-инфраструктуре, подменит содержимое письма, добавит туда вредоносные ссылки или просто запустит массовую рассылку без согласия пользователей, ответственность понесёт компания, чьё имя стоит в поле «отправитель» — даже если она к атаке отношения не имеет.

Более того, даже до появления оборотных штрафов были реальные прецеденты, когда пользователи доказывали в суде, что они не давали согласия на рассылку. При этом никто не разбирался, как и почему произошла ошибка — штраф получала компания, просто потому что письма были разосланы от её имени.

Защита от атак

Есть понятные варианты защиты от атак, например:

  • Неавторизованный доступ между сервисами. Наша задача — гарантировать, что каждый сервис в системе может предъявить своё имя и валидный сертификат, и что доступ строго ограничен только авторизованным сервисам. 

А теперь к важному: аутентификация должна быть обязательной на каждом участке взаимодействия. Без исключений. Если где-то в системе допускается обход аутентификации — будь то экспериментальный сервис, забытый endpoint или зона «внутреннего доверия» — именно туда и пойдёт злоумышленник.

  • Impersonation (подделка сервисов). Когда проектируете защиту, важно чётко понимать, от какого типа атакующего вы хотите защититься. Например, если атакующий находится снаружи — в интернете, нужно оценить, к каким ресурсам внутри вашего кластера или ЦОДа он может получить доступ и какие действия выполнить.

Istio подробно описывает возможные модели угроз и уровни доступа злоумышленника (https://istio.io/latest/docs/ops/deployment/security-model/) — на уровне workload, отдельного пода, самого Service Mesh или Kubernetes API. У каждого — свои возможности и риски.

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

Ситуация меняется, если скомпрометированы сам Service Mesh или API Kubernetes. В этом случае атакующий получает полный доступ к конфигурации кластера, может имитировать любые сервисы и обходить существующие механизмы защиты.

Важно: с точки зрения последствий, компрометация Service Mesh и API Kubernetes — это одно и то же. В обоих случаях успешная атака даёт полный контроль над системой, полный доступ на кластере, возможность менять конфигурации и обходить защиту.

  • Перехват трафика (MitM). mTLS защищает от пассивного перехвата и активных атак MitM, но неэффективен, если злоумышленник скомпрометировал инфраструктуру или получил закрытые ключи.

Важно, что Istio — это не просто одна коробочка, которую ставишь и она работает. Это целый набор компонентов, каждый со своей конфигурацией, зависимостями и потенциальными уязвимостями. Когда мы добавляем такой инструмент ради безопасности, то должны быть уверены, что он сам безопасен. Иначе вместо защиты получаем новую точку для атак.

На конференции Black Hat был замечательный доклад о том, как из-за ошибок конфигурации в облаке SAP исслежователи, которые просто купили доступ к облачным сервисам, как простые клиенты, смогли получить практически неограниченный доступ. Они просматривали и меняли Docker-образы, получали админские права в Kubernetes-кластере, а так как это всё в облаке — ещё и доступ к данным других пользователей и их API-ключам для доступа ко внешним сервисам.

Что важно — с точки зрения безопасности всё было настроено достаточно аккуратно. Не было избыточных прав или root доступов. Но в контейнерах, где запускались задачи с AI-моделями, был настроен Istio Service Mesh, и файрвол блокировал весь трафик, кроме трафика от UID, под которым работал Service Mesh.

Повысить привилегии до root не получалось, но присвоить нужный UID исследователи смогли. Это позволило обойти фильтрацию трафика, и дальше — за счёт других ошибок в конфигурации — получить достаточно широкий доступ к системе.

Подходы к обеспечению ИБ

Недостаточно нарисовать на бумажке модель угроз. Весёлые картинки, которые я показываю, хороши для презентации, длиной в 40 минут, когда нет возможности глубоко погрузиться в детали. 

Модель угроз хороша, когда мы что-то планируем и проектируем. На этапе проектирования все любят рисовать квадратики. Это удобно: переместить компонент на диаграмме — дело трёх минут, и почти ничего не стоит. Но если с архитектурой ошиблись на этом этапе, а потом всё реализовали и выкатили в прод — менять уже больно и дорого.

Но после развёртывания решения, одних квадратиков для оценки безопасности недостаточно. Мы должны реально проверять, как система работает вживую, как всё настроено, где могут быть дыры. Архитектурная схема — это только начало. Настоящие проблемы начинаются, когда всё уже запущено на проде.

Всё больше компаний переходят к модели безопасности «предполагаем взлом» (assume breach). То есть мы не надеемся, что всё защищено, а сразу исходим из предположения, что любой узел в системе может быть скомпрометирован. Важно не просто так думать, а регулярно это проверять на практике — через боевые учения.

Есть два основных подхода:

  1. Пентесты — внутренние или внешние Red Team-команды пытаются взломать вашу систему, как реальные атакующие. Вы смотрите, где слабые места и как реагирует команда защитников.

  2. Баг-баунти — вы платите внешним «белым» хакерам за найденные уязвимости. Они ломают вашу систему и сообщают о проблемах, а вы их закрываете до того, как их проэксплуатирует кто-то другой.

В упомянутом докладе с Black Hat — много примеров некорректных конфигураций, где наглядно показано, как не надо делать. И эти конфигурации делали крупные компании, которые предоставляют облачные услуги и хотят делать это безопасно. Но, увы, не всегда получается.

Проблемы и ошибки конфигурации

Как только мы включаем шифрование, начинаем выдавать сертификаты, производительность неминуемо падает.

Важно, что производительность надо измерять на реальной нагрузке.

Если посмотреть на измерения производительности на официальных сайтах Istio и его конкурентов, то увидите у всех разные данные — в зависимости от того, кто тестирует и для кого. Все сходятся на том, что шифрование ухудшает производительность, вопрос только в том, насколько.

https://istio.io/latest/blog/2020/large-scale-security-policy-performance-tests/
https://isovalent.com/blog/post/2022-05-03-servicemesh-security/

Понятно, что шифрование — штука тяжёлая с точки зрения ресурсов. Это математика, и она требует вычислений. Но кроме mTLS на уровне Service Mesh, можно шифровать трафик и на сетевом уровне. Есть проверенные варианты: IPsec, WireGuard — их можно поднять на сетевом оборудовании или на уровне ядра.

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

Но если требований больше — например, нужна аутентификация, контроль доступа, управление политиками и так далее — тогда мы начинаем смотреть в сторону mTLS, Service Mesh и прочего.

При этом не стоит забывать, что шифрование — это не только нагрузка на CPU. Отдельная боль — сами сертификаты. Когда вы начинаете массово выпускать и обновлять сертификаты, это становится отдельной задачей. И если этим не управлять — будут проблемы.

В чем суть проблемы? Пока мы разворачиваем систему постепенно, всё выглядит нормально. Поды запускаются, сертификаты запрашиваются в обычном режиме, удостоверяющий центр (CA) справляется. Сертификаты обновляются, всё работает.

Но всё меняется, когда происходит сбой. Допустим, весь кластер вырубился — и потом мы его запускаем заново. Все поды одновременно начинают обращаться за новыми сертификатами. Если у вас большая инфраструктура, это может быть десятки тысяч запросов за считанные секунды. Удостоверяющий центр с этим не справляется, ложится. А следом ложится и вся инфраструктура, потому что без сертификатов в режиме strict TLS соединения не устанавливаются. И всё, кластер не поднимается.

Получается, с точки зрения безопасности — всё отлично: у нас конфиденциальность и целостность соблюдены. Вот только доступность — не завезли. Инфраструктура лежит, и сделать с этим ничего нельзя, только разгребать вручную.

Есть ещё нюанс, о котором часто забывают. Все эти sidecar proxy — Envoy и прочее — пусть и занимают немного ресурсов, но они не бесплатны. Память, диск, CPU. Если это десятки мегабайт на каждый под — на масштабе это уже заметная нагрузка. А если у вас юнит-экономика и так не очень сходится, эти лишние мегабайты на каждый микросервис могут стать той самой песчинкой, которая перевесит чашу весов.

Официальные рекомендации по использованию mTLS

  • По умолчанию permissive mode.

  • Рекомендуется переводить на strict mode.

Ключевой момент в том, что все вендоры, будь то Istio, OpenShift и другие, рекомендуют перевести mTLS в strict mode. Это значит, что при установке любого соединения обе стороны требуют предоставления сертификата и установки защищённого соединения. Если какая-то сторона не справляется с предоставлением сертификата, соединение не устанавливается. Но, несмотря на все рекомендации, везде по умолчанию режим strict не включен. Вместо него по умолчанию режим permissive — если кто-то показал сертификат, мы его посмотрели. Если кто-то не показал сертификат, то мы сделаем небезопасное соединение. Эта конфигурация намекает на то, что при включении strict mode что-то может пойти не так.

Поэтому переключение с одного режима на другой нужно запланировать. В идеале strict mode должен быть включен и в тестовой, и в продакшен среде, потому что все вопросы, связанные с перезагрузками, перезапусками, аварийными ситуациями, обновлениями, с большой долей вероятности приведут к проблемам сертификатов. Желательно это отловить на тестовой среде, а не на продакшене, чтобы понять, где может быть проблема.

Криптография

Я уже упоминала в разных местах про важность криптографии. Подведу итог. 

  • Генерация ключей. Обратите внимание, где именно генерируется ключ. В последних версиях Service Mesh все нормально, он генерируется там же, где используется.

Если вы используете сертификаты и для клиентских подключений на ingress, egress, для управления и Control Plane, важно, чтобы ключи не летали по сети до тех пор, пока защищённое соединение не установлено. К сожалению, бывают печальные ситуации, когда ключ генерируется на удостоверяющем центре, а дальше передается конечному сервису в открытом виде по сети. Так делать не надо.

  • Криптографические алгоритмы. Подумайте о том, какие криптографические алгоритмы используете, насколько они надёжны, и как долго будут оставаться стойкими.

  • Хранение ключей. Знайте, где хранятся ваши ключи (в памяти, либо на диске), и ограничивайте к ним права доступа.

  • Наиболее безопасный и дорогой вариант — хранить ключи с использованием аппаратного модуля безопасности (HSM). Это предотвращает утечку ключей из оперативной памяти или файловой системы.

  • Права доступа должны ограничивать доступ к закрытым ключам, хранящимся на диске. 

  • Резервные копии. Важный момент, про который часто забывают: мы классно всё защищаем во время работы, но забываем о резервных копиях. Я неоднократно видела резервные копии, которые не зашифрованы и хранятся в совершенно неподобающих местах. Это отличный источник закрытых ключей для взломщиков.

  • Физический доступ. Никто не отменял возможность дампа памяти, откуда можно получить ключи.

Проверка отзыва сертификата

Ещё один важный момент — это проверка отзыва сертификатов. У сертификата есть срок действия. Традиционно это примерно год. Для публичных TLS-сертификатов срок жизни, который постоянно сокращается, раньше был несколько лет, сейчас не более 398 дней, с марта 2029 не более 47 дней.

У пользователя или веб-сервиса могут украсть закрытый ключ, пользователь может потерять свой токен или смарт-карту. В этом случае сертификат можно и нужно отозвать. В Istio проверка отзыва сертификатов появилась далеко не с первых версий и не подключена по умолчанию. И до последних версий не поддерживается проверка отзыва mTLS-сертификата при установке защищённых соединений между Sidecard Proxy. Понятно, что это сделано по причинам производительности, потому что проверка каждого сертификата может привести к задержкам в десятки миллисекунд, и всё будет работать очень медленно.

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

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

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

Из-за того, что мы не проверяем отзыв сертификатов, используемых в рамках Service Mesh, то используется коротки срок действия таких сертификатов — от несколько часов до пары дней, после чего сертификаты обновляются. Поэтому, если мы расследуем инцидент, произошедший неделю назад, то не увидим старые сертификаты. А значит нам необходимо понять по логам, кто и когда подключался, как их запрашивал, была ли это нормальная активность или аномалия.

Подводим итоги

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

Принципы построения полезной и эффективной безопасности:

  • Добавление конкретной настройки (решения) снижает как минимум один из рисков. Если мы добавляем новое решение либо настройку, оно должно реально снижать какой-то существующий риск и при этом не создавать новых. 

  • Использовать безопасную конфигурацию должно быть удобнее, чем небезопасную. Без Istio Service Mesh управление сертификатами было сложной и неудобной задачей, а сейчас всё автоматизировано. Но у автоматизации есть обратная сторона медали: многое спрятано под капотом, и мы не всегда понимаем, что на самом деле там происходит.

  • Вместо проверки конкретной настройки, контроль процесса изменения настроек. Например, если включен режим strict mTLS, то нужно контролировать процесс изменения этой настройки. Если сегодня мы посмотрели настройки в 15:15, и убедились, что они правильные и прошли все аудиты, то это ничего не говорит о том, что с ними было час назад и что будет через день. Нам важно не только проверять конкретные настройки безопасности, которые действуют сейчас, но и понимать процесс, как эти настройки могут изменить. Это как раз про контроль взаимодействия между Data Plane и Control Plane и наличия защищённых соединений между ними. 

Чек-лист: что надо проверять

  • Включен ли режим mTLS mode: STRICT.

  • Есть ли разграничение прав доступа (RBAC), что ключи могут генерировать только соответствующие сервисы и запрашивать для них сертификаты.

  • Контроль конфигураций, чтобы, например, нельзя было просто отключить требования установки защищённых соединений.

  • Сетевая сегментация, чтобы компрометация одного пода не приводила к возможности  компрометации всех остальных узлов (lateral movement), которые находятся в сети.

  • Логирование и активный мониторинг, чтобы мы могли выявлять аномалии.

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

  • Стойкая криптография, которая позволяет обеспечить конфиденциальность данных в течение срока актуальности этих данных.

  • Безопасное хранение секретов (HSM или шифрование) и резервных копий.

  • Тестировать производительность под имеющийся трафик, потому что профили трафика и ситуации могут сильно отличаться.

Послушать новые доклады по теме можно будет на DevOps Conf в апреле 2026 года — следите за новостями, и до встречи на новых конференциях!

Комментарии (0)