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

Информация об авторе

www.tauceti.blog

Установить
ansible-galaxy install githubixx/ansible-role-harden-linux
Лицензия
gpl-3.0
Загрузки
2916
Владелец
Senior System Engineer - Python, Go, Cloud, Kubernetes, Commodore, Retro, 80's ;-)