Первый запуск Lynis на свежем VPS обычно даёт что-то около 60 и длинный список рекомендаций, в котором непонятно, за что хвататься. Хорошая новость: до 80–85 доезжают за один вечер, и большая часть шагов — не косметика, а действительно нужные вещи. Плохая: последние пятнадцать пунктов на арендованной виртуалке не берутся вовсе, и гнаться за ними не надо.
Что показывает индекс и чего не показывает
Hardening index — это соотношение пройденных проверок к общему их числу с весами, а не процент защищённости. Lynis выполняет порядка трёхсот тестов и по итогам выдаёт два разных списка: warnings — то, что похоже на реальную проблему, и suggestions — то, что можно улучшить. Начинать всегда с warnings, их обычно единицы.
Ста баллов не бывает: часть рекомендаций требует решений, принимаемых при установке системы (отдельные разделы под /home, /tmp и /var), часть — доступа к загрузчику, которого на VPS нет, часть противоречит друг другу. И сравнивать свой индекс с чужим бесполезно: Lynis снимает баллы за то, что на машине работает. Каждая запущенная служба — это ещё один открытый порт, свой конфиг и десяток новых рекомендаций, поэтому высокие значения чаще встречаются там, где кроме SSH ничего не запущено. Для рабочего сервера с сайтом, базой и почтой 85 — хороший результат.
Запускать от root
sudo lynis audit system
Без sudo Lynis пропустит все тесты, которым нужны системные файлы, и покажет заниженный индекс — не потому что сервер плох, а потому что проверок не было видно. Отчёт кладётся в /var/log/lynis-report.dat, читаемый лог — в /var/log/lynis.log.
Каждая строка вывода начинается с идентификатора теста вида SSH-7408 или KRNL-6000. По этому идентификатору ищется и объяснение, и способ отключения — запомните его форму, дальше всё крутится вокруг неё.
Что даёт прирост
SSH (SSH-7408). Самый весомый блок: один тест проверяет сразу десяток параметров. Не правьте sshd_config целиком, положите отдельный файл — так апдейт пакета ничего не затрёт:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
MaxSessions 2
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
LogLevel VERBOSE
TCPKeepAlive no
EOF
sudo sshd -t && sudo systemctl reload ssh
sshd -t перед перезагрузкой службы обязателен: ошибка в конфиге при живой сессии оставит вас снаружи. И прежде чем ставить PasswordAuthentication no, убедитесь, что ключ действительно работает — из второго открытого терминала.
Параметры ядра (KRNL-6000). Тест проверяет два десятка значений sysctl. Файл под них:
sudo tee /etc/sysctl.d/99-hardening.conf <<'EOF'
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.sysrq = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.log_martians = 1
EOF
sudo sysctl --system
Отсутствующие инструменты. Немалая часть suggestions — это просто «поставьте то, чего нет»: auditd (журнал системных событий), aide (контроль целостности файлов), debsums (целостность пакетов), unattended-upgrades (автообновления безопасности), sysstat и acct (учёт процессов), антивирусный сканер. Каждый закрывает одну-две рекомендации, но ставить их стоит не ради баллов, а потому что без них вы после инцидента ничего не восстановите.
Мелочи с хорошим соотношением усилий. umask 027 в /etc/login.defs; сроки жизни паролей там же; баннеры /etc/issue и /etc/issue.net; компиляторы, доступные только root (chmod 700 /usr/bin/gcc). Про баннеры честно скажем: на защиту они не влияют никак, это юридическая формальность, но балл дают.
Одна ловушка с login.defs
Правка umask через sed с заменой строки нередко оставляет в файле несколько строк UMASK сразу. Lynis в этом случае значение не засчитывает, и тест AUTH-9328 остаётся красным, хотя настройка на вид сделана. Проверяйте после правки:
grep -c '^UMASK' /etc/login.defs
Должна быть ровно единица. То же касается любых других параметров этого файла.
Ложные срабатывания и как их глушить правильно
Некоторые предупреждения к вашему серверу не относятся вовсе. Живой пример: на VPS одного крупного хостера тест PKGS-7388 сообщает, что репозиторий безопасности не найден, — просто потому, что репозитории описаны в формате deb822 со ссылкой на файл зеркал, а Lynis ищет привычную строку. Обновления безопасности при этом приходят исправно.
Глушить такое надо не удалением строк из отчёта, а профилем. Файлы профилей — с расширением .prf (не .prof, на этом легко потерять полчаса), свои правила пишутся в /etc/lynis/custom.prf:
skip-test=PKGS-7388
skip-test=KRNL-5788
Правило одно: рядом с каждой строкой должен быть комментарий, почему тест пропущен. Через полгода вы не вспомните, отключён он потому, что не применим, или потому, что чинить было лень, — а разница между этими случаями и есть вся разница.
Чего не делать
Не гнаться за цифрой. Индекс легко накрутить, отключив неудобные тесты, и это единственный способ подняться выше определённого уровня — только защищённее сервер от этого не станет. Полезно другое: зафиксировать своё значение и следить за изменениями. Индекс, упавший после обновления или чужой правки конфига, — гораздо более ценный сигнал, чем его абсолютная величина.
Именно поэтому Lynis имеет смысл запускать не разово, а по расписанию и складывать отчёты, чтобы было с чем сравнивать. Как это выглядит собранным на одну страницу — на демо ниже: индекс, список warnings с идентификаторами тестов и то, что изменилось со времени прошлого прогона.