SSH-Bastion. Замковые ворота вашей инфраструктуры

Предисловие

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

Другая ситуация — Вы один администратор в компании с несколькими площадками  (офис, несколько серверов в ЦОДе, удаленная производственная площадка)

Что их объединяет? Необходимо предоставить удаленный, удобный и безопасный доступ к этим самым серверам ( и другому оборудованию) по различному набору протоколов — SSH, RDP, VNC, HTTP и еще много чего. Что в такой ситуации обычно предлагается сделать? — Да, поднять vpn сервер. Что обычно подразумевает под собой что нам нужно следить еще за одной службой — устанавливать ее, настраивать, разбираться в ее тонкостях, логировании и т.д. Если вы используете централизованное управление пользователями, как например Microsoft Active Directory, необходимо позаботиться о том, чтобы выбранное Вами vpn решение имело возможность интеграции.

Ну и наконец последнее — давайте вспомним, что означает буква N в слове VPN. N это Networks — вам необходимо предусмотреть выделенное IP пространство под VPN тунели, заниматься поддержкой маршрутизации. Все эти пункты по отдельности не кажутся страшными, но собираясь вместе — нарастают как страшный снежный ком.

Эта статья посвящена тому, какое альтернативное решение  можно использовать, не неся подобных технических затрат. 

Обращаю Ваше внимание — это не критика VPN как решения, это лишь попытка показать более простую альтернативу.

Приступим….

До фортификации

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

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

Хочется остановить все это и спрятать их всех за прочную стену. Но как тогда обеспечить доступ? Нам нужны ворота, нам нужна башня, защищающая эти ворота и строгий привратник. Все это зовется просто — Бастион Сервер. Так же его порой называют Access gateway.

Проектируем нашу защиту

Сейчас я хочу показать, как такое решение можно создать самому, используя opensource инструменты на базе Linux и не прибегая к платным проприетарным решениям.

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

Мы ставим 1 сервер, открываем наружу ( через корпоративный фаервол, или он сам может защитить себя своим фаерволом) 1 сервер, только ему даем доступ внутрь нашей DMZ. Что нам это дает:

  • Active directory base аутентификация. SSH как сервис, нативно используем PAM для аутентфикации и авторизации пользователей. Соедините его через sssd и realmd с Active Directory — получите нативную аутентификацию через доменные учетные записи, получите разграничение по группам, возможность включать и выключать в AD пользователю возможность подключаться к нему ( а значит и через него) извне.
  • Привычный в настройке и эксплуатации сервис. SSH — хорошо известный всем Linux ( да и не только Linux) администраторам сервис, привычный в настройке, с стойким шифрованием, способный пробрасывать порты и соединения, передавать файлы и многое другое!
  • Легко доступные и настраиваемые средства защиты. Помимо встроенных в саму реализацию средств обеспечения безопасности ( минимальные привилегии, ограничение числа подключений, доступ по ключам, стойкое шифрование) существуют так же дополнительные меры которые крайне легко настроить — например тот же Fail2ban.
  • Простота настройки доступа для нового сервера. Если раньше, чтобы обеспечить доступ извне к новому серверу, вам нужно было накрутить на нем методы безопасности, настроить правила фаервола для предоставления доступа извне, сейчас достаточно просто подключить интерфейс нового сервера в DMZ.

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

Строим

Так, наша задача:

  • Централизованная аутентификация
  • SSH харденинг
  • Fail2ban
  • Мониторинг
  • Настройки внутреннего Firewall

Централизованная аутентификация

Используем для этого SSSD. Это пакет приложений для управления аутентификацией и авторизацией в операционных системах на базе Linux. SSSD является отличной альтернативой монструозной Samba, позволяя подключить Linux машину к уже имеющемуся домену Active Directory.

Эта система использует LDAP и Kerberos (собственно как и Windows) для того чтобы связываться с контроллером домена AD. Умеет матчить юзеров AD в линуксовы, автоматом создавать домашний каталог, подтягивать группы из AD и т.д.

Короче получаем легко настраиваемые идентификацию аутентификацию и авторизацию. Настраиваем…

Первым делом проверяем, что в качестве DNS у нас установлен домен контроллер. И в принципе контроллеры домена должны быть доступны по dns, ldap и kerberos портам с этой машины. В данном примере мы используем 1 DC.

Устанавливаем реалм

Для ubuntu18.04 нужен вот такой фикс: https://askubuntu.com/questions/1067495/installation-candidate-for-ad-join-not-found

Проверяем доступность домена

В файл «/etc/realmd.conf» добавляем информацию об ОС

Ставим все необходимое

Вгоняем в домен

