first-10-min.md 23 KB


title: "Первые 10 минут на сервере" date: 2022-10-09T00:38:39+03:00

tag: [linux]

Исходная статься на Хабрахабре.

{{< toc >}}

Азбука безопасности Ubuntu

«Мои первые 5 минут на сервере» Брайана Кеннеди — отличное введение, как быстро обезопасить сервер от большинства атак. У нас есть несколько исправлений для этой инструкции, чтобы дополнить ею наше полное руководство. Также хочется подробнее объяснить некоторые вещи для более юных инженеров.

Каждое утро я проверяю почтовые уведомления logwatch и получаю основательное удовольствие, наблюдая несколько сотен (иногда тысяч) безуспешных попыток получить доступ. (Многие довольно прозаичны — попытки авторизоваться как root с паролем 1234 снова и снова). Приведённая здесь общая методика подходит для серверов Debian/Ubuntu, которые лично мы предпочитаем всем остальным. Они обычно служат только хостами для контейнеров Docker, но принципы те же.

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

Примечание: Эта справка создана как базовая азбука. Её следует расширить и дополнить в соответствие с вашими потребностями.

В первую очередь

У нас ещё даже нет пароля для рута. Хотелось бы выбрать что-нибудь случайное и сложное. Используем генератор менеджера паролей с настройками максимальной сложности. Менеджер паролей сохраняет пароль и шифрует его, доступ к нему возможен только по длинному мастер-паролю. Здесь предусмотрена пара избыточных мер защиты (длинный, сложный случайный пароль + защита пароля шифрованием и другим длинным паролем). Используете вы парольный менеджер или другие инструменты, сохраняйте пароль в безопасности, применяя какую-нибудь форму шифрования. Вам понадобится только этот рутовый пароль в случае потери пароля sudo.

# passwd

{{< hint title=Примечание >}} На HN и Reddit развернулась интересная дискуссия о рутовых паролях. Её стоит почитать. {{< /hint >}}

Теперь следует обновить репозитории и накатить последние патчи. Далее будет отдельный раздел по автоматизации установки обновлений безопасности.

apt-get update
apt-get upgrade

Добавляем пользователя

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

useradd deploy
mkdir /home/deploy
mkdir /home/deploy/.ssh
chmod 700 /home/deploy/.ssh

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

usermod -s /bin/bash deploy

Помните: chmod 700 означает, что владелец аккаунта обладает правами на чтение, запись и запуск программ. Мы всё ещё находимся с правами рута, но через минуту мы запустим команду chown рекурсивно на этой папке для пользователя deploy и группы deploy. Только этот пользователь должен иметь право работать с папкой .ssh.

Аутентификация по ключу ssh

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

  1. Ключи ssh лучше паролей только потому, что они содержат и требуют больше информации.
  2. Пароли можно подобрать брутфорсом. Гадать по публичному ключу по существу невозможно, так что их можно считать полностью безопасными.
  3. Что насчёт кражи компьютера? Да, там ваши секретные ключи, но отозвать ssh-key легко, достаточно просто удалить открытый ключ из authorized_keys. Вам следует также защитить секретный ключ безопасной и длинной парольной фразой. См. следующий пункт.
  4. Всё это работает ТОЛЬКО ПРИ УСЛОВИИ БЕЗОПАСНОЙ И ДЛИННОЙ ПАРОЛЬНОЙ ФРАЗЫ, ЗАЩИЩАЮЩЕЙ КЛЮЧ. Повторяем второй раз, потому что это критически важно.

Итак, оставим в прошлом аутентификацию по паролю. Скопируйте содержимое id_rsa.pub[^1] со своей локальной машины на серверы в файл authorized_keys. [^1]: Убедитесь, что указан именно .pub. Это кажется очень простым, но я встречал двух товарищей (оба не работают в нашей компании — они бы быстро прекратили здесь работать) за свою карьеру, которые прислали мне свои секретные ключи (id_rsa без расширения .pub), когда я попросил прислать открытый ключ.

vim /home/deploy/.ssh/authorized_keys

Установим правильные привилегии, руководствуясь принципом безопасности Linux, известным как принцип минимальных привилегий:

chmod 400 /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy -R

chmod 400 устанавливает разрешения, так что файл может прочитать только владелец. Другая команда chown делает пользователя deploy и группу deploy владельцами (рекурсивно) их домашней директории. Мы упоминали об этом ранее, когда устанавливали разрешения на чтение, запись и исполнение для владельца этой директории.

Вернёмся к этому чуть позже, когда правильно протестируем нашего пользователя deploy и sudo для отключения авторизации рута и установки авторизации только по ключу ssh.

Тестирование пользователя deploy и установка sudo

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

passwd deploy

Установка sudo простая. Открываем файл sudo:

visudo

Добавляем группу %sudo под рутовым пользователем, как показано ниже. Убедитесь, что все остальные пользователи и группы отбиты комментариями с символом # (у пользователей нет префиксов, а группы начинаются с %). На большинстве свежих установок там ничего нет, но на всякий случай.

