Библиотека — FreeBSD — безопасность: hardening, SSH, брутфорс-защита, аудит [X]
Шифр
freebsd-security-hardening
Разделы
freebsd security
Сверено
2 сентября — в этот день утверждения статьи сверялись с первоисточниками, а не правился текст
Объём
21 084 знака · 29 разделов · чтения около 20 минут

FreeBSD — безопасность: hardening, SSH, брутфорс-защита, аудит


Обзор

FreeBSD исторически проектировалась с акцентом на безопасность. Base system включает инструменты, которые в Linux требуют отдельных пакетов: встроенный аудит, MAC framework, securelevel, blocklistd, интегрированный OpenSSH с поддержкой blocklistd, файловые флаги immutable/append-only. Всё это — часть системы, а не надстройки.

Статья организована от практичного к продвинутому: сначала SSH и базовый hardening (то, что нужно сделать на каждом VPS в первый час), затем брутфорс-защита, firewall-аспекты безопасности, аудит и MAC framework. Многие темы пересекаются с предыдущими статьями (sysctl, pf, jails) — здесь они собраны в единую картину безопасности.

SSH: первая линия обороны

Конфигурация sshd

OpenSSH входит в base system FreeBSD. Конфигурация — /etc/ssh/sshd_config. Ключевые настройки для production:

# /etc/ssh/sshd_config

# Аутентификация
PermitRootLogin no                  # запретить прямой вход root
PubkeyAuthentication yes            # разрешить ключи
PasswordAuthentication no           # отключить пароли (после настройки ключей!)
KbdInteractiveAuthentication no     # отключить keyboard-interactive
PermitEmptyPasswords no

# Ограничение доступа
AllowUsers deployer admin           # только перечисленные пользователи
# или AllowGroups sshusers          # по группе

# Таймауты и лимиты
LoginGraceTime 30                   # секунд на аутентификацию (дефолт 120)
MaxAuthTries 3                      # попыток аутентификации
MaxSessions 5                       # сессий на соединение
ClientAliveInterval 300             # keepalive каждые 5 мин
ClientAliveCountMax 2               # 2 пропуска = разрыв

# Протокол
X11Forwarding no                    # если не нужен
AllowTcpForwarding no               # если не нужен проброс портов
AllowAgentForwarding no             # если не нужен
PrintMotd no

# Blocklistd интеграция (base system)
UseBlocklist yes

Порядок действий: сначала настроить ключи и проверить вход, потом отключать пароли. Потеря доступа при PasswordAuthentication no без рабочего ключа — классическая ошибка.

Ключи и Ed25519

# На клиенте — генерация ключа
ssh-keygen -t ed25519 -C "user@host"

# Копирование на сервер
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# На сервере — проверка прав
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Ed25519 предпочтительнее RSA: короче, быстрее, устойчивее к side-channel атакам. RSA-4096 — приемлемый fallback для совместимости со старыми клиентами.

doas vs sudo

FreeBSD base system не включает sudo (это сторонний пакет). Альтернатива из OpenBSD — doas(1), значительно проще и минималистичнее:

pkg install doas
# /usr/local/etc/doas.conf
permit persist :wheel           # группа wheel может выполнять команды от root
permit nopass deployer cmd service   # deployer может перезапускать сервисы без пароля

persist должен кэшировать аутентификацию, чтобы не вводить пароль на каждую команду, — но именно на FreeBSD порт security/doas этого не умеет: механизм опирается на ioctl TIOCCHKVERAUTH, которого в ядре FreeBSD нет, и пароль спрашивается каждый раз. Кому нужен работающий persist — ставит security/opendoas, форк OpenDoas с собственной реализацией timestamp-файлов. doas.conf — один файл с простым синтаксисом, в отличие от sudoers с его визивигами и потенциальными ошибками.

sudo тоже доступен (pkg install sudo), и для сложных сценариев с гранулярными правилами он мощнее. Для типичного VPS с 1-3 администраторами doas достаточен.

