Как построить бастион-хост и превратить его в неприступную крепость
Привет, меня зовут Сергей Истомин, я DevOps-инженер в KTS.
Осталось ли бастион-хостам место в мире, в котором инфраструктуру можно защитить оверлейными сетями, нативными прокси и VPN? Задавшись этим вопросом, мы провели анализ материалов некоторых авторов (ссылки на материалы в конце статьи), перевели, порассуждали и обобщили полученные выводы.
В статье рассказываю, зачем нужен бастион-хост, какие есть ему альтернативы, а также как его возвести и укрепить.
Оглавление
Бастион: зачем и почему
Итак, давайте разбираться. Стоит ли настраивать бастион, когда рынок пестрит всевозможными решениями «под ключ» для организации доступа к целевым хостам?
Для ответа на этот вопрос вернемся к истокам и вспомним, что выбор решения — это всегда вопрос баланса. Баланса между удобством, управляемостью, вероятностью той или иной атаки, величиной потенциального ущерба, а главное — стоимостью. Как стоимостью лицензий, так и стоимостью времени инженеров.
И в поисках баланса вы можете прийти к выводу, что до определенного размера вашей инфраструктуры и количества источников контролируемого трафика вам действительно будет целесообразнее закрыться простым бастионом, VPN или их комбинацией. Но с ростом инфраструктуры вы, возможно, захотите довериться какой-то более привлекательной технологии, обещающей повышение и удобства, и безопасности. Попробуем разобраться в выборе.
Бастион vs. «zero-trust»
Вспомним о концепции нулевого доверия. Она предполагает, что каждый узел вашей сети рассматривает любое обращение как потенциально опасное. С этим трудно не согласиться. В решениях «zero-trust» появляется возможность направлять трафик между точками, минуя хост управления, и более удобный менеджмент правил.
Однако чего-то принципиально нового в «zero-trust» нет. По факту это тот же бастион на максималках — с двухфакторкой, ограниченными по времени сертификатами, логированием и т.п. Все это — давно проверенные технологии, пересобранные в новой обертке. Маркетологи Google придумали разделять «zero-trust» и бастионы, хотя суть их одинакова: централизованно пройти идентификацию и безопасно установить соединение до целевой машины. Из минусов бастиона как такового маркетологи отметили, что бастионом нужно управлять и что (о ужас!) там есть SSH и им можно воспользоваться (речь про SSH multiplexing). Не самые сильные аргументы.
Тем не менее, в ИТ-сообществе все же появилось деление на zero-trust и условно «классические» решения — VPN и бастион. И да, чаще всего бастионом называют любой хост, где стоит SSH-сервер, позволяющий через него попасть на целевой хост. Но ведь можно организовать бастион и посложнее. Нулевое доверие можно устроить и без оверлейных сетей, разрешая общение между серверами только через бастион. Киллер-фича бастиона — возможность постепенного наращивания сложности, регулируя баланс затрат и получаемого решения.
Бастион for everyone
Бастионы актуальны. Выбор в пользу бастионов делают стартапы на ранних стадиях — бастион пользуется популярностью как хороший проверенный способ решения задачи безопасного доступа к инфраструктуре при ее малых размерах и концентрации усилий на становлении бизнеса.
Бастион может быть и частью решения в вашей системе обеспечения доступа. Он отлично смотрится как «гейт» перед какой-либо выделенной частью инфраструктуры, кластером, подсетью или группой хостов. И перед условной «стройплощадкой», где вы проводите исследования и экспериментируете.
Ну, а когда у вас есть опенсорсные компоненты и тонны мануалов на каждый отдельный шаг, то руки так и тянутся построить бастион и отказаться от сторонних SaaS-решений, подписок и прочих радостей зависимости от отделов продаж третьих лиц. Начнем?
Закладываем фундамент
Поговорим о том, что взяли бы мы для первых шагов в организации бастиона.
Выбираем операционную систему
Здесь очень простая логика: чем меньше установлено пакетов, чем меньше запущено служб и чем новее запускаемые ядро и компоненты, тем меньше у вас вероятность подвергнуться результативной атаке. Поэтому исходной точкой бастиона предпочтительно делать какой-либо минимальный образ операционной системы. Но при этом учитывайте свои навыки и знание дистрибутива — используйте то, чем умеете управлять.
Определяемся с перечнем пользователей и создаем им ключи
В идеале на бастионе нужно 1 в 1 создать всех пользователей, под которыми будут производиться подключения к целевым хостам. Конечно, вам ничего не мешает добавить все ключи одному пользователю, однако это лишит вас читаемости журнала подключений.
Если ваши пользователи будут подключаться к бастиону только для проксирования до целевого хоста, то им должен быть закрыт интерактивный вход в оболочку на самом бастионе:
useradd -s /sbin/nologin ivanov.
Ходить будем по ключам. Вот хороший мануал как ими пользоваться (оставим тут для полноты картины). Каждый пользователь, разумеется, ключи создает себе сам и бережно хранит свой приватный ключ.
Используем OpenSSH
Это опенсорс и он входит по умолчанию в большинство дистрибутивов линукс. В этом его преимущество.
Базовые настройки в '/etc/ssh/sshd_config':
PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
ClientAliveInterval 600
MaxAuthTries 3
Закрываемся фаерволом
Вот пара инструкций, как можно сделать это различными способами:
UFW для Ubuntu — для простого закрытия портов.
iptables — универсальное решение для тех, кому важны детали реализации.
Настраиваем автобан брутфорсеров
Усилим установленный параметр MaxAuthTries 3 любым решением на выбор: Fail2Ban, SSHGuard, CrowdSec. Это шаг в сторону эшелонированной защиты, который убережет ваш SSH-демон от назойливых ботов, перебирающих варианты для входа — атакующий просто получит бан.
Возводим стены
Когда ваш базовый бастион готов, вы можете сделать его безопаснее. В этом разделе мы перечислим несколько способов укрепления бастиона, которые помогут вам избежать неприятностей.
Проводим тюнинг SSH и сетевых правил
Избавляемся от уязвимости Diffie-Hellman. Обмен ключами Диффи-Хеллмана — это популярный криптографический алгоритм, который позволяет интернет-протоколам согласовывать общий ключ и безопасное соединение, однако при его использовании важно учитывать, что короткие модули уязвимы для атаки Logjam. Деактивируем короткие модули:
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv
/etc/ssh/moduli.tmp /etc/ssh/moduli
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms
curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers
chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs
hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
На случай, если у пользователя все же будет назначена оболочка, вносим в конфиг SSH-сервера запреты и принудительный перехват команд (для User, Group, Host или Address):
Match User ivanov,petrov,sidorov
PermitTTY no
ForceCommand /bin/echo 'Interactive sessions disabled.'
AllowUsers ivanov petrov sidorov
Также можно конкретизировать список до комбинации
AllowUsers ivanov@1.2.3.4 petrov sidorov@5.6.7.8.
Ограничиваем источники подключений по IP-адресам. Способов несколько.
А если вы о-о-о-чень хотите, то можно сменить порт с 22 на что-то затейливое. Можно пойти дальше в этот лес и внедрить PortKnocking.
Разбираемся с пересылкой агента. Суть проблемы и варианты решения описаны в гайде OpenSSH в разделе SSH agent forwarding.
А можно вообще запретить использование пересылки, чтобы клиенты использовали ключ ssh -J, , но для этого нужен OpenSSH 7.3 и старше.
Запрещаем вообще весь форвардинг конфиге SSH-сервера, кроме tcp:
AllowAgentForwarding no
AllowStreamLocalForwarding no
X11Forwarding no
LogLevel VERBOSE
Выключаем все лишнее, оставляем все нужное
Выполняем следующую команду и оцениваем, какие сервисы точно не пригодятся.
systemctl list-units --type=service --state=running
На эту тему есть старинная, но все еще актуальная по смыслу статья. И поверьте, вам точно не нужен portmapper на бастионе.
Итоговый набор слушателей смотрим через:
lsof -i -P -n | grep LISTEN
Собираем логи на внешний ресурс
Локально что-то хранить для истории на бастионе не нужно. Для простого сетапа можно ограничиться удаленным syslog-сервером, но если в вашей инфраструктуре уже есть какой-то процесс сбора логов, настроенный, например, через Loki или Elasticsearch, то не забудьте собирать логи и с бастиона.
Актуализируем ключи при разворачивании из образов
Необходимо удалить с помощью следующей команды:
rm /etc/ssh/ssh_host_*
Затем заново сгенерировать ключи хоста, когда сервер разворачивается из образа или клонируется, ведь они должны быть уникальными:
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
Настраиваем целевые хосты
Переходим к тому самому неотъемлемому элементу концепции нулевого доверия. Принимаем подключения только через брокера: SSH и прикладные службы целевых хостов должны быть настроены на прием подключений только от бастиона. Не до фанатизма, конечно. Например, доступ к портам, используемым для репликации между членами кластера стоит настроить только с хостов такого кластера.
Где-то тут начинают отчетливо проявляться преимущества решений «zero-trust» в части упрощения администрирования, однако спроектировать за вас, кого и куда пускать, они в любом случае не смогут. И если вы используете IaC, то по большому счету все равно, где именно будут задаваться правила доступа. Главное — создать их.
Настраиваем клиентов
Пользователям стоит иметь настройку SSH-клиента:
UpdateHostKeys yes
Это позволит без вопросов принимать новые ключи, предлагаемые известным хостом. В современных версиях эта опция уже включена.
Для постоянного использования подключений удобно вынести указание на бастион в конфигурационный файл ~/.ssh/config:
Host *.cluster.local
ProxyJump bastion.mydomain.ru
Тогда достаточно будет использовать ssh node-x.cluster.local, и клиент даже не будет разрешать это имя целевого хоста в ip — такая задача будет у бастиона.
Укрепляем по полной
Нет предела совершенству. Тем, кто хочет укрепить свой бастион еще основательнее, мы предлагаем еще несколько опций на рассмотрение. Имейте в виду, они достаточно объемные, но мы пробежимся по ним очень кратко и дадим ссылки на нужные материалы.
Переводим SSH на OIDC и сертификаты. На эту тему есть хорошая статья от Smallstep.
Ставим второй фактор. Подробности реализации от Mozilla все в том же гайде.
Обнаруживаем вторжения. Здесь на Хабре есть статьи по Wazuh и OSSEC — они погрузят вас в эту тему.
Повышаем отказоустойчивость. Можно подумать над балансировщиком и несколькими бастионами, но не забудьте разработать план восстановления. Также у вас должен оставаться доступ к консоли сервера через провайдера или ваш гипервизор.
Закрываем бастион VPN-ом. OpenVPN все еще актуален — в облаке и у себя. WireGuard тоже прекрасен — и тоже в облаке и у себя.
Противодействуем DDOS. У облачных провайдеров всегда есть предложение по защите от DDOS.
Итоги
Вполне вероятно, что мы перечислили не все возможные варианты укрепления бастиона. В этой статье мы постарались сосредоточиться на проверенных опциях, которые доказали свою эффективность.
Какой компот сварить из всего этого, конечно, решать каждому самостоятельно. А возможно, вы захотите сразу купить готовый нектар «zero-trust» в коробке. Главное — не переусложняйте. В конечном итоге все стоит усилий и денег, и только вам решать каким инструментарием защищать вашу инфраструктуру.
И не забывайте обновлять ПО, вести документацию и регулярно делать бекапы.
Материалы, использованные при написании этой статьи
Другие статьи про DevOps для начинающих:
Другие статьи про DevOps для продолжающих: