Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи

в 9:07, , рубрики: Linux для всех, selinux, безопасность linux, Блог компании Сервер Молл, Настройка Linux, Серверное администрирование, системное администрирование

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 1

Несмотря на то, что Linux по праву считается более защищенной системой, чем MS Windows, самого по себе этого факта мало.

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

Где начать закручивать гайки

Первая и самая главная рекомендация ― аккуратнее относиться к инструкциям в интернете. К сожалению, часто эти инструкции содержат неактуальную, а то и вредную информацию и не объясняют, почему делается так, а не иначе. Всегда надо понимать, что именно вы делаете. Копировать же команды в консоль и вовсе опасно.

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

В сети часто встречаются рекомендации не работать под пользователем root ― суперпользователем, обладающим полными правами на все. Отчасти рекомендация верная: работать под root небезопасно с точки зрения фатальности возможных ошибок и опасности перехвата пароля.

Так как реально на сервере вы работаете пару раз за год, и при этом занимаетесь в основном обновлением или небольшой правкой конфигов, работа с рут-правами напоминает как раз временное повышение привилегий с помощью sudo. Но ряд разумных мер предосторожности все равно не помешает:

  • в идеале настроить вход на сервер по ключам;

  • не вводить пароль от суперпользователя на ненадежных машинах;

  • не использовать простые или словарные пароли. Можно и вовсе переименовать пользователя root, только сначала лучше проверить последствия в тестовой среде.

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

Защищаем файловую систему

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

В каждом дистрибутиве используется так называемая избирательная система доступа. Например, возможность пользователя открыть файл проверяется по списку управления доступом (Access Control List, ACL) ― какие «галочки» для этого пользователя включены.

Хороший принцип в обеспечении безопасности – предоставлять только те права, которые действительно необходимы для работы.

В частности, в системах Linux для файлов используется следующий механизм предоставления доступа:

  • у каждого объекта есть три параметра доступа ― для владельца, для группы пользователей, куда входит владелец и для всех остальных;

  • каждый параметр может принимать комбинацию из трех значений ― можно читать, можно изменять, можно запускать.

Право доступа удобно представить в числовом виде. Число будет трехзначным, вычисляемым по простой схеме:

Тип доступа Владалец Группа Все
Право читать 400 40 4
Право изменять 200 20 2
Право запускать 100 10 1

Таким образом, право на полные права для всех на объект будут выглядеть как: (400+200+100) + (40+20+10)+(4+2+1) = 777. Такие права, как правило, не нужны никогда и никому, допустимо их выставлять лишь в процессе отладки.

Подобный механизм доступа иногда называется UGO (User-Group-Others).

Подробнее о правах доступа и работе с ними можно почитать в соответствующих материалах.

Конечно, не всегда такой механизм доступа удобен. Например, при необходимости дать права пользователю на конкретный объект придётся добавлять его в группу, а то и создавать новую. Поэтому в системах UNIX добавлен чуть усложненный механизм доступа, называемый ACL. Он поддерживает уже более гибкие и сложные списки доступа.

По умолчанию эта система отключена. Для ее включения необходимо монтировать жесткий диск с опцией acl. Для примера включим acl для корневого раздела, добавив опцию монтирования в /etc/fstab:

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 2
Теперь система загрузится с поддержкой расширенных ACL.

Теперь можно управлять списками доступа с помощью команды setfacl. Просмотр текущих разрешений ― getfacl.

Подробнее ознакомиться можно в документации, я же для примера дам полные права доступа пользователю user на файл test.txt:

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 3
Предоставление полных прав пользователю user.

Механизм защиты довольно прост, эффективен… и напоминает ACL в файловой системе NTFS.

Огненная стена на автобане

Основной механизм для защиты доступа к серверу ― традиционно фаерволл. В системах GNULinux для этого используется встроенный в ядро netfilter.

Для желающих освежить в памяти основные принципы работы этого фаервола ― добро пожаловать под спойлер.

В системе netfilter трафик проходит через так называемые цепочки. Цепочка ― это упорядоченный список правил. В каждом правиле есть критерии для фильтрации пакета и действие, которое нужно совершить с пакетом, попавшим под эти критерии. Критериев существует довольно много, действия по умолчанию:

  • ACCEPT. Пропускаем пакет;

  • DROP. Удаляем пакет;

  • QUEUE. Передаем пакет на анализ внешней программе;

  • RETURN. Возвращаем пакет в предыдущую цепочку.

Цепочки по умолчанию выглядят так:

  • PREROUTING. Изначальная обработка входящих пакетов;

  • INPUT. Обработка входящих пакетов, адресованных непосредственно локальному процессу;

  • FORWARD. Обработка входящих пакетов, перенаправленных на выход. Нужно отметить, что перенаправляемые пакеты проходят сначала цепочку PREROUTING, затем FORWARD и POSTROUTING;

  • OUTPUT. Обработка пакетов, генерируемых локальными процессами;

  • POSTROUTING. Окончательная обработка исходящих пакетов.

Разумеется, цепочки можно создавать и свои. В свою очередь цепочки для удобства работы объединены в следующие таблицы:

  • raw. Эта таблица просматривается до передачи пакета системе определения состояний. Используется довольно редко, содержит цепочки PREROUTING и OUTPUT;

  • mangle. Содержит правила модификации IP‐пакетов. Как правило, модифицируется заголовок пакета. Содержит все пять стандартных цепочек;

  • nat. Работает только с пакетами, создающими новое соединение. Помимо стандартных, поддерживает действия DNAT, SNAT, MASQUERADE, REDIRECT. В современных операционных системах содержит цепочки PREROUTING, INPUT, OUTPUT, и POSTROUTING;

  • filter ― основная таблица. Используется по умолчанию, если название таблицы не указано. Содержит цепочки INPUT, FORWARD, и OUTPUT.

Цепочки с одинаковым названием, но в разных таблицах независимы друг от друга. Например, raw PREROUTING и mangle PREROUTING обычно содержат разный набор правил: пакеты сначала проходят через цепочку raw PREROUTING, а потом через mangle PREROUTING.

Также в фаерволе есть специальный модуль определения состояний пакетов ―conntrack. Состояния могут быть следующих видов:

  • NEW. Новое подключение, соединение получает это состояние, если обнаружен первый пакет в соединении;

  • ESTABLISHED. Уже состоявшееся подключение. Соединение получает это состояние, если пакет уже не первый. Очень удобно использовать для разрешения ответного трафика;

  • RELATED. Самое «хитрое» состояние соединения. Соединение получает его, только если само было инициировано из другого соединения. Типичный пример ― работа FTP-сервера, в котором канал передачи данных поднимается отдельно от канала приема команд;

  • INVALID. Состояние, когда пакет не может быть идентифицирован. Обычно к таким пакетам применяют действие DROP.

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 4
Путь проверки пакета в системе netfilter.

Для управления фаерволом чаще всего используется утилита iptables. Материала по ней достаточно, поэтому ограничусь общей рекомендацией ― блокируем все, что не разрешено. А что разрешено ― максимально ограничиваем.

Например, если доступ по SSH к серверу необходим только с определенных внешних адресов ― разрешите доступ только с них.

Но с iptables работать не всегда удобно, потому что требуется глубокое понимание пути прохождения пакетов. В качестве альтернативы часто используются другие утилиты, вроде ufw в системах Ubuntu.

Например, для предоставления доступа по ssh с помощью ufw достаточно выполнить команду:

ufw allow from 1.2.3.4 to any port 22

Тоже самое с помощью iptables выглядело бы более громоздко. Разрешим входящий трафик:

iptables -A INPUT -p tcp -s 1.2.3.4 --dport 22 -j ACCEPT

Затем разрешим ответный трафик:

iptables -A OUTPUT -p tcp --sport 22 -d 1.2.3.4 -j ACCEPT

Надо сказать, что чаще вместо того чтобы делать два явных правила для входящего и ответного трафика, просто разрешают трафик установленных соединений (ESTABLISHED) и связанных с установленными (RELATED). Для этого достаточно разрешить все подключения ESTABLISHED и RELATED следующими командами:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

В современных RPM-дистрибутивах вроде CentOS, Fedora и Red Hat в качестве замены iptables используют демона firewalld. От привычного механизма он отличен тем, что может применять правила на ходу без перезагрузки списка, а также работой с зонами ― уровнями доверия к сетевым подключениям. Немного напоминает встроенный фаервол Windows. Правда, использовать его после iptables немного непривычно, и часто системные администраторы предпочитают вернуть сложный, но привычный iptables.

В связке с фаерволом тесно работает и такой механизм как fail2ban, который делает следующее:

  • мониторит лог какого-либо сервиса, например ssh или ftp;

  • если слишком много подключений с одного IP-адреса с неверными логинами и паролями ― блокируем этот IP с помощью фаервола на некоторое время. Вдруг это брутфорс.

Подробнее с настройкой fail2ban можно ознакомиться в официальной Wiki.

АНБ на страже

SELinux ― дополнительный механизм принудительной системы контроля доступа. В отличие от классической избирательной, доступ основан на специальных политиках, а не ACL.

Минусы системы доступа на базе ACL:

  • пользователь сервера может предоставить доступ к своим файлам ― например, к закрытым ключам;

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

Устранить эти недостатки может SELinux, созданный АНБ (Агентство Национальной Безопасности США) и Red Hat еще в 1998 году. В ядре Linux-систем эта технология присутствует уже давно. Тем не менее в некоторых инструкциях до сих пор часто встречается рекомендация ее отключить, что не всегда справедливо. Подробнее про SELinux можно почитать в профильной статье на Хабре, поэтому ограничусь небольшим ликбезом.

У SELinux есть три режима работы:

  • enforcing. Режим работы по-умолчанию, все неразрешенные действия блокируются;

  • permissive. Все неразрешенные действия выполняются, но записываются в журнал;

  • disabled. SELinux отключен.

Узнать текущий режим работы можно командой getenforce, переключиться между режимами enforcing и permissive можно командой setenforce. Выключение же SELinux требует перезагрузки системы.

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