Базовый hardening: sysctl и rc.conf

Собираем в одном месте все security-relevant настройки из предыдущих статей.

/etc/sysctl.conf

# Видимость процессов: пользователи не видят чужие процессы
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.see_jail_proc=0

# Непривилегированные пользователи не могут читать dmesg и отлаживать процессы
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0

# ASLR — рандомизация адресного пространства
kern.elf64.aslr.enable=1
kern.elf64.aslr.pie_enable=1
kern.elf32.aslr.enable=1
kern.elf32.aslr.pie_enable=1

# Рандомизация PID
kern.randompid=1

# Отключить core dumps (могут содержать чувствительные данные)
kern.coredump=0

# Stack guard page
security.bsd.stack_guard_page=1

/etc/rc.conf

# Очистка /tmp при загрузке
clear_tmp_enable="YES"

# Отключить sendmail (если не нужен)
sendmail_enable="NONE"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

# Syslogd: не слушать сеть (если не syslog-сервер)
syslogd_flags="-ss"

# Включить PF
pf_enable="YES"
pflog_enable="YES"

/etc/ttys — запрет прямого root-входа на консоль

Заменить secure на insecure для всех терминалов:

ttyv0   "/usr/libexec/getty Pc"   xterm   on   insecure

После этого root не может войти напрямую через консоль — только через su/doas от обычного пользователя. Это создаёт audit trail: в логах видно, кто именно стал root.

Защита от брутфорса

Три подхода, от встроенного до стороннего, с разными trade-off'ами.

PF overload tables (встроенный)

PF имеет встроенный механизм автоматического блокирования по rate-limiting (описан в статье о сети):

table <bruteforce> persist
block quick from <bruteforce>

pass in on $ext_if proto tcp to port ssh \
    flags S/SA keep state \
    (max-src-conn 5, max-src-conn-rate 3/30, \
     overload <bruteforce> flush global)

Это работает на L4 — считает TCP-соединения, не заглядывая в протокол аутентификации. Достаточно для SSH, но не видит неудачные логины на уровне приложения. Нет экспоненциального backoff'а.

Для автоматической очистки таблицы от старых записей:

# /etc/crontab (очищать записи старше 24 часов)
0 * * * * root /sbin/pfctl -t bruteforce -T expire 86400

blocklistd (base system)

blocklistd(8) — демон из base system FreeBSD (портирован из NetBSD). Принципиально отличается от fail2ban/sshguard: вместо парсинга логов использует API (libblocklist), через который приложения напрямую сообщают о неудачных попытках аутентификации. FreeBSD-шный sshd уже поддерживает это API.

В FreeBSD 15.0 весь набор переименован вслед за upstream: blacklistd стал blocklistd, libblacklist — libblocklist, конфиг переехал в /etc/blocklistd.conf, переменная rc.conf — blocklistd_enable. Старые имена сохранены как алиасы и продолжают работать, печатая предупреждение; в 14.x актуальны ещё они. Переименовать нужно и файлы конфигурации, и якоря firewall.

# /etc/ssh/sshd_config
UseBlocklist yes

# /etc/rc.conf
blocklistd_enable="YES"

# /etc/blocklistd.conf
# adr/mask:port  type    proto   owner   name    nfail   duration
[local]
ssh             stream  *       *       *       3       24h
ftp             stream  *       *       *       3       24h
smtp            stream  *       *       *       3       24h
*               *       *       *       *       3       60

Конфигурация читается так: после 3 неудачных попыток (nfail) на порт ssh — заблокировать источник на 24 часа (последнее поле, duration). Правила демон создаёт сам, но выкладывает их в якорь: по умолчанию — в PF-anchor blocklistd, который должен быть объявлен в pf.conf (anchor "blocklistd/*" in on $ext_if), иначе блокировки никуда не попадут. Пятое поле правила позволяет задать своё имя якоря.

