Первые 10 минут на сервере
«Мои первые 5 минут на сервере» Брайана Кеннеди — отличное введение, как быстро обезопасить сервер от большинства атак. У нас есть несколько исправлений для этой инструкции, чтобы дополнить ею наше полное руководство. Также хочется подробнее объяснить некоторые вещи для более юных инженеров.
Каждое утро я проверяю почтовые уведомления logwatch и получаю основательное удовольствие, наблюдая несколько сотен (иногда тысяч) безуспешных попыток получить доступ. (Многие довольно прозаичны — попытки авторизоваться как root с паролем 1234 снова и снова). Приведённая здесь общая методика подходит для серверов Debian/Ubuntu, которые лично мы предпочитаем всем остальным. Они обычно служат только хостами для контейнеров Docker, но принципы те же.
На больших масштабах лучше использовать полностью автоматические установки с инструментами вроде Ansible или Shipyard, но иногда вы просто поднимаете единственный сервер или подбираете задачи для Ansible — для таких ситуаций предназначена инструкция.
Примечание: Эта справка создана как базовая азбука. Её следует расширить и дополнить в соответствие с вашими потребностями.
В первую очередь
У нас ещё даже нет пароля для рута. Хотелось бы выбрать что-нибудь случайное и сложное. Используем генератор менеджера паролей с настройками максимальной сложности. Менеджер паролей сохраняет пароль и шифрует его, доступ к нему возможен только по длинному мастер-паролю. Здесь предусмотрена пара избыточных мер защиты (длинный, сложный случайный пароль + защита пароля шифрованием и другим длинным паролем). Используете вы парольный менеджер или другие инструменты, сохраняйте пароль в безопасности, применяя какую-нибудь форму шифрования. Вам понадобится только этот рутовый пароль в случае потери пароля sudo.
*Примечание: На HN и Reddit развернулась интересная дискуссия о рутовых паролях. Её стоит почитать.
Теперь следует обновить репозитории и накатить последние патчи. Далее будет отдельный раздел по автоматизации установки обновлений безопасности.
apt-get update
apt-get upgrade
Добавляем пользователя
Вам никогда не следует заходить на сервер как рут. Мы следуем тем же правилам при создании пользователей, которые установил Брайан Кеннеди, но вы можете использовать собственные. У нашей маленькой команды не было проблем с использованием единственного пользователя для авторизации, но в больших командах лучше создать разных пользователей с разными уровнями привилегий, где только избранные получают привилегии sudo.
useradd deploy
mkdir /home/deploy
mkdir /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
Устанавливаем предчтительную оболочку для пользователя deploy, мы используем bash:
Помните: chmod 700 означает, что владелец аккаунта обладает правами на чтение, запись и запуск программ. Мы всё ещё находимся с правами рута, но через минуту мы запустим команду chown рекурсивно на этой папке для пользователя deploy и группы deploy. Только этот пользователь должен иметь право работать с папкой .ssh.
Аутентификация по ключу ssh
Мы стараемся не использовать пароли для входа на сервер. Насчёт этого было много споров после того как вышла инструкция Брайана, но я тоже склонен согласиться с такой позицией. Вот несколько замечаний на этот счёт:
- Ключи ssh лучше паролей только потому, что они содержат и требуют больше информации.
Установим правильные привилегии, руководствуясь принципом безопасности 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. Снова мы запускаем парольный менеджер для генерации сложного и случайного пароля, сохраняем его в зашифрованном виде и сообщаем коллегам (синхронизация зашифрованного файла с паролем).
Установка sudo простая. Открываем файл sudo:
Добавляем группу %sudo под рутовым пользователем, как показано ниже. Убедитесь, что все остальные пользователи и группы отбиты комментариями с символом # (у пользователей нет префиксов, а группы начинаются с % ). На большинстве свежих установок там ничего нет, но на всякий случай.
root ALL=(ALL) ALL
%sudo ALL=(ALL:ALL) ALL
Теперь добавим пользователя deploy в группу sudo .
Это предоставит пользователю deploy доступ к sudo после введения пароля, который мы только что создали.
Замечание к исправлению: спасибо пользователю ackackacksyn на Reddit за верное замечение, что не следует добавлять пользователей напрямую в список sudo.
Активируем вход по ключу ssh
Конфигурация ssh для этой машины хранится здесь:
Вы захотите добавить туда несколько строк. Мне кажется, они довольно понятны сами по себе. Это IP-адрес, который вы используете для подключения. У нас в компании используется VPN-конфигурация с OpenVPN и криптографической аутентификацией, так что для подключения к серверу нужно также пройти аутентификацию и быть подключённым к VPN.
PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy@(your-VPN-or-static-IP)
Активируйте все эти правила, перезапустив службы ssh. Вероятно, придётся переподключиться (делайте это через пользователя deploy!).
Установка файрвола
Обычно здесь два лагеря. Одни используют IPtables напрямую, а другие применяют удобный интерфейс под названием ufw , который представляет собой слой над IPtables для упрощения процесса настройки. Более простой вариант обычно предпочтительнее с точки зрения безопасности. ufw от DigitalOcean действительно неплох и помогает в основных вещах.
ufw установлен по умолчанию на Ubuntu, а на Debian достаточно запустить команду apt-get install ufw .
По умолчанию ufw должен отказывать во всех входящих подключениях и разрешать все исходящие, однако, он не будет запущен (потому что иначе как бы вы подключились?). Мы пройдёмся и явно разрешим соединения, которые считаются нормальными.
Во-первых, следует убедиться в поддержке IPv6. Откройте конфигурационный файл.
Установите IPv6 в значение yes .
Для остальных портов, которые мы собираемся открыть, можно просто использовать инструмент ufw из командной строки, что очень удобно.
sudo ufw allow from to any port 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw disable
sudo ufw enable
Первое — это избыточная мера, которая гарантирует, что только соединения с нашего IP-адреса могут соединяться по SSH (стандартный порт SSH) 2 . Вторая и третья команда открывают трафик http и https.
Примечание: Спасибо chrisfosterelli за замечание, что если вы собираетесь установить первое правило (а вам следует это сделать), то убедитесь, что у вас статичный IP-адрес или безопасный VPN, к которому вы подключаетесь. Динамический IP-адрес оставит вас без доступа к серверу когда-нибудь в будущем.
Автоматические обновления безопасности
Мне они нравятся. Они не идеальны, но это лучше, чем пропустить патчи после их выхода.
apt-get install unattended-upgrades
Обновите этот файл следующим образом:
APT::Periodic::Update-Package-Lists «1»;
APT::Periodic::Download-Upgradeable-Packages «1»;
APT::Periodic::AutocleanInterval «7»;
APT::Periodic::Unattended-Upgrade «1»;
Я в целом согласен с Брайаном, что лучше отключить обычные обновления, а оставить только обновления безопасности. Идея в том, что будет не очень хорошо, если приложение внезапно перестанет работать из-за обновления какого-то пакета с зависимостями, в то время как обновления безопасности очень редко создают проблемы с зависимостями на уровне приложения.
Отредактируйте файл следующим образом:
Unattended-Upgrade::Allowed-Origins «Ubuntu lucid-security»;
//»Ubuntu lucid-updates»;
>;
Fail2ban
fail2ban — отличный пакет, который проактивно блокирует подозрительную активность, как только она обнаружена. В их вики сказано, что fail2ban сканирует файлы логов (например, /var/log/apache/error_log ) и банит IP-адреса, которые проявляют подозрительные признаки — слишком много попыток ввода неправильного пароля, поиск эксплоитов и проч… Сразу после установки Fail2Ban оснащён фильтрами для различных сервисов (apache, courier, ssh и др.).
Двухфакторная аутентификация
Двухфакторная аутентификация обязательна, если мы проектируем систему, которая соответствует нормам безопасности. Теоретически, если вы активируете двухфакторную аутентификацию поверх всех остальных защитных мер, то тогда для получения доступа к серверу (через вскрытие уязвимостей в приложениях), нападающим придётся также иметь:
- Доступ к вашему сертификату и ключу для доступа к VPN.
- Доступ к вашему компьютеру, чтобы получить секретный ключ.
- Доступ к вашей парольной фразе для секретного ключа.
- Доступ к вашему телефону для двухфакторной аутентификации.
apt-get install libpam-google-authenticator
Для установки запускаем команду и следуем инструкциям:
su deploy
google-authenticator
Двухфакторная аутентификация устанавливается очень легко и добавляет хороший дополнительный уровень безопасности.
Logwatch
Этот инструмент скорее для удовольствия и мониторинга постфактум. Logwatch отслеживает логи и в соответствии с настройками высылает по почте ежедневную красиво структурированную сводку. Это довольно занимательные данные, и вы удивитесь, как много попыток доступа к серверу происходит каждый день. Я установил его только для того, чтобы продемонстрировать коллегам, насколько важно иметь хорошую безопасность.
У DigitalOcean есть отличное описание установки и настройки Logwatch, но если мы хотим уложиться в 10 минут, то просто установим его и сделаем задание cron для ежедневного запуска и отправки письма по электронной почте.
Добавьте следующую строку в файл cron:
/usr/sbin/logwatch —output mail —mailto you@example.com —detail high
Всё готово
Ну вот. После завершения всего вышеперечисленного вашей основной заботой и точкой сбоя станет ваше приложение и сервисы. Это совершенно другая область.
Мы пытаемся максимально формализовать и описать наши лучшие практики и процессы, если хотите узнать больше, изучите наш репозиторий. Всё в открытом доступе, и мы продолжаем пополнять его.
1 Убедитесь, что указан именно `.pub`. Это кажется очень простым, но я встречал двух товарищей (оба *не* работают в нашей компании — они бы быстро прекратили здесь работать) за свою карьеру, которые прислали мне свои секретные ключи (`id_rsa` без расширения .pub), когда я попросил прислать открытый ключ. Вернуться к статье
2 Мнения расходятся, назначать ли для соединений SSH стандартный или нестандартный порт. См. здесь и здесь аргументы обеих сторон. Вернуться к статье