ls -Z

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 5
Смотрим маркировку свежесозданного файла.

В качестве примера настройки я разберу ситуацию, когда мы хотим разместить сайт в папке не по умолчанию и «повесить» веб-сервер на другой порт. Одной смены значений в конфигурационном файле httpd.conf будет недостаточно, необходимо сказать SELinux, что веб-серверу следует предоставить доступ к папке и к порту. Для этого необходимо:

  • установить пакет администрирования policycoreutils-python;

  • сказать системе о маркировке папки командами:

    semanage fcontext -a -t httpd_sys_content_t "/path/to/www(/.*)?"
    semanage fcontext -a -t httpd_sys_rw_content_t "/path/to/www(/.*)?"

  • восстановить маркировки командой:

    restorecon -R /path/to/www

  • предоставить доступ к порту:
    semanage port -a -t http_port_t -p tcp 81

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

SELinux как решение не уникален. Второй по популярности механизм защиты ― это AppArmor. Его разработку изначально курировала Novell, но после инструмент забросили как бесперспективный. Однако теперь над AppArmor работает Canonical, и продукт тесно связан с системой Ubuntu. Что касается отличий, то AppArmor удобнее SELinux благодаря множеству готовых политик.

Есть и механизм обучения, при котором действия пользователей записываются в журнал, но не блокируются ― так можно запустить новую защиту в качестве «пилота» и сразу устранить огрехи. Если в SELinux этот режим включается для всей системы, то с AppArmor его можно активировать для конкретного приложения. Пример такого назначения:

aa-complain /path/to/bin

Ключевое отличие AppArmor от SELinux заключается в том, что AppArmor привязывает политику к пути, а SELinux опирается на дескриптор файла. Если заблокировать исполнение файла и потом переместить его, то AppArmor позволит файлу запуститься, а SELinux ― нет.

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

Если описать отличия коротко, то разработчики SELinux делали упор не на простоту использования, а именно на безопасность. С AppArmor все обстоит с точностью до наоборот. Почитать об AppArmor подробнее можно в документации от производителя, либо в библиотеке Ubuntu.

Увы, не могу дать однозначный совет, что вам выбрать, потому что это вопрос приоритетов и предпочтений по дистрибутиву ОС. Поклонники Centos и Red Hat чаще выбирают SELinux, а любители Ubuntu ― AppArmor.

Кстати, напишете в комментариях, какой механизм предпочитаете вы?

Набор отмычек на всякий случай

В этом разделе я расскажу про несколько полезных, но не must-have механизмов для защиты сервера.

Запрет подключений root к терминалу

В системах GNULinux можно ограничить список терминалов, куда может подключаться пользователь root. Сделать это можно путем модификации файла /etc/securetty. Если файл пустой, то root не сможет напрямую подключаться вовсе, и для получения полных прав понадобится su или sudo.

Политика паролей

Также может быть полезно задать срок действия пароля следующей командой:

chage -M 20 username

Где 20 ― это срок действия пароля в днях. Другим вариантом будет изменение общей политики паролей в файле /etc/login.defs. Допустим, мы хотим, чтобы пароль нужно было менять каждые 20 дней, и чтобы пользователь за 5 дней получал напоминание об этом. Тогда содержимое файла будет следующим:

PASS_MAX_DAYS 20 

PASS_MIN_DAYS 0

PASS_WARN_AGE 5

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

password required pam_cracklib.so minlen=8 lcredit=1 ucredit=1 dcredit=1 

в файл /etc/pam.d/system-auth.

Уведомления о случаях повышения прав

Еще одна нужная опция ― уведомление о каждом вводе sudo для контроля доступа к правам суперпользователя. Для этого достаточно добавить в файл /etc/sudoers следующие строки:

mailto [admin@domain.com](mailto:admin@domain.com)

mail_always on

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

Деактивация компиляторов

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

В качестве примера под спойлером отключим доступ к gcc.

Для начала посмотрим список исполняемых файлов командой:

rpm -q --filesbypkg gcc | grep 'bin'

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 6
Исполняемые файлы gcc.

Теперь будет удобно создать отдельную группу командой:

groupadd compilerGroup

Затем сменить группу-владельца для нужных файлов:

chown root:compilerGroup /usr/bin/gcc

И задать права доступа, запрещающие доступ к файлам всем прочим:

chmod 0750 /usr/bin/gcc

Иммунитет для файлов конфигураций

Хороший способ защитить системные файлы и конфигурации даже от суперпользователя ― это атрибут иммуности. Для его применения используется команда chattr +i filename.

Базовая фортификация Linux: выбираем ежи и учимся рыть траншеи - 7
Даже root не может удалить иммунный файл.

Для снятия этого атрибута достаточно выполнить команду chattr -i filename.

Я думаю у каждого администратора есть еще свои best-practices по безопасности серверов. Предлагаю поделиться ими с коллегами в комментариях.

Автор: Сервер Молл

Источник

Поделиться

* - обязательные к заполнению поля