harden_linux
ansible-role-harden-linux
Эта роль Ansible была создана в основном для моей серии блогов Kubernetes the not so hard way with Ansible - Harden the instances. Но ее также можно использовать отдельно для усиления безопасности Linux. Она имеет следующие функции (некоторые из них являются необязательными):
- Добавить обычного/развертывающего пользователя для администрирования (например, для Ansible или входа через SSH)
- Настроить интервалы обновления APT
- Установить брандмауэр
UFW
и по умолчанию разрешить только доступ по SSH (добавьте больше правил/разрешенных сетей, если хотите) - Настроить параметры sysctl, связанные с безопасностью
- Настроить параметры
sshd
, например, отключить аутентификацию паролем sshd, отключить вход root через sshd и отключить sshd PermitTunnel - Установить
sshguard
и настроить белый список - Изменить пароль root
- Установить/настроить
Синхронизацию времени сети
(NTP), например,openntpd
/ntp
/systemd-timesyncd
- Изменить конфигурацию
systemd-resolved
Версии
Я помечаю каждую версию и стараюсь придерживаться семантического версионирования. Если вы хотите использовать роль, я рекомендую проверить последнюю метку. Главная ветка по сути является веткой разработки, в то время как метки отмечают стабильные релизы. Но в общем, я стараюсь поддерживать главную ветку в хорошем состоянии тоже.
Журнал изменений
История изменений:
Смотрите полный CHANGELOG.md
Недавние изменения:
v8.2.0
- ФУНКЦИЯ
- поддержка Ubuntu 24.04
v8.1.0
ДРУГОЕ
- обновлены комментарии о использовании
mkpasswd
вместоansible
для создания зашифрованного пароля - Ubuntu: добавлена задача автозагрузки
- обновлен рабочий процесс Github
- обновлены комментарии о использовании
MOLECULE
- использовать
alvistack
вместоgeneric
Vagrant образы - использовать разные IP-адреса
- использовать
v8.0.0
BREAKING/FEATURE
- введены переменные
harden_linux_deploy_group
иharden_linux_deploy_group_gid
. Обе являются необязательными. Но как минимумharden_linux_deploy_group
должна быть указана, если также установленаharden_linux_deploy_user
. Еслиharden_linux_deploy_group
установлена вroot
, ничего не будет изменено. - если
harden_linux_deploy_user
установлена вroot
, ничего не будет изменено. harden_linux_deploy_user
теперь необязательна. Если не указана, пользователь не будет настроен. Также все переменные, начинающиеся сharden_linux_deploy_user_
, используются только если указанаharden_linux_deploy_user
. Дополнительно была добавлена переменнаяharden_linux_deploy_user_home
.harden_linux_deploy_user_shell
,harden_linux_deploy_user_home
,harden_linux_deploy_user_uid
иharden_linux_deploy_user_password
теперь необязательны. Директория $HOME пользователяharden_linux_deploy_user
создается только если установленаharden_linux_deploy_user_home
.
- введены переменные
MOLECULE
- обновлена тестовая схема, чтобы отразить изменения пользователя/группы развертывания
Установка
Скачайте напрямую с Github (Перейдите в каталог роли Ansible перед клонированием. Вы можете определить путь к роли, используя команду
ansible-config dump | grep DEFAULT_ROLES_PATH
):git clone https://github.com/githubixx/ansible-role-harden-linux.git githubixx.harden_linux
Через команду
ansible-galaxy
и загрузить напрямую из Ansible Galaxy:ansible-galaxy install role githubixx.harden_linux
Создайте файл
requirements.yml
со следующим содержимым (это загрузит роль с Github) и установите с помощьюansible-galaxy role install -r requirements.yml
(изменитеверсию
, если это необходимо):
---
roles:
- name: githubixx.harden_linux
src: https://github.com/githubixx/ansible-role-harden-linux.git
version: v8.1.0
Переменные роли
Следующие переменные не имеют значений по умолчанию. Вам нужно указать их либо в файле в директориях group_vars
или host_vars
. Например, если эти настройки должны использоваться только для одного конкретного хоста, создайте файл для этого хоста, названный как FQDN этого хоста (например, host_vars/your-server.example.tld
) и поместите переменные с правильными значениями там. Если вы хотите применить эти переменные к группе хостов, создайте файл group_vars/your-group.yml
. Замените your-group
на название группы хостов, которую вы создали в файле hosts
Ansible (не путайте с /etc/hosts...).
Если вы хотите установить или изменить пароль пользователя root
, установите переменную harden_linux_root_password
. Это необязательно. Она ожидает зашифрованный пароль. Ansible не зашифрует пароль за вас. Как создать зашифрованный пароль, описано в Ansible FAQs. В Linux следующая команда, вероятно, является самой надежной:
mkpasswd --method=sha-512
Чтобы установить пользователя, который может выполнять команды с sudo
без пароля, установите следующие переменные:
harden_linux_deploy_user: "имя_пользователя"
harden_linux_deploy_user_password: "пароль"
harden_linux_deploy_user_home: "/home/пользователь"
harden_linux_deploy_user_uid: "9999"
harden_linux_deploy_user_gid: "9999"
harden_linux_deploy_user_shell: "/bin/bash"
harden_linux_deploy_user
указывает пользователя, которого мы хотим использовать для входа на удаленном хосте. Как уже упоминалось, роль harden_linux
отключит вход пользователя root через SSH по обоснованной причине. Следовательно, нужен другой пользователь. Этот пользователь получит разрешение "sudo", которое необходимо для работы Ansible (и/или вас, конечно).
В harden_linux_deploy_user_password
хранится зашифрованный пароль пользователя. То же самое относится к harden_linux_root_password
относительно того, как создать зашифрованный пароль.
Домашняя директория пользователя указывается в harden_linux_root_password
. Для UID и GID установите harden_linux_deploy_user_uid
и harden_linux_deploy_user_gid
. Примечание: Если пользователь уже существует, но имеет другую домашнюю директорию, UID и/или GID, он будет изменен в соответствии с указанными настройками! Это также касается harden_linux_deploy_user_shell
, который указывает оболочку, которую пользователь должен использовать после входа, например.
harden_linux_deploy_user_public_keys
указывает список файлов с общими SSH-ключами, которые вы хотите добавить в $HOME/.ssh/authorized_keys
развертывающего пользователя на удаленном хосте. Если вы укажете, например, /home/deploy/.ssh/id_rsa.pub
как значение здесь, содержимое этого локального файла (находящегося на узле контроллера Ansible) будет добавлено в $HOME/.ssh/authorized_keys
развертывающего пользователя на удаленном хосте.
harden_linux_optional_packages
(до версии v6.0.0
этой роли эта переменная называлась harden_linux_required_packages
) указывает дополнительные/необязательные пакеты для установки на удаленном хосте. По умолчанию эта переменная не указана. Например:
harden_linux_optional_packages:
- vim
В отличие от предыдущей переменной, harden_linux_absent_packages
удалит пакеты ОС на удаленном хосте. По умолчанию эта переменная не указана. Например:
harden_linux_absent_packages:
- vim
Следующие переменные имеют значения по умолчанию. Поэтому вам нужно изменить их только в случае необходимости. Роль по умолчанию меняет некоторые параметры sshd
:
harden_linux_sshd_settings:
"^PasswordAuthentication": "PasswordAuthentication no" # Отключить аутентификацию по паролю
"^PermitRootLogin": "PermitRootLogin no" # Отключить вход root по SSH
"^PermitTunnel": "PermitTunnel no" # Отключить туннелирование
"^Port ": "Port 22" # Установить порт sshd
Лично я всегда меняю порт SSH по умолчанию, так как на этот порт происходит много атак методом грубой силы (но, конечно, сканер портов все равно сможет быстро это выяснить). Так что, если вы хотите изменить настройку порта, вы можете сделать это, например:
harden_linux_sshd_settings_user:
"^Port ": "Port 22222"
(Обратите внимание на пробел после ^Port
!). Плейбук объединит harden_linux_sshd_settings
и harden_linux_sshd_settings_user
, при этом параметры в harden_linux_sshd_settings_user
будут иметь приоритет, что означает, что они переопределят установку ^Port
в harden_linux_sshd_settings
. Как вы могли заметить, все ключи в harden_linux_sshd_settings
и harden_linux_sshd_settings_user
начинаются с ^
. Это потому, что это регулярное выражение (regex). Одна из задач плейбука будет искать строку в /etc/ssh/sshd_config
, например ^Port
(где ^
означает "строка, начинающаяся с ...") и заменит эту строку (если найдена) на, например, Port 22222
. Этот способ делает плейбук очень гибким для настройки параметров в sshd_config
(вы можете заменить практически любое значение). Вы также увидите этот шаблон и для других задач. Так что то, что здесь упомянуто, верно и в таких случаях.
Далее идут некоторые настройки по умолчанию для брандмауэра/iptables. Правила и настройки брандмауэра/iptables управляются UFW:
harden_linux_ufw_defaults:
"^IPV6": 'IPV6=yes'
"^DEFAULT_INPUT_POLICY": 'DEFAULT_INPUT_POLICY="DROP"'
"^DEFAULT_OUTPUT_POLICY": 'DEFAULT_OUTPUT_POLICY="ACCEPT"'
"^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="DROP"'
"^DEFAULT_APPLICATION_POLICY": 'DEFAULT_APPLICATION_POLICY="SKIP"'
"^MANAGE_BUILTINS": 'MANAGE_BUILTINS=no'
"^IPT_SYSCTL": 'IPT_SYSCTL=/etc/ufw/sysctl.conf'
"^IPT_MODULES": 'IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns"'
Эти настройки в основном меняют значения в /etc/defaults/ufw
. Для переопределения одной или нескольких настроек по умолчанию вы можете сделать это, указав тот же ключ (который является регулярным выражением), как выше, например, ^DEFAULT_FORWARD_POLICY
, и просто назначив ему новое значение:
harden_linux_ufw_defaults_user:
"^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="ACCEPT"'
Как уже упоминалось, этот плейбук также объединит harden_linux_ufw_defaults
и harden_linux_ufw_defaults_user
, при этом параметры в harden_linux_ufw_defaults_user
будут иметь приоритет.
Кроме того, мы можем указать некоторые правила брандмауэра с harden_linux_ufw_rules
. По умолчанию разрешен трафик SSH на порту 22
, который использует протокол tcp
:
harden_linux_ufw_rules:
- rule: "allow"
to_port: "22"
protocol: "tcp"
Следующие параметры доступны с значениями по умолчанию (если имеются):
rule (нет значения по умолчанию)
interface (по умолчанию '')
direction (по умолчанию 'in')
from_ip (по умолчанию 'any')
to_ip (по умолчанию 'any')
from_port (по умолчанию '')
to_port (по умолчанию '')
protocol (по умолчанию 'any')
log (по умолчанию 'false')
delete (по умолчанию 'false')
Правило может иметь значения allow
, deny
, limit
и reject
. Интерфейс определяет интерфейс для правила. Направление (входящее или исходящее), используемое для интерфейса, зависит от значения направления. from_ip указывает адрес источника, а from_port - порт источника. to_ip указывает адрес назначения, а to_port - порт назначения. Протокол по умолчанию 'any'. Возможные значения: tcp
, udp
, ipv6
, esp
, ah
, gre
и igmp
. log может быть false
(по умолчанию) или true
и указывает, должны ли новые подключения, совпадающие с этим правилом, быть записаны. Удаление определяет, должно ли правило быть удалено. Это важно, если предыдущее добавленное правило должно быть удалено. Просто удалить правило из harden_linux_ufw_rules
недостаточно! Вы должны использовать delete
, чтобы удалить это правило.
Вы также можете разрешить хостам общаться по определенным сетям (без ограничений по портам), например:
harden_linux_ufw_allow_networks:
- "10.3.0.0/24"
- "10.200.0.0/16"
Кроме того, роль harden_linux
изменяет некоторые системные переменные (sysctl.conf / файловая система proc). Эти настройки являются рекомендациями от Google, которые они используют для своих образов ОС Google Compute Cloud (см. Google Cloud - Требования для создания пользовательских изображений и Настройка вашего импортированного образа для Compute Engine). Это настройки по умолчанию (если вас устраивают эти настройки, вам не нужно ничего делать, но я рекомендую проверить, работают ли они для вашей конфигурации):
harden_linux_sysctl_settings:
"net.ipv4.tcp_syncookies": 1 # Включить защиту от син-флудов
"net.ipv4.conf.all.accept_source_route": 0 # Игнорировать пакеты с маршрутом источника
"net.ipv6.conf.all.accept_source_route": 0 # IPv6 - Игнорировать ICMP перенаправления
"net.ipv4.conf.default.accept_source_route": 0 # Игнорировать пакеты с маршрутом источника
"net.ipv6.conf.default.accept_source_route": 0 # IPv6 - Игнорировать пакеты с маршрутом источника
"net.ipv4.conf.all.accept_redirects": 0 # Игнорировать ICMP перенаправления
"net.ipv6.conf.all.accept_redirects": 0 # IPv6 - Игнорировать ICMP перенаправления
"net.ipv4.conf.default.accept_redirects": 0 # Игнорировать ICMP перенаправления
"net.ipv6.conf.default.accept_redirects": 0 # IPv6 - Игнорировать ICMP перенаправления
"net.ipv4.conf.all.secure_redirects": 1 # Игнорировать ICMP перенаправления от не-GW хостов
"net.ipv4.conf.default.secure_redirects": 1 # Игнорировать ICMP перенаправления от не-GW хостов
"net.ipv4.ip_forward": 0 # Не разрешать трафик между сетями или действовать как маршрутизатор
"net.ipv6.conf.all.forwarding": 0 # IPv6 - Не разрешать трафик между сетями или действовать как маршрутизатор
"net.ipv4.conf.all.send_redirects": 0 # Не разрешать трафик между сетями или действовать как маршрутизатор
"net.ipv4.conf.default.send_redirects": 0 # Не разрешать трафик между сетями или действовать как маршрутизатор
"net.ipv4.conf.all.rp_filter": 1 # Фильтрация обратного пути - защита от подделки IP
"net.ipv4.conf.default.rp_filter": 1 # Фильтрация обратного пути - защита от подделки IP
"net.ipv4.icmp_echo_ignore_broadcasts": 1 # Игнорировать широковещательные ICMP-запросы, чтобы избежать участия в атаках Smurf
"net.ipv4.icmp_ignore_bogus_error_responses": 1 # Игнорировать плохие ICMP-ошибки
"net.ipv4.icmp_echo_ignore_all": 0 # Игнорировать плохие ICMP-ошибки
"net.ipv4.conf.all.log_martians": 1 # Логировать пакеты с подделкой источника, маршрутом и перенаправлением
"net.ipv4.conf.default.log_martians": 1 # Логировать пакеты с подделкой источника, маршрутом и перенаправлением
"net.ipv4.tcp_rfc1337": 1 # Реализовать исправление RFC 1337
"kernel.randomize_va_space": 2 # Случайным образом менять адреса базиса mmap, кучи, стека и страницы VDSO
"fs.protected_hardlinks": 1 # Защита от гонки ToCToU
"fs.protected_symlinks": 1 # Защита от гонки ToCToU
"kernel.kptr_restrict": 1 # Усложнение нахождения адресов ядра
"kernel.perf_event_paranoid": 2 # Установить доступ к perf только для root
Вы можете переопределить каждую отдельную настройку, например, создав переменную с названием harden_linux_sysctl_settings_user
:
harden_linux_sysctl_settings_user:
"net.ipv4.ip_forward": 1
"net.ipv6.conf.default.forwarding": 1
"net.ipv6.conf.all.forwarding": 1
Одна из задач плейбука объединит harden_linux_sysctl_settings
и harden_linux_sysctl_settings_user
, при этом настройки harden_linux_sysctl_settings_user
будут иметь приоритет. Посмотрите на файл defaults/main.yml
роли для получения дополнительной информации о настройках.
Если вы хотите включить ведение журнала UFW, установите:
harden_linux_ufw_logging: 'on'
Возможные значения: on
, off
, low
, medium
, high
и full
.
Далее идут настройки "sshguard". "sshguard" защищает от атак методом грубой силы против SSH. Чтобы избежать блокировки вашего доступа на некоторое время, вы можете добавить IP-адреса или диапазоны IP в белый список. По умолчанию это в основном только "localhost":
harden_linux_sshguard_whitelist:
- "127.0.0.0/8"
- "::1/128"
Также могут быть установлены/настроены пакеты NTP. Это необязательно. По умолчанию я рекомендую использовать systemd-timesyncd
. Вы также можете использовать пакет ntp
. Но openntpd
и systemd-timesyncd
имеют преимущество, так как по умолчанию не слушают никаких портов. Если вы просто хотите поддерживать время на хостах, этого будет вполне достаточно. Наличие одинакового времени на всех ваших хостах критично для некоторых сервисов. Например, для проверки сертификатов, для etcd, баз данных, криптографии и так далее.
Допустимые параметры для harden_linux_ntp
:
- openntpd
- ntp
- systemd-timesyncd
openntpd
и systemd-timesyncd
имеют преимущество, так как по умолчанию не слушают никаких портов, как уже упоминалось. Если вы просто хотите поддерживать время на хостах, один из этих двух должен справиться с задачей. systemd-timesyncd
уже установлен, если дистрибутив использует systemd
(что по сути верно для большинства современных дистрибутивов Linux). Поэтому в этом случае не требуется никаких дополнительных пакетов. Чтобы включить openntpd
, установите harden_linux_ntp
соответствующим образом, например:
harden_linux_ntp: "openntpd"
Настройки для openntpd
, ntpd
или systemd-timesyncd
(см. следующий параграф). Для получения дополнительных параметров см. страницу man: man 5 ntpd.conf
для ntp
и openntpd
, а также man 5 timesyncd.conf
для systemd-timesyncd
.
"Ключ" здесь — это регулярное выражение настройки, которую вы хотите заменить, а значение - это имя настройки + значение настройки. Например, мы хотим заменить строку servers 0.debian.pool.ntp.org
на servers 1.debian.pool.ntp.org
. Регулярное выражение (ключ) будет ^servers 0
, что означает:
"найдите строку в конфигурационном файле, которая начинается с server 0
, и замените всю строку на servers 1.debian.pool.ntp.org
". Таким образом, можно заменить каждую настройку в конфигурационном файле. Некоторые примеры:
harden_linux_ntp_settings:
"^servers 0": "servers 0.debian.pool.ntp.org"
"^servers 1": "servers 1.debian.pool.ntp.org"
"^servers 2": "servers 2.debian.pool.ntp.org"
"^servers 3": "servers 3.debian.pool.ntp.org"
Пожалуйста, обратите внимание: systemd-timesyncd
поставляется с разумными значениями по умолчанию на этапе компиляции. Поэтому обычно нет необходимости изменять конфигурацию (даже NTP-серверов). Таким образом, следующие строки только примеры, но вам действительно не нужно указывать harden_linux_ntp_settings
для systemd-timesyncd
.
Для systemd-timesyncd
конфигурационный файл немного отличается. В этом случае будет создана конфигурация drop-in для /etc/systemd/timesyncd.conf
в /etc/systemd/timesyncd.conf.d/
.
Пример для Debian:
harden_linux_ntp_settings:
"^#NTP=": "NTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org"
Для Ubuntu:
harden_linux_ntp_settings:
"^#NTP=": "NTP=ntp.ubuntu.com"
Для Archlinux:
harden_linux_ntp_settings:
"^#NTP=": "NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org"
С помощью harden_linux_files_to_delete
можно указать список файлов, которые должны отсутствовать на целевом хосте, например:
harden_linux_files_to_delete:
- "/root/.pw"
Если для разрешения DNS используется systemd-resolved
, его поведение можно настроить с помощью harden_linux_systemd_resolved_settings
. По умолчанию эта переменная не указывается. Будет создана конфигурация drop-in в /etc/systemd/resolved.conf.d/99-override.conf
, и указанные настройки будут добавлены туда.
Примечание: Если параметр в /etc/systemd/resolved.conf
уже установлен (например, DNS=8.8.8.8
), то установление DNS=9.9.9.9
ниже будет добавлено. Это означает, что конечная установка будет DNS=8.8.8.8 9.9.9.9
. Если вы этого не хотите, вам нужно сначала "снять" значение, а затем добавить желаемое. Например:
harden_linux_systemd_resolved_settings:
- DNS=
- DNS=9.9.9.9
Пока серверы DNS Google (8.8.8.8
, 8.8.4.4
) предлагают быстрые DNS-запросы, это, конечно, еще одна возможность, что Google может шпионить за вами. Так что использование других серверов DNS должно быть хотя бы на размышления. Но есть еще один момент — это шифрование DNS-запросов. Один из способов, который поддерживает systemd-resolved
, — это DNSOverTLS
. Quad9 (9.9.9.9/149.112.112.112) и Cloudflare (1.1.1.1/1.0.0.1) поддерживают DNSOverTLS
.
Таким образом, следующие настройки systemd-resolved
настраивают DNS Quad9 и Cloudflare для IPv4 и IPv6. Параметр DNSOverTLS=opportunistic
использует DNSOverTLS
, если DNS-сервер его поддерживает, и возвращается к стандартному нешифрованному DNS, если не поддерживается (также см. resolved.conf.5):
harden_linux_systemd_resolved_settings:
- DNS=
- DNS=9.9.9.9 1.1.1.1 2606:4700:4700::1111 2620:fe::fe
- FallbackDNS=
- FallbackDNS=149.112.112.112 1.0.0.1 2620:fe::9 2606:4700:4700::1001
- DNSOverTLS=
- DNSOverTLS=opportunistic
Также можно повлиять на кэширование менеджера пакетов. Например, для Ubuntu:
# Установите в "false", если кэш пакетов не должен обновляться
harden_linux_ubuntu_update_cache: true
# Установите время действия кэша пакетов
harden_linux_ubuntu_cache_valid_time: 3600
Для Archlinux:
# Установите в "false", если кэш пакетов не должен обновляться
harden_linux_archlinux_update_cache: true
Пример плейбука
Если вы установили роль через ansible-galaxy install githubixx.harden_linux
, тогда включите роль в свой плейбук, как в этом примере:
- hosts: webservers
roles:
- githubixx.harden_linux
Тестирование
Эта роль имеет небольшую тестовую конфигурацию, которая создается с помощью Molecule, libvirt (vagrant-libvirt) и QEMU/KVM. Пожалуйста, посмотрите мой пост в блоге Testing Ansible roles with Molecule, libvirt (vagrant-libvirt) and QEMU/KVM, чтобы узнать, как настроить. Конфигурация теста здесь.
После этого можно выполнить molecule:
molecule converge
Это создаст несколько виртуальных машин (VM) с разными поддерживаемыми операционными системами Linux и настроит роль harden_linux
соответственно. Также включен небольшой этап верификации:
molecule verify
Чтобы очистить, выполните
molecule destroy
Лицензия
GNU GENERAL PUBLIC LICENSE Version 3
Информация об авторе
Ansible role for hardening Linux
ansible-galaxy install githubixx/ansible-role-harden-linux