Привет, меня зовут Сергей Истомин, я 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':

  • Отключаем вход для root

PermitRootLogin no
  • Отключаем вход по паролю

PasswordAuthentication no
  • Указываем допустимый метод входа

AuthenticationMethods publickey
  • Устанавливаем таймаут бездействия в секундах (например, 600)

ClientAliveInterval 600
  • Устанавливаем число попыток авторизации (например, 3)

MaxAuthTries 3

Закрываемся фаерволом

  • Запрещаем все.

  • Разрешаем 22 порт.

Вот пара инструкций, как можно сделать это различными способами:

  • 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
  • Устанавливаем в конфиге SSH-сервера следующий порядок поддерживаемых алгоритмов ключей хоста (от более предпочтительных к менее предпочтительным):

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.'
  • Дополняем конфиг SSH-сервера белым списком пользователей, от имени которых следует принять подключения.

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
  • Наконец, предусматриваем в конфиге SSH-сервера нужную детализацию логирования:

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 для продолжающих:

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


  1. David_Osipov
    14.05.2024 08:51
    +4

    1. Лучше поиграться с sysctl.conf. Начните с моего и сконфигурируйте под себя.

    2. Берите Lynis тулзу и тоже укрепите свой сервер.

    3. Вместо Fail2Ban я использую Crowdsec.

    4. Самое малоизученное, но сильное решение - systemd sandboxing. Начните с просмотра этой репы, и моей репы. Но будьте аккуратными.

    5. Вместо стандартного NTP протокола я использую NTS, чтобы просто снизить поверхность атаки, да и настраивается очень быстро. Софт можно использовать либо chrony либо ntpsec, а серверы брать отсюда.


  1. Angel_of_Sorrow
    14.05.2024 08:51
    +1

    • Включаем вход для root 

    PermitRootLogin no

    Ошибочка закралась - или выключаем, или yes. Спасибо !


    1. Jaffarr
      14.05.2024 08:51

      Скорее всего выключаем


    1. sergey_ist Автор
      14.05.2024 08:51

      Спасибо, что заметили опечатку! Поправил


  1. redfox0
    14.05.2024 08:51

    Чтобы не копировать бездумно наборы шифров из статьи, советую питоновскую утилиту https://github.com/jtesta/ssh-audit Есть в репозитории pip'a.


  1. YasonD
    14.05.2024 08:51

    Как можно запретить ssh tunnel?


  1. paparazzo
    14.05.2024 08:51

    Я еще для интерактивного входа дополнял сессию через rbash в cgroups с ограничением переопределения переменных окружения и пересоздание домашних директорий при выходе и авторизацией через домен FreeIPA, ограничивал возможность построения туннелей для передачи данных, логировал все действия в консоли. Но умные люди просто запрещают все кроме туннелей))