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

Привет! Меня зовут Марк, я методолог по информационной безопасности в Selectel. В этой статье расскажу, как использовать механизм cloud-init для базовой настройки параметров безопасности облачных Linux-серверов в небольших проектах. Рассмотрим, каким образом такая практика помогает реализовать меры по обеспечению безопасности персональных данных в соответствии с Приказом ФСТЭК № 21.

Приглашаем 10 октября на Selectel Tech Day
Расскажем о новинках на рынке и обновлениях в наших продуктах. Вас ждут доклады, нетворкинг, мастер-классы и вечерняя программа. Участие бесплатное, но нужно зарегистрироваться.


Используйте навигацию, если не хотите читать текст полностью:

О каких рисках стоит задуматься
Настройка безопасной конфигурации
    → Управление административным доступом
    → Противодействие подбору учетных данных
    → Фильтрация трафика
    → Журнал событий безопасности
    → Применение настроек
Итоги

О каких рисках стоит задуматься


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

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

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

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

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

Чтобы быть уверенным в безопасности сервера, нужно исключить период ручной первоначальной настройки, когда защитные механизмы еще не активны и система находится в уязвимом состоянии. Что предпринять, чтобы при развертывании сервиса не потерять деловую репутацию? И как не стать невольным соучастником противоправных действий при запуске pet-проекта?



Настройка безопасной конфигурации


Ботов очень много, и они невероятно быстры. В этой игре на время выигрышной является стратегия создания виртуальных серверов сразу в базовой безопасной конфигурации. Другими словами, необходимо настроить систему до ее первого запуска. Для этого мы зададим пользовательские параметры user data, которые будут автоматически применены при первой загрузке с использованием механизма cloud-init.

user data — данные конфигурации, которые передает пользователь облачной платформы экземпляру cloud-init при запуске. Форматов для хранения user data несколько — мы использовали YAML как наиболее удобный. Подробнее можно прочитать в нашей статье и документации разработчиков.

Рассмотрим несколько основных параметров, а также простых и проверенных временем инструментов. Для описания user data будем использовать YAML-файл, который мы шаг за шагом заполним при составлении конфигурации.

Управление административным доступом


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

Создадим новую группу admins и входящего в нее пользователя admin. Далее включим его в группу sudo, дадим разрешение на выполнение команд с повышенными привилегиями без ввода пароля, зададим Bash командной оболочкой по умолчанию и добавим публичный SSH-ключ администратора в список авторизованных ключей ~/.ssh/authorized_keys.

Здесь и далее отдельные настройки будут сопровождаться ссылкой на принятое ФСТЭК обозначение соответствующей меры защиты персональных данных.

В контексте приказа ФСТЭК России № 21 такой подход соответствуют реализации мер ИАФ.3, ИАФ.5 и УПД.1. Причем мера ИАФ.5 (защита обратной связи при вводе аутентификационной информации) реализуется за счет того, что интерактивный ввод пароля не используется, а значит, его невозможно и подсмотреть.

Для cloud-init выполненные настройки описываются в следующем формате:

groups:
  - admins
users:
  - name: admin
    primary_group: admin
    groups:
      - sudo
      - admins
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - <ssh_public_key>

Теперь скорректируем настройки SSH-сервера путем перезаписи отдельных строк конфигурационного файла /etc/ssh/sshd_config с использованием утилиты sed:

runcmd:
  - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
  - sed -i -e '/^PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
  - sed -i -e '/^#ClientAliveInterval/s/^.*$/ClientAliveInterval 5m/' /etc/ssh/sshd_config
  - sed -i -e '/^#ClientAliveCountMax/s/^.*$/ClientAliveCountMax 3/' /etc/ssh/sshd_config
  - sed -i -e '$aAllowGroups admins' /etc/ssh/sshd_config

Указанные параметры запрещают аутентификацию по паролю при использовании SSH, а также вход пользователя root и любых других пользователей, не принадлежащих ранее созданной группе admins (меры ИАФ.1 и УПД.2). Кроме того, реализуется автоматическое завершение открытой SSH-сессии на стороне сервера при отсутствии сетевой активности SSH-клиента в течение 15 минут — например, при переходе компьютера администратора в спящий режим или при потере интернет-соединения.

Если по какой-то причине администратор оставил компьютер с открытой SSH-сессией незаблокированным, в теории есть риск неконтролируемого доступа к управлению сервером. Чтобы избежать этого, задаем значение переменной окружения TMOUT равным 900:

runcmd:
  - printf "%s\n""readonly TMOUT=900" "export TMOUT" >> /etc/profile

Если пользователь не совершал никаких действий на сервере в течение заданных 900 секунд (15 минут), происходит автоматический выход из учетной записи и завершение SSH-сессии с отправкой стандартного сообщения «timed out waiting for input: auto-logout» (мера УПД.10).