Преимущества перед fail2ban/sshguard: работает через API, а не парсит логи (не сломается при изменении формата логов); входит в base system (нет внешних зависимостей); интеграция с sshd на уровне кода.

Недостаток: работает только с приложениями, поддерживающими libblocklist API. На практике это прежде всего sshd; ftpd, второй классический потребитель API, из base удалён в 15.0 и живёт теперь в порту ftp/freebsd-ftpd. Для защиты nginx, postfix, dovecot — нужен sshguard или fail2ban.

sshguard (сторонний)

sshguard (security/sshguard) — лёгкий демон, парсящий логи и блокирующий атакующих через firewall backend. Поддерживает PF, IPFW, IPFILTER, а на Linux — iptables/nftables. Отдельных портов под каждый backend (sshguard-pf, sshguard-ipfilter) больше нет: остался один порт, а backend выбирается строкой BACKEND в конфиге.

pkg install sshguard
sysrc sshguard_enable="YES"

Читать логи sshguard умеет сам — через FILES или LOGREADER в конфиге. Старый рецепт с pipe в /etc/syslog.conf (auth.info;authpriv.info |exec /usr/local/sbin/sshguard) порт прямо называет нерекомендуемым и неподдерживаемым.

В PF добавить таблицу и правило:

table <sshguard> persist
block in quick on $ext_if proto tcp from <sshguard> to any port ssh

sshguard использует экспоненциальный backoff: первая блокировка — 120 сек, вторая — 240, третья — 480 и т.д. Поддерживает permanent blacklist для упорных атакующих.

Конфигурация /usr/local/etc/sshguard.conf:

BACKEND="/usr/local/libexec/sshg-fw-pf"
LOGREADER="LANG=C /usr/bin/tail -n 0 -F /var/log/auth.log"
THRESHOLD=30
BLOCK_TIME=120
DETECTION_TIME=1800
BLACKLIST_FILE=120:/var/db/sshguard/blacklist.db

Выбор подхода

Минимальный VPS с SSH: PF overload + PasswordAuthentication no — достаточно.

VPS с несколькими сервисами: blacklistd для SSH + PF overload для остальных.

Сервер с множеством сервисов (mail, web, ftp): sshguard или fail2ban — парсят логи всех сервисов.

Файловые флаги: immutable и append-only

FreeBSD поддерживает расширенные файловые флаги через chflags(1):

chflags schg /etc/rc.conf              # system immutable — даже root не может изменить
chflags sappnd /var/log/auth.log       # system append-only — можно добавлять, нельзя перезаписывать
chflags noschg /etc/rc.conf            # снять флаг

Флаги schg (system immutable) и sappnd (system append-only) работают в связке с securelevel. При securelevel ≥ 1 снять эти флаги невозможно без перезагрузки в single-user mode. Это защищает критичные файлы от модификации даже при компрометации root.

ls -lo /etc/rc.conf                    # посмотреть флаги (колонка flags)

Практическое применение: установить schg на ключевые конфиги (/etc/rc.conf, /etc/ssh/sshd_config, /boot/loader.conf) и sappnd на лог-файлы. При securelevel 1 атакующий с root-доступом не сможет подчистить логи или изменить конфигурацию.

Securelevel

Подробно описан в статье о sysctl, здесь — security-контекст.

# /etc/rc.conf
kern_securelevel_enable="YES"
kern_securelevel="1"

Securelevel 1 на production-сервере закрывает конкретные вектора атак: загрузку вредоносных kernel modules (kldload), прямой доступ к памяти (/dev/mem, /dev/kmem), снятие флагов immutable/append-only. Securelevel 3 дополнительно запрещает изменение правил firewall — полезно, если хочешь гарантировать, что даже скомпрометированный root не отключит PF.

Ограничение: securelevel можно понизить только перезагрузкой в single-user mode. Это означает, что легитимное обслуживание (изменение immutable-файлов) тоже требует перезагрузки. Для VPS, где физический доступ к консоли ограничен, это нужно учитывать.