root ALL=(ALL) ALL
%sudo ALL=(ALL:ALL) ALL

Теперь добавим пользователя deploy в группу sudo.

usermod -a -G sudo deploy

Это предоставит пользователю deploy доступ к sudo после введения пароля, который мы только что создали.

{{< hint title="Замечание к исправлению" >}} Спасибо пользователю ackackacksyn на Reddit за верное замечание, что не следует добавлять пользователей напрямую в список sudo. {{< /hint >}}

Активируем вход по ключу ssh

Конфигурация ssh для этой машины хранится здесь:

vim /etc/ssh/sshd_config

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

PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy@(your-VPN-or-static-IP)

Активируйте все эти правила, перезапустив службы ssh. Вероятно, придётся переподключиться (делайте это через пользователя deploy!).

service ssh restart

Установка файрвола

Обычно здесь два лагеря. Одни используют IPtables напрямую, а другие применяют удобный интерфейс под названием ufw, который представляет собой слой над IPtables для упрощения процесса настройки. Более простой вариант обычно предпочтительнее с точки зрения безопасности. ufw от DigitalOcean действительно неплох и помогает в основных вещах.

ufw установлен по умолчанию на Ubuntu, а на Debian достаточно запустить команду apt-get install ufw.

По умолчанию ufw должен отказывать во всех входящих подключениях и разрешать все исходящие, однако, он не будет запущен (потому что иначе как бы вы подключились?). Мы пройдёмся и явно разрешим соединения, которые считаются нормальными.

Во-первых, следует убедиться в поддержке IPv6. Откройте конфигурационный файл.

sudo vim /etc/default/ufw

Установите IPv6 в значение yes.

IPV6=yes

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

sudo ufw allow from {your-ip} to any port 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw disable
sudo ufw enable

Первое — это избыточная мера, которая гарантирует, что только соединения с нашего IP-адреса могут соединяться по SSH (стандартный порт SSH)[^2] Вторая и третья команда открывают трафик http и https. [^2]: Мнения расходятся, назначать ли для соединений SSH стандартный или нестандартный порт. См. здесь и здесь аргументы обеих сторон.

{{< hint title=Примечание >}} Спасибо chrisfosterelli за замечание, что если вы собираетесь установить первое правило (а вам следует это сделать), то убедитесь, что у вас статичный IP-адрес или безопасный VPN, к которому вы подключаетесь. Динамический IP-адрес оставит вас без доступа к серверу когда-нибудь в будущем. {{< /hint >}}

Автоматические обновления безопасности

Мне они нравятся. Они не идеальны, но это лучше, чем пропустить патчи после их выхода.

sudo apt-get install unattended-upgrades
vim /etc/apt/apt.conf.d/10periodic

Обновите этот файл следующим образом:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

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

sudo vim /etc/apt/apt.conf.d/50unattended-upgrades

Отредактируйте файл следующим образом:

Unattended-Upgrade::Allowed-Origins {
"Ubuntu lucid-security";
//"Ubuntu lucid-updates";
};

Всё готово.

Fail2ban

Fail2ban

fail2ban — отличный пакет, который проактивно блокирует подозрительную активность, как только она обнаружена. В их вики сказано, что fail2ban сканирует файлы логов (например, /var/log/apache/error_log) и банит IP-адреса, которые проявляют подозрительные признаки — слишком много попыток ввода неправильного пароля, поиск эксплоитов и проч… Сразу после установки Fail2Ban оснащён фильтрами для различных сервисов (apache, courier, ssh и др.).

sudo apt-get install fail2ban

Двухфакторная аутентификация

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

  1. Доступ к вашему сертификату и ключу для доступа к VPN.
  2. Доступ к вашему компьютеру, чтобы получить секретный ключ.
  3. Доступ к вашей парольной фразе для секретного ключа.
  4. Доступ к вашему телефону для двухфакторной аутентификации.

Это немало барьеров (четыре), которые придётся преодолеть. Даже если они получат рутовый доступ через sudo, им придётся найти пароль deploy, который защищён шифрованием AES (пятый барьер).

Устанавливаем пакет.

sudo apt-get install libpam-google-authenticator

Для установки запускаем команду и следуем инструкциям:

su deploy
google-authenticator

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

Logwatch

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

У DigitalOcean есть отличное описание установки и настройки Logwatch, но если мы хотим уложиться в 10 минут, то просто установим его и сделаем задание cron для ежедневного запуска и отправки письма по электронной почте.

sudo apt-get install logwatch

Добавляем задание cron.

sudo vim /etc/cron.daily/00logwatch

Добавьте следующую строку в файл cron:

sudo /usr/sbin/logwatch --output mail --mailto you@example.com --detail high

Всё готово

Ну вот. После завершения всего вышеперечисленного вашей основной заботой и точкой сбоя станет ваше приложение и сервисы. Это совершенно другая область.

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