Противодействие подбору учетных данных


В качестве дополнительной меры защиты можно реализовать автоматическую блокировку IP-адресов, с которых пытаются подобрать учетные данные (логин и пароль) для подключения по SSH (мера УПД.6). Для этого используем пакет fail2ban:

package_update: true
packages:
  - fail2ban
write_files:
  - path: /etc/fail2ban/jail.local
    permissions: 0640
    owner: root:root
    content: |
      [sshd]
      enabled = true
      findtime = 1m
      nmaxretry = 5
      bantime = 15m
runcmd:
  - systemctl enable fail2ban

Параметры fail2ban задаются в конфигурационном файле /etc/fail2ban/jail.local и предполагают 15-минутную блокировку IP-адреса, если в течение минуты было предпринято пять неудачных попыток входа по SSH.

Фильтрация трафика


Следующим шагом настроим базовые правила фильтрации входящего трафика с использованием встроенного межсетевого экрана iptables:

package_update: true
packages:
  - iptables-persistent
write_files:
  - path: /etc/iptables/rules.v4
    permissions: 0640
    owner: root:root
    content: |
      *filter
      :INPUT DROP [0:0]
      :FORWARD DROP [0:0]
      :OUTPUT ACCEPT [0:0]
      -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
      -A INPUT -i lo -j ACCEPT
      -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
      -A INPUT -p icmp --icmp-type 0 -j ACCEPT
      -A INPUT -p icmp --icmp-type 3 -j ACCEPT
      -A INPUT -p icmp --icmp-type 11 -j ACCEPT
      COMMIT

Базовые правила фильтрации для IPv4-трафика, разрешающие по умолчанию только входящие подключения по SSH и сетевое взаимодействие в рамках инициированных сервером соединений (мера УПД.3), описаны в правилах /etc/iptables/rules.v4. Для автоматической загрузки правил из файла устанавливается пакет iptables-persistent. Также в целях безопасности рекомендуется отключить обработку IPv6-трафика:

runcmd:
  - printf "%s\n" "net.ipv6.conf.all.disable_ipv6 = 1" "net.ipv6.conf.default.disable_ipv6 = 1" "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf && sysctl -p

Журнал событий безопасности


Завершающим этапом является настройка логирования событий безопасности (меры РСБ.1 и РСБ.3). Все действия, связанные с попытками аутентификации пользователей, удаленного подключения к серверу, а также с созданием, изменением, удалением учетных записей, фиксируются по умолчанию компонентами операционной системы (PAM). Однако для своевременного выявления подозрительных действий рекомендуется настроить мониторинг изменения основных лог-файлов, повышения привилегий, изменения прав доступа. Для этого используем возможности подсистемы Linux Audit (auditd):

package_update: true
packages:
  - auditd
write_files:
  - path: /etc/audit/rules.d/audit.rules
    permissions: 0640
    owner: root:root
    content: |
      -D
      -e 1
      -f 1
      -a always,exclude -F msgtype=CWD
      -a always,exclude -F msgtype=PATH
      -a always,exclude -F msgtype=PROCTITLE
      -a always,exit -F dir=/var/log/audit/ -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F path=/var/log/syslog -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F path=/var/log/auth.log -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F arch=x86_64 -S setuid -F auid!=unset -F a0=0 -F exe=/usr/bin/su -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S setresuid -F auid!=unset -F a0=0 -F exe=/usr/bin/sudo -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S execve -F auid!=unset -C uid!=euid -F euid=0 -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S chmod -S fchmod -S chown -S fchown -S lchown -F auid!=unset -F key=access-rights-modification

Описанные типы событий безопасности будут записываться в журнал /var/log/audit/audit.log и могут быть просмотрены непосредственно в файле или с использованием утилит ausearch и aureport. При необходимости список событий может быть дополнен в правилах /etc/audit/rules.d/audit.rules.

Применение настроек


Для применения всех выполненных настроек необходимо перезагрузить сервер.

Содержимое user data с учетом всего вышесказанного:

#cloud-config
package_update: true
packages:
  - iptables-persistent
  - fail2ban
  - auditd
groups:
  - admins