MAC Framework: Mandatory Access Control

MAC — pluggable framework для модулей принудительного контроля доступа. В отличие от DAC (стандартные UNIX-права, где владелец файла решает, кому дать доступ), MAC-политики enforced ядром и не могут быть переопределены пользователями, включая root.

MAC поддерживается в FreeBSD с версии 5.0 (TrustedBSD project). Фреймворк модульный: каждый модуль реализует свою политику, модули комбинируются.

Практически полезные модули

mac_portacl(4) — позволяет непривилегированным пользователям привязываться к привилегированным портам (<1024). Полезно для запуска web-сервера без root:

kldload mac_portacl
sysctl security.mac.portacl.rules=uid:80:tcp:80,uid:80:tcp:443
sysctl net.inet.ip.portrange.reservedhigh=0

Пользователь с UID 80 (www) может слушать порты 80 и 443 без root-привилегий.

mac_seeotheruids(4) — более гранулярная альтернатива security.bsd.see_other_uids. Сама политика включается отдельным sysctl security.mac.seeotheruids.enabled, а поверх неё задаются послабления: primarygroup_enabled разрешает видеть процессы участников той же первичной группы, а specificgid_enabled вместе с specificgid выводит перечисленные GID из-под политики:

kldload mac_seeotheruids
sysctl security.mac.seeotheruids.enabled=1
sysctl security.mac.seeotheruids.primarygroup_enabled=1

mac_bsdextended(4) — firewall для файловой системы. Позволяет создавать правила, ограничивающие доступ пользователей/групп к файлам по аналогии с правилами PF:

kldload mac_bsdextended
ugidfw add subject uid 1001 object uid 0 mode n   # UID 1001 не может обращаться к файлам root
ugidfw list                                         # показать правила

mac_biba(4) и mac_mls(4) — реализации классических моделей целостности (Biba) и конфиденциальности (MLS) с метками. Это territory enterprise/military и выходит за рамки типичного VPS.

Когда MAC нужен на VPS

Для типичного VPS — в большинстве случаев не нужен. Стандартных UNIX-прав + jails + securelevel достаточно. MAC оправдан, когда: нужно запустить сервис на привилегированном порту без root (mac_portacl); на многопользовательской системе нужна изоляция, выходящая за рамки стандартных прав; требуется compliance с конкретными стандартами безопасности (CIS Benchmark и подобные).

Аудит: отслеживание действий

Системный аудит (audit)

FreeBSD включает BSM (Basic Security Module) аудит из base system — запись действий пользователей и системных событий:

# /etc/rc.conf
auditd_enable="YES"

# Запустить
service auditd start

Конфигурация — /etc/security/audit_control:

dir:/var/audit
dist:off
flags:lo,aa,ad,fw,fc,fd,fm
minfree:5
naflags:lo,aa
policy:cnt,argv
filesz:2M
expire-after:30d

flags определяют, какие события записываются: lo (логин/логаут), aa (аутентификация), ad (административные действия), fw (запись в файлы), fc (создание файлов), fd (удаление), fm (изменение атрибутов).

Просмотр аудит-логов:

praudit /var/audit/current               # читаемый формат текущего лога
auditreduce -u root /var/audit/ | praudit   # все действия root
auditreduce -m AUE_OPEN_W /var/audit/ | praudit  # все операции записи

Аудит — мощный инструмент для forensics, но генерирует значительный объём данных. На VPS с ограниченным диском стоит тщательно выбирать flags и настроить ротацию (filesz, expire-after).

Логирование и newsyslog

Стандартное логирование через syslogd(8) (base system). Ключевые логи:

/var/log/auth.log          # аутентификация (SSH, su, sudo)
/var/log/messages          # общие системные сообщения
/var/log/security          # security-события
/var/log/pflog             # PF firewall (бинарный, читается через tcpdump)

Ротация логов — newsyslog(8) (base system, аналог logrotate):

# /etc/newsyslog.conf
# logfile                 owner:group  mode  count  size   when  flags
/var/log/auth.log          root:wheel   600   12     1000   *     JC
/var/log/messages          root:wheel   644   5      1000   *     JC

J — сжатие bzip2, C — создавать файл если не существует. Ротация по размеру (KB) или времени.

Мониторинг целостности файлов

mtree(8) (base system) — создаёт спецификацию файловой иерархии и проверяет изменения:

# Создать baseline
mtree -c -K sha256 -p /etc > /root/etc.mtree

# Проверить изменения
mtree -f /root/etc.mtree -p /etc

Показывает изменённые файлы, изменения прав, owner, размера, контрольных сумм. Baseline следует хранить в безопасном месте (на отдельном носителе или под schg-флагом при securelevel ≥ 1).

freebsd-update IDS — верификация установленных файлов base system против известных хэшей:

freebsd-update IDS

Оговорка из man-страницы: доверять этому как настоящей IDS нельзя — на скомпрометированной системе сам freebsd-update может врать, так что проверку имеет смысл гонять с заведомо чистого носителя. И это работает для системы, поставленной традиционными distribution sets; если base установлен пакетами (pkgbase, доступный начиная с 15.0), сверку контрольных сумм даёт pkg check -s.

GELI: шифрование дисков

FreeBSD включает GELI (base system) для полнодискового шифрования:

geli init -s 4096 -l 256 /dev/ada0p3
geli attach /dev/ada0p3
# Работа с /dev/ada0p3.eli как с обычным устройством

На VPS полнодисковое шифрование обычно бессмысленно (провайдер имеет доступ к RAM), но шифрование отдельных разделов с чувствительными данными (бэкапы, БД) может быть оправдано для compliance.

CIS Benchmark для FreeBSD

В 2024 году вышел CIS (Center for Internet Security) FreeBSD 14 Benchmark — первый формальный документ по hardening FreeBSD от CIS. Он покрывает: управление пользователями и группами, конфигурацию сервисов, файловые системы и права, сетевые настройки, аудит и логирование.

Документ полезен как чеклист для production-серверов и для compliance-сценариев. Доступен через FreeBSD Foundation.

Практический чеклист: hardening VPS за первый час

Минимальный набор действий для нового VPS, в порядке приоритета:

  1. Создать непривилегированного пользователя, добавить в группу wheel, настроить SSH-ключ
  2. Установить doas, настроить permit persist :wheel
  3. В sshd_config: PermitRootLogin no, PasswordAuthentication no
  4. Применить sysctl hardening (see_other_uids, ASLR, randompid, coredump)
  5. Включить PF с default deny + overload-таблицей для SSH
  6. Включить blocklistd с UseBlocklist yes в sshd_config
  7. Отключить неиспользуемые сервисы в rc.conf
  8. syslogd_flags="-ss" — закрыть syslog от сети
  9. Рассмотреть securelevel 1 после стабилизации конфигурации

Отличия от Linux-подхода к безопасности

Нет SELinux/AppArmor — вместо них MAC framework с модульной архитектурой. SELinux enforces type enforcement с метками; MAC framework во FreeBSD поддерживает аналогичные модели (Biba, MLS), но используется значительно реже на practice.

Нет fail2ban в base — вместо него blocklistd (API-based подход vs парсинг логов). Для более широкой защиты — sshguard из пакетов.

Файловые флаги (schg, sappnd) + securelevel — уникальная для BSD комбинация. В Linux ближайший аналог — chattr +i, но без securelevel-механизма для enforce.

Аудит (BSM) встроен в base system. В Linux нужен auditd из отдельного пакета.

doas как альтернатива sudo — проще, из OpenBSD, минимальная attack surface.

Источники


Связанные заметки

Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.

Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.