Указываем учетную запись любого пользователя из домена, не обязательно админа

  • user – логин доменного пользователя с правами, достаточными для ввода компьютера в домен AD. От имени этого пользователя будет выполняться присоединение компьютера к домену и модификация атрибутов доменной учётной записи компьютера. В классической ситуации — это пользователь с правами администратора домена, так как именно администраторы домена по умолчанию в AD могут обновлять значение атрибута servicePrincipalName. Однако я не очень люблю для «попсовых» задач использовать привилегии такого уровня, поэтому здесь я использую рядового доменного пользователя, у которого есть права на создание и модификацию объектов типа Computer в OU указанном в опции computer-ou;
  • user-principal – строка регистрации принципала Kerberos, которая будет использоваться для генерации keytab-файла и регистрации значений атрибута userPrincipalName в свойствах учётной записи компьютера в домене AD.
  • computer-ou – имя OU, в котором мы хотим создать учётную запись компьютера в домене. Если учётная запись уже существует, то она будет обновлена.
  • verbose – понятное дело, подразумевает расширенный вывод информации о всех происходящих действиях.

Все почти готово, остались последние шаги

Немного исправляем файл /etc/sssd/sssd.conf, приводя это к следующему виду:

+ ставим права на файл иначе без этого не заведется

В каталоге /etc/sudoers.d/ создаем файл ( имя не важно но пусть будет linux_admin) и Добавляем туда разрешение тем, кто входим в группу linux_admins вызывать sudo

Чтобы при логине нового юзера у нас автоматически создавался домашний каталог, в файл /etc/pam.d/common-session в конец добавляем строчку

Все сохраняем и перезапускаем sssd:

Как теперь разрешить доступ к серверам? В active directory у нас две группы:

  • linux_users
  • linux_admins

Будучи добавленным в любую из них, пользователь получает возможность логиниться на Linux сервер но только linux_admins может вызывать sudo 

Усиление SSH

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

Некоторый список best practices:

Но мне больше всего понравилась вот эта: https://www.atraining.ru/ssh-armoring/

В итоге у меня родился примерно следующий конфиг:

Fail2ban

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

Одной из дополнительных мер защиты, которую я настоятельно рекомендую применять в любом случае, является установка и настройка службы fail2ban. Это очень хороший инструмент борьбы с различными брутфорсерами и сканировщиками в автоматическом режиме без вашего участия. Инструмент парсит логи различных служб ( поддерживется очень большое число популярных — начиная от ssh и заканчивая различными ftp сервисами) на предмет нездоровой активности, вычисляет источник и банит его по ip адресу, добавляя в специально созданное правило firewall. Для общего развития советую так же ознакомиться вот с такой статьей на хабре.  

По умолчанию, fail2ban готов защищать ваш ssh сервер ( только в нашем случае нужно будет в настройках сменить порт с стандартного под псевдонимом ssh на тот который Вы указали в настройках sshd) 

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

Как разбанивать пострадавших, так же описано в предыдущей статье.

Мониторинг

Если вы еще не выбрали себе систему мониторинга, я настоятельно рекомендую начать с Zabbix. В случае сложных и серьезных проектов его первенство спорно — возможно лучше взять Prometheus или TICK/TIG стэк. Но в целом я ставлю под сомнение ситуацию, когда Вы решили ставить бастион сервер а системы мониторинга у вас нет.

Что нам нужно будет мониторить:

  • Целостность файлов с паролями, например /etc/shadow. Это zabbix делает по умолчанию.
  • Целостность файлов с ssh ключами сервера и конфигурационными файлами  sshd и sssd. Сделать это можно аналогично как это сделано для /etc/shadow.
  • Статистику fail2ban и статистику ssh по подключениям. Я для себя реализовал мониторинг ssh через логи, для f2b это можно сделать схожим образом.

Вот так выглядят элементы данных:

Настройки Firewall

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

Разрешенный входящий трафик:

  • порт 22/tpc — ssh
  • порт 10050/tpc — zabbix (тк в моем примере я ссылаюсь именно на него, однако никто не запрещает заменить его чем-то другим.) — опционально можно разрешить весь входящий трафик с сервера мониторинга ( в нашем примере это 10.0.1.13)

Разрешенный исходящий трафик:

  • порт 22/tpc — ssh
  • порт 53/udp — DNS
  • порты 67,68/udp — dhcp
  • порты 80,443/tpc — http/https — скачивание обновлений из интернет 
  • любые порты на 10.0.1.20 — обращение к домен контроллеру

Подключение через бастион

Как же нам теперь работать с внутренними сервисами, спросите Вы. А очень просто — я нарисую лишь варианты для ssh, однако один из них ( с пробросом порта), подойдет и для RDP и для VNC и для HTTP.

Сессия внутри сессии

Самый простой вариант — называется заходим на бастион сервер а потом заходим на нужный сервер. То есть сессия внутри сесии.

Как видно из лога выше, вначале произошла авторизация на бастион сервере, потом я  залогинился на вики сервер. Вся авторизация прошла с данными моей учетной записи AD.

Проброс портов

Не буду тут копипастить — просто приведу ссылки на готовые статьи как этим пользоваться:

Основная схема:

Пример: 

Jump через сервер

Основная статья вот она: https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts#Jump_Hosts_—_Passing_Through_a_Gateway_or_Two

Я только покажу пример:

А если при этом закинуть на бастион сервер свой ssh ключ и добавить в настройках ssh клиента директиву IdentityFile с полным путем до ключа — то вообще получается сказка!

Заключение

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

П.С. Подписывайтесь на мой Telegram канал