users:
  - name: admin
    primary_group: admin
    groups:
      - sudo
      - admins
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - <ssh_public_key>
write_files:
  - path: /etc/iptables/rules.v4
    permissions: 0640
    owner: root:root
    content: |
      *filter
      :INPUT DROP [0:0]
      :FORWARD DROP [0:0]
      :OUTPUT ACCEPT [0:0]
      -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
      -A INPUT -i lo -j ACCEPT
      -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
      -A INPUT -p icmp --icmp-type 0 -j ACCEPT
      -A INPUT -p icmp --icmp-type 3 -j ACCEPT
      -A INPUT -p icmp --icmp-type 11 -j ACCEPT
      COMMIT
  - path: /etc/fail2ban/jail.local
    permissions: 0640
    owner: root:root
    content: |
      [sshd]
      enabled = true
      findtime = 1m
      nmaxretry = 5
      bantime = 15m
  - path: /etc/audit/rules.d/audit.rules
    permissions: 0640
    owner: root:root
    content: |
      -D
      -e 1
      -f 1
      -a always,exclude -F msgtype=CWD
      -a always,exclude -F msgtype=PATH
      -a always,exclude -F msgtype=PROCTITLE
      -a always,exit -F dir=/var/log/audit/ -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F path=/var/log/syslog -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F path=/var/log/auth.log -F perm=wa -F auid!=unset -F key=audit-trail-modification
      -a always,exit -F arch=x86_64 -S setuid -F auid!=unset -F a0=0 -F exe=/usr/bin/su -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S setresuid -F auid!=unset -F a0=0 -F exe=/usr/bin/sudo -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S execve -F auid!=unset -C uid!=euid -F euid=0 -F key=elevated-privileges-session
      -a always,exit -F arch=x86_64 -S chmod -S fchmod -S chown -S fchown -S lchown -F auid!=unset -F key=access-rights-modification
runcmd:
  - printf "%s\n""readonly TMOUT=900" "export TMOUT" >> /etc/profile
  - printf "%s\n" "net.ipv6.conf.all.disable_ipv6 = 1" "net.ipv6.conf.default.disable_ipv6 = 1" "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf && sysctl -p
  - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
  - sed -i -e '/^PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
  - sed -i -e '/^#ClientAliveInterval/s/^.*$/ClientAliveInterval 5m/' /etc/ssh/sshd_config
  - sed -i -e '/^#ClientAliveCountMax/s/^.*$/ClientAliveCountMax 3/' /etc/ssh/sshd_config
  - sed -i -e '$aAllowGroups admins' /etc/ssh/sshd_config
  - systemctl enable fail2ban
  - reboot

Для использования описанной конфигурации необходимо внести в нее свои данные — как минимум публичный SSH-ключ <ssh_public_key> — и сохранить в текстовом файле, например, cloud-config.txt. При создании нового облачного сервера в панели управления my.selectel.ru в разделе Автоматизация нужно выбрать опцию Файл, указать путь к сохраненному файлу конфигурации или просто перетащить его в выделенное поле.


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

После запуска сервера к нему можно подключаться по SSH с использованием заданного в конфигурации имени пользователя (в описанном примере — admin) и соответствующего ключа. Для дополнительной защиты рекомендуется зашифровать используемые SSH-ключи парольной фразой.

Итоги


Описанные в статье действия позволяют:
  • предпринять базовые меры безопасности, необходимые для начала работы с облачным сервером;
  • успешно противодействовать ботам, атакующим хост сразу после создания;
  • реализовать часть обязательных мер защиты персональных данных в соответствии с требованиями ФСТЭК России.

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

Читайте также:

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


  1. VenbergV
    20.08.2024 15:24
    +6

    Уже простите за занудство, но за ручную правку sshd_config нужно бить не только по рукам, но и по голове. Для пользовательских настроек существует папка sshd_config.d.
    Ну и тащить iptables-persistentв Ubuntu 24.04 совсем моветон. Т.к. там изначально уже работает nftables. И простые правила nftables выглядят не страшнее правил iptables.
    P.S. Сейчас все меняется очень быстро (впрочем как и всегда). Хорошие наработки двухлетней давности могут быть устаревшими (deprecated). А работать с этим "свеже-настроенным" наследием (legacy) придется пару лет. Пока дистрибутив не уйдет с поддержки.


    1. markpeskov Автор
      20.08.2024 15:24
      +4

      Спасибо за обстоятельный комментарий, замечания справедливые.

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

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

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

      Я не оправдываю использование неподдерживаемых компонентов — ПО надо обновлять своевременно. Однако даже у именитых российских и зарубежных вендоров есть решения, в том числе в области безопасности (!), под капотом которых можно с удивлением обнаружить Debian 7.


      1. mayorovp
        20.08.2024 15:24

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


  1. eyeDM
    20.08.2024 15:24
    +1

    Объясните, в чём преимущества использования учётки admin со входом по SSH-ключу и запуск sudo без ввода пароля по сравнению с подключением с аналогичным ключом, но сразу под root'ом?

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

    По моему опыту, удобнее подключиться root'ом с ключом, обязательно защищённым паролем и опционально лежащим в ssh-агенте, выполнить нужные команды и отключиться. Ну или сначала зайти под кастомной учёткой с нетипичным логином, а потом набрать su -.


    1. Alexx_B
      20.08.2024 15:24
      +2

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

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


  1. Antra
    20.08.2024 15:24

    В качестве идеи для следующей статьи - как обойтись без fail2ban: рассказать про настройки с использованием новых openssh фич (Penalties).