★☆★ Добро пожаловать на shiro.su ★☆★ Оптимизировано под Netscape Navigator 4.0 и разрешение 800x600 ★☆★ Заходите есчё! ★☆★
⚠ САЙТ В РАЗРАБОТКЕ ⚠

Coraza WAF перед HAProxy: разбор боевой конфигурации

опубликовано 01.09.2026 · #haproxy #waf #coraza #security

На этом же хосте, что держит shiro.su, перед бэкендом стоит Coraza — WAF с движком, совместимым по правилам с ModSecurity, и набором правил OWASP Core Rule Set (CRS). Интеграция с HAProxy идёт не через модуль, а через отдельный демон coraza-spoa, который общается с HAProxy по протоколу SPOP (Stream Processing Offload Protocol). Разберём, как это собрано и как работает.

Схема

HAProxy на каждый запрос отправляет данные (метод, путь, заголовки, тело) во внешний агент через SPOE-фильтр. Агент — это coraza-spoa, отдельный процесс, который прогоняет запрос через движок Coraza с правилами CRS и возвращает вердикт (allow/deny и anomaly score). HAProxy уже сам решает, блокировать запрос или пропускать, на основе переменных, которые выставил агент.

клиент → HAProxy (frontend) → [SPOE: coraza-spoa] → решение → backend (shiro-blog) / 403

Плюс такой схемы: WAF живёт в отдельном процессе с собственным непривилегированным пользователем и минимальными правами, а не встроен в worker HAProxy.

Демон coraza-spoa

Собран из исходников через mage (github.com/corazawaf/coraza-spoa, версия v0.7.2, Go 1.25):

version	v0.7.2
go	go1.25.7
dep	github.com/corazawaf/coraza/v3	v3.7.0
dep	github.com/corazawaf/coraza-coreruleset/v4	v4.25.0

Правила CRS вкомпилированы в бинарь как Go-модуль (coraza-coreruleset/v4) — отдельно тащить и обновлять файлы правил на сервере не нужно, они обновляются вместе с зависимостью при пересборке.

Собранный бинарь лежит в /usr/bin/coraza-spoa, конфиг — в /etc/coraza-spoa/config.yaml:

bind: 127.0.0.1:9000

log_level: info
log_file: /var/log/coraza-spoa/coraza-spoa.log
log_format: console

default_application: shiro

applications:
  - name: shiro
    directives: |
      Include @coraza.conf-recommended
      Include @crs-setup.conf.example
      Include @owasp_crs/*.conf

      SecRuleEngine On

    response_check: false
    transaction_ttl_ms: 60000

    log_level: info
    log_file: /var/log/coraza-spoa/shiro-app.log
    log_format: console

name: shiro в applications — это тег приложения, на него ссылается HAProxy при отправке запроса (app=var(txn.coraza.app)), так можно на одном агенте держать разные наборы правил под разные сайты. SecRuleEngine On включает блокировку сразу; для обкатки на боевом трафике логичнее сперва подержать SecRuleEngine DetectionOnly и посмотреть на срабатывания в логе, прежде чем включать блокировку.

Systemd-сервис

Юнит не штатный из репозитория — в него руками добавлен ExecReload, без него systemctl reload не перечитывает конфиг:

[Service]
ExecStart=/usr/bin/coraza-spoa -config=/etc/coraza-spoa/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
User=coraza-spoa
Group=coraza-spoa
Restart=always

SIGHUP проверен вживую — конфиг перечитывается без разрыва уже открытых соединений.

Дальше — плотный sandboxing systemd: своя система/юзер без домашней папки, ProtectSystem=strict, PrivateUsers=true, MemoryDenyWriteExecute=yes, длинный список InaccessiblePaths (от /usr/bin/bash до /usr/bin/ssh), и главное —

RestrictAddressFamilies=AF_INET AF_INET6
IPAddressDeny=any
IPAddressAllow=localhost
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

то есть демону разрешено общаться только с localhost и запрещено вообще всё остальное сетевое взаимодействие. Даже если в самом WAF найдут RCE, вырваться наружу из этой песочницы или достучаться до внешней сети процессу будет некуда.

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

SPOE-конфиг (/etc/haproxy/coraza.cfg) — стандартный пример из репозитория coraza-spoa, без правок:

[coraza]
spoe-agent coraza-agent
    groups      coraza-req
    option      var-prefix      coraza
    option      set-on-error    error
    timeout     hello           2s
    timeout     idle            2m
    timeout     processing      500ms
    use-backend coraza-spoa
    log         global

spoe-message coraza-req
    args app=var(txn.coraza.app) src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body exportRuleIDs=bool(false)

spoe-group coraza-req
    messages coraza-req

Важный нюанс: имя движка в haproxy.cfg (filter spoe engine coraza ...) — это имя секции [coraza] в этом файле, а не имя spoe-agent coraza-agent. Легко перепутать при чтении доки.

В самом haproxy.cfg, во frontend:

http-request set-var(txn.coraza.app) str(shiro)

filter spoe engine coraza config /etc/haproxy/coraza.cfg
http-request send-spoe-group coraza coraza-req

http-request deny deny_status 403 hdr waf-block "request"  if { var(txn.coraza.action) -m str deny }
http-response deny deny_status 403 hdr waf-block "response" if { var(txn.coraza.action) -m str deny }

# fail-closed: SPOA недоступен/ошибся -> 500 вместо тихого пропуска.
# Для fail-open — удалить эти две строки.
http-request deny deny_status 500 if { var(txn.coraza.error) -m int gt 0 }
http-response deny deny_status 500 if { var(txn.coraza.error) -m int gt 0 }

и backend, который проксирует данные агенту (SPOP работает поверх обычного TCP-соединения):

backend coraza-spoa
    mode tcp
    option spop-check
    server coraza_spoa 127.0.0.1:9000 check

Отдельно стоит решение про fail-closed: если агент недоступен или упал с ошибкой, HAProxy вернёт 500, а не молча пропустит запрос мимо WAF. Это осознанный компромисс — доступность сайта против гарантии, что необработанный агентом трафик не проскочит фильтрацию.

Как это выглядит в бою

Из /var/log/coraza-spoa/shiro-app.log — обычный фон сканеров, которые прощупывают любой сайт в интернете:

Coraza: Warning. Restricted File Access Attempt [id "930130"] [msg "Restricted File Access Attempt"]
  [data "Matched Data: .env found within REQUEST_FILENAME: /.env"] [uri "/.env"]

Coraza: Warning. Found User-Agent associated with security scanner [id "913100"]
  [data "Matched Data: Fuzz Faster found within REQUEST_HEADERS:user-agent: Fuzz Faster U Fool v2.1.0-dev"]

Coraza: Access denied (phase 2). Inbound Anomaly Score Exceeded (Total Score: 10) [id "949110"]
  [uri "/wp-config.php"]

Каждое отдельное правило CRS просто добавляет очки в общий anomaly score запроса; финальное решение принимает правило 949110 (REQUEST-949-BLOCKING-EVALUATION) — если суммарный score выше порога, запрос помечается на блокировку, и уже тогда HAProxy получает var(txn.coraza.action) = deny и отдаёт 403. Это стандартная модель CRS — не бинарные "правило сработало → блок", а накопление веса по нескольким сигналам.

Как воспроизвести тестовый стенд у себя

Прежде чем катить такую связку в прод, её стоит собрать и прогнать отдельно — вслепую редактировать боевой HAProxy ради проверки синтаксиса SPOE не лучшая идея. Ниже — пошаговая инструкция стенда, которым я валидировал именно эту схему (HAProxy + coraza-spoa v0.7.2 + OWASP CRS) на живом трафике, прежде чем переносить её в прод. Все команды и результаты ниже реально выполнялись, а не собраны по памяти из документации.

1. Подготовка ОС

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl build-essential gcc socat jq

build-essential и gcc обязательны: сборка coraza-spoa v0.7.2 идёт с CGO_ENABLED=1 (это видно по выводу -version собранного бинаря), чистая кросс-компиляция с CGO_ENABLED=0 не проверялась.

2. HAProxy

sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:vbernat/haproxy-3.2
sudo apt update
sudo apt install -y haproxy
haproxy -v

Стенд проверялся на HAProxy 3.4.0 из этой PPA; сайт работает на 3.2.23 из той же PPA — SPOE стабильна в обеих версиях, разницы в поведении не было.

3. Go и сборка coraza-spoa

go.mod репозитория требует Go 1.25.7 — стокового apt-пакета (обычно куда более старая версия) для этого недостаточно, ставим тарболл с golang.org:

export GOVER=1.25.7
curl -LO https://go.dev/dl/go${GOVER}.linux-amd64.tar.gz
sudo mv /usr/local/go /usr/local/go.bak
sudo tar -C /usr/local -xzf go${GOVER}.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/golang.sh
source /etc/profile.d/golang.sh
go version

Сборка через штатный magefile проекта:

git clone --branch v0.7.2 https://github.com/corazawaf/coraza-spoa.git /opt/coraza-spoa
cd /opt/coraza-spoa
go run mage.go build
./build/coraza-spoa -version

Команда собирает build/coraza-spoa (~27 МБ); вывод -version печатает v0.7.2 и полный список зависимостей, среди них coraza-coreruleset/v4 v4.25.0 — OWASP CRS не тянется отдельным git-клоном, а зашивается в бинарь как обычная Go-зависимость на этапе компиляции. Захотите более свежий CRS — поднимите версию этого модуля в go.mod и пересоберите той же командой.

sudo install -m 0755 build/coraza-spoa /usr/bin/coraza-spoa

4. Конфиг coraza-spoa — начинаем с DetectionOnly

Та же схема config.yaml, что и в проде (см. выше), но с одним отличием на время обкатки:

SecRuleEngine DetectionOnly

В этом режиме атаки логируются с полным разбором сработавших правил CRS и итоговым anomaly score, но ничего не блокируется — самое время посмотреть, что происходит на легитимном трафике, прежде чем включать блокировку. Валидация конфига без запуска сервиса:

sudo -u coraza-spoa /usr/bin/coraza-spoa -config /etc/coraza-spoa/config.yaml -validate

5. systemd-unit, пользователь, логи

Пользователь и каталоги логов на реальном пакете создаются postinst-скриптом; при ручной установке — то же самое руками:

sudo addgroup --quiet --system coraza-spoa
sudo adduser --quiet --system --ingroup coraza-spoa --no-create-home --home /nonexistent --disabled-password coraza-spoa

sudo mkdir -p /var/log/coraza-spoa
sudo chown -R coraza-spoa:adm /var/log/coraza-spoa
sudo chmod 755 /var/log/coraza-spoa

sudo mkdir -p /etc/coraza-spoa
sudo cp coraza-spoa.yaml /etc/coraza-spoa/config.yaml
sudo chown -R coraza-spoa:coraza-spoa /etc/coraza-spoa

sudo cp /opt/coraza-spoa/contrib/coraza-spoa.service /etc/systemd/system/
sudo cp /opt/coraza-spoa/contrib/coraza-spoa.logrotate /etc/logrotate.d/coraza-spoa

Не забудьте про ExecReload из раздела про systemd-сервис выше — в штатном unit-файле его нет, а без него systemctl reload не работает, только полный restart.

sudo systemctl daemon-reload
sudo systemctl enable --now coraza-spoa
sudo systemctl status coraza-spoa

6–7. SPOE-конфиг и haproxy.cfg

Копируем coraza.cfg как есть (раздел выше), в haproxy.cfg прописываем frontend с filter spoe engine и backend, указывающий на реальный адрес защищаемого сайта. Если ваш бэкенд разруливает виртуальные хосты по заголовку Host — не забудьте добавить http-request set-header Host ваш-домен, иначе получите не тот сайт или редирект.

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl restart haproxy
sudo systemctl status haproxy coraza-spoa

8. Функциональные тесты — с реальными результатами

Легитимный запрос — обычный 200 и HTML главной страницы:

curl -si http://<адрес-стенда>/

Необработанные кавычки и угловые скобки в URL curl иногда отклоняет как "Malformed input to a URL function" ещё до отправки запроса — используйте percent-encoding:

# SQLi
curl -si "http://<адрес-стенда>/?id=1%27%20OR%20%271%27%3D%271"
# XSS
curl -si "http://<адрес-стенда>/?q=%3Cscript%3Ealert(1)%3C/script%3E"

В DetectionOnly оба запроса вернули 200, но в лог приложения реально записались сработки CRS:

Coraza: Warning. SQL Injection Attack Detected via libinjection
[file "@owasp_crs/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [id "942100"]
[data "Matched Data: s&sos found within ARGS:id: 1' OR '1'='1"] [severity "critical"]

Coraza: Warning. Inbound Anomaly Score Exceeded (Total Score: 5)
[file "@owasp_crs/REQUEST-949-BLOCKING-EVALUATION.conf"] [id "949110"]

9. Переключение в blocking и живой reload

sudo sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/coraza-spoa/config.yaml
sudo systemctl reload coraza-spoa

Перечитывание по SIGHUP проходит без разрыва уже установленных соединений и без простоя сервиса — в отличие от полного restart. Те же тестовые запросы после этого вернули:

HTTP/1.1 403 Forbidden
waf-block: request

а в access-логе HAProxy — строка с реальными значениями переменных:

... "GET /?q=%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1" txn:QVWBOMOAKYDMDCKC spoa-error:- waf-status:403 score:20 rules_hit:5

10. Проверка fail-open/fail-closed

sudo systemctl stop coraza-spoa
curl -si http://<адрес-стенда>/
sudo systemctl start coraza-spoa

С блокирующими правилами по var(txn.coraza.error) из конфига выше это честный fail-closed: при остановленном coraza-spoa HAProxy отвечает 500 на все запросы, включая легитимные. Нужен fail-open — уберите обе строки http-request/http-response deny по error из haproxy.cfg.

11. Про замер латентности

ab -n 1000 -c 20 http://<адрес-стенда>/

Если гоняете стенд через VPN/туннель до защищаемого сайта — цифры будут врать: сетевой джиттер такого канала (сотни миллисекунд между отдельными запросами) полностью маскирует добавленную WAF-латентность. Валидный замер p50/p99 нужно делать там же, где будет жить прод — с HAProxy, coraza-spoa и бэкендом на одной машине или в одном сегменте сети.

Итог

Получилась разделённая по процессам и правам схема: HAProxy занимается только терминацией TLS и маршрутизацией, WAF — отдельный демон с урезанным systemd-сэндбоксом и доступом только к localhost, а правила CRS обновляются как обычная Go-зависимость при пересборке coraza-spoa. Из минусов — SPOE добавляет сетевой прыжок на каждый запрос (localhost, но всё же), и его конфигурация неочевидна с первого взгляда: три разных файла (systemd-юнит, coraza.cfg, config.yaml) должны договориться об именах (coraza / coraza-agent / shiro), и легко перепутать, что где называется.

Приложение: полные конфиги

Выше — только фрагменты по делу, здесь всё целиком одним куском, для копипасты.

/etc/coraza-spoa/config.yaml
bind: 127.0.0.1:9000

log_level: info
log_file: /var/log/coraza-spoa/coraza-spoa.log
log_format: console

default_application: shiro

applications:
  - name: shiro
    directives: |
      Include @coraza.conf-recommended
      Include @crs-setup.conf.example
      Include @owasp_crs/*.conf

      SecRuleEngine On

    response_check: false
    transaction_ttl_ms: 60000

    log_level: info
    log_file: /var/log/coraza-spoa/shiro-app.log
    log_format: console
/etc/haproxy/coraza.cfg (SPOE)
[coraza]
spoe-agent coraza-agent
    groups      coraza-req
    option      var-prefix      coraza
    option      set-on-error    error
    timeout     hello           2s
    timeout     idle            2m
    timeout     processing      500ms
    use-backend coraza-spoa
    log         global

spoe-message coraza-req
    args app=var(txn.coraza.app) src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body exportRuleIDs=bool(false)

spoe-group coraza-req
    messages coraza-req
/etc/haproxy/haproxy.cfg — минимальный рабочий пример
global
    log /dev/log local0
    maxconn 4096

defaults
    mode http
    log global
    option httplog
    timeout connect 5s
    timeout client  30s
    timeout server  30s

frontend fe_shiro
    bind *:80
    log-format "%ci:%cp\ [%t]\ %ft\ %b/%s\ %Tt\ %ST\ %B\ %{+Q}r\ txn:%[var(txn.coraza.id)]\ spoa-error:%[var(txn.coraza.error)]\ waf-status:%[var(txn.coraza.status)]\ score:%[var(txn.coraza.anomaly_score)]\ rules_hit:%[var(txn.coraza.rules_hit)]"

    http-request set-var(txn.coraza.app) str(shiro)
    http-request set-header Host shiro.su

    filter spoe engine coraza config /etc/haproxy/coraza.cfg
    http-request send-spoe-group coraza coraza-req

    http-request deny deny_status 403 hdr waf-block "request"  if { var(txn.coraza.action) -m str deny }
    http-response deny deny_status 403 hdr waf-block "response" if { var(txn.coraza.action) -m str deny }

    # fail-closed: SPOA недоступен/ошибся -> 500 вместо тихого пропуска.
    # Для fail-open — удали эти две строки.
    http-request deny deny_status 500 if { var(txn.coraza.error) -m int gt 0 }
    http-response deny deny_status 500 if { var(txn.coraza.error) -m int gt 0 }

    default_backend be_shiro

backend be_shiro
    server shiro_origin 127.0.0.1:8080 check

backend coraza-spoa
    mode tcp
    option spop-check
    server coraza_spoa 127.0.0.1:9000 check
/etc/systemd/system/coraza-spoa.service — полный hardened unit
[Unit]
Description=Coraza WAF SPOA Daemon
Documentation=https://www.coraza.io

[Service]
ExecStart=/usr/bin/coraza-spoa -config=/etc/coraza-spoa/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/
Restart=always
Type=exec
User=coraza-spoa
Group=coraza-spoa

# Hardening
AmbientCapabilities=
MountFlags=private

ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectProc=noaccess
ProtectClock=yes
ProtectHostname=yes
ProtectSystem=strict
RestrictSUIDSGID=true
RestrictRealtime=true
SecureBits=no-setuid-fixup-locked noroot-locked

TemporaryFileSystem=/etc
TemporaryFileSystem=/var
BindReadOnlyPaths=-/etc/ca-certificates
BindReadOnlyPaths=-/etc/crypto-policies
BindReadOnlyPaths=-/etc/fdns
BindReadOnlyPaths=-/etc/ld.so.cache
BindReadOnlyPaths=-/etc/ld.so.preload
BindReadOnlyPaths=-/etc/localtime
BindReadOnlyPaths=-/etc/nsswitch.conf
BindReadOnlyPaths=-/etc/passwd
BindReadOnlyPaths=-/etc/pki
BindReadOnlyPaths=-/etc/ssl
BindReadOnlyPaths=-/etc/coraza-spoa
BindPaths=-/var/log/coraza-spoa

InaccessiblePaths=-/opt
InaccessiblePaths=-/srv
#InaccessiblePaths=-/bin
InaccessiblePaths=-/bin/bash
inaccessiblepaths=-/bin/find
InaccessiblePaths=-/bin/less
InaccessiblePaths=-/bin/zcat
InaccessiblePaths=-/bin/rm
InaccessiblePaths=-/bin/readlink
InaccessiblePaths=-/bin/readpath
InaccessiblePaths=-/sbin
InaccessiblePaths=-/efi
InaccessiblePaths=-/run/media
InaccessiblePaths=-/run/mount
InaccessiblePaths=-/efi
InaccessiblePaths=-/boot
InaccessiblePaths=-/dev/kmsg
InaccessiblePaths=-/dev/port
InaccessiblePaths=-/lib/modules
InaccessiblePaths=-/lost+found
InaccessiblePaths=-/proc/bus
InaccessiblePaths=-/proc/config.gz
InaccessiblePaths=-/usr/bin/alsaloop
InaccessiblePaths=-/usr/bin/alsamixer
InaccessiblePaths=-/usr/bin/alsatplg
InaccessiblePaths=-/usr/bin/alsaucm
InaccessiblePaths=-/usr/bin/alsaunmute
InaccessiblePaths=-/usr/bin/attr
InaccessiblePaths=-/usr/bin/balooctl
InaccessiblePaths=-/usr/bin/bash
InaccessiblePaths=-/usr/bin/bootctl
InaccessiblePaths=-/usr/bin/busctl
InaccessiblePaths=-/usr/bin/chacl
InaccessiblePaths=-/usr/bin/chattr
InaccessiblePaths=-/usr/bin/cmp
InaccessiblePaths=-/usr/bin/coredumpctl
InaccessiblePaths=-/usr/bin/crontab
InaccessiblePaths=-/usr/bin/csh
InaccessiblePaths=-/usr/bin/dash
InaccessiblePaths=-/usr/bin/dd
InaccessiblePaths=-/usr/bin/df
InaccessiblePaths=-/usr/bin/diff
InaccessiblePaths=-/usr/bin/diff3
InaccessiblePaths=-/usr/bin/dmesg
InaccessiblePaths=-/usr/bin/dnf
InaccessiblePaths=-/usr/bin/dotty
InaccessiblePaths=-/usr/bin/dracut
InaccessiblePaths=-/usr/bin/evmctl
InaccessiblePaths=-/usr/bin/free
InaccessiblePaths=-/usr/bin/ftp
InaccessiblePaths=-/usr/bin/getfacl
InaccessiblePaths=-/usr/bin/getfattr
InaccessiblePaths=-/usr/bin/grotty
InaccessiblePaths=-/usr/bin/grub2-file
InaccessiblePaths=-/usr/bin/grub2-menulst2cfg
InaccessiblePaths=-/usr/bin/grub2-mkimage
InaccessiblePaths=-/usr/bin/grub2-mkrelpath
InaccessiblePaths=-/usr/bin/grub2-render-label
InaccessiblePaths=-/usr/bin/grub2-script-check
InaccessiblePaths=-/usr/bin/hostnamectl
InaccessiblePaths=-/usr/bin/htop
InaccessiblePaths=-/usr/bin/ipcmk
InaccessiblePaths=-/usr/bin/journalctl
InaccessiblePaths=-/usr/bin/keyctl
InaccessiblePaths=-/usr/bin/kill
InaccessiblePaths=-/usr/bin/killall
InaccessiblePaths=-/usr/bin/ksh
InaccessiblePaths=-/usr/bin/last
InaccessiblePaths=-/usr/bin/localectl
InaccessiblePaths=-/usr/bin/locate
InaccessiblePaths=-/usr/bin/loginctl
InaccessiblePaths=-/usr/bin/ls
InaccessiblePaths=-/usr/bin/lsattr
InaccessiblePaths=-/usr/bin/lsb_release
InaccessiblePaths=-/usr/bin/lsblk
InaccessiblePaths=-/usr/bin/lscpu
InaccessiblePaths=-/usr/bin/lsdiff
InaccessiblePaths=-/usr/bin/lsinitrd
InaccessiblePaths=-/usr/bin/lsipc
InaccessiblePaths=-/usr/bin/lslocks
InaccessiblePaths=-/usr/bin/lslogins
InaccessiblePaths=-/usr/bin/lsmem
InaccessiblePaths=-/usr/bin/lsns
InaccessiblePaths=-/usr/bin/lsof
InaccessiblePaths=-/usr/bin/lsscsi
InaccessiblePaths=-/usr/bin/lsusb
InaccessiblePaths=-/usr/bin/lua
InaccessiblePaths=-/usr/bin/lynis
InaccessiblePaths=-/usr/bin/mail
InaccessiblePaths=-/usr/bin/mkfifo
InaccessiblePaths=-/usr/bin/mkinitrd
InaccessiblePaths=-/usr/bin/mkisofs
InaccessiblePaths=-/usr/bin/mknod
InaccessiblePaths=-/usr/bin/mount
InaccessiblePaths=-/usr/bin/mountpoint
InaccessiblePaths=-/usr/bin/nc
InaccessiblePaths=-/usr/bin/netcap
InaccessiblePaths=-/usr/bin/netstat
InaccessiblePaths=-/usr/bin/netstat-nat
InaccessiblePaths=-/usr/bin/networkctl
InaccessiblePaths=-/usr/bin/nmap
InaccessiblePaths=-/usr/bin/nping
InaccessiblePaths=-/usr/bin/nsenter
InaccessiblePaths=-/usr/bin/pactl
InaccessiblePaths=-/usr/bin/panelctl
InaccessiblePaths=-/usr/bin/passwd
InaccessiblePaths=-/usr/bin/peekfd
InaccessiblePaths=-/usr/bin/pgrep
InaccessiblePaths=-/usr/bin/pidof
InaccessiblePaths=-/usr/bin/ping
InaccessiblePaths=-/usr/bin/pkill
InaccessiblePaths=-/usr/bin/pkttyagent
InaccessiblePaths=-/usr/bin/pmap
InaccessiblePaths=-/usr/bin/portablectl
InaccessiblePaths=-/usr/bin/prtstat
InaccessiblePaths=-/usr/bin/ps
InaccessiblePaths=-/usr/bin/pslog
InaccessiblePaths=-/usr/bin/pstree
InaccessiblePaths=-/usr/bin/pstree.x11
InaccessiblePaths=-/usr/bin/pulseaudio
InaccessiblePaths=-/usr/bin/pwdx
InaccessiblePaths=-/usr/bin/python
InaccessiblePaths=-/usr/bin/python2
InaccessiblePaths=-/usr/bin/python3
InaccessiblePaths=-/usr/bin/python3.9
InaccessiblePaths=-/usr/bin/resolvectl
InaccessiblePaths=-/usr/bin/rkhunter
InaccessiblePaths=-/usr/bin/rpm
InaccessiblePaths=-/usr/bin/rsync
InaccessiblePaths=-/usr/bin/ruby
InaccessiblePaths=-/usr/bin/run-parts
InaccessiblePaths=-/usr/bin/scp
InaccessiblePaths=-/usr/bin/screen
InaccessiblePaths=-/usr/bin/sdiff
InaccessiblePaths=-/usr/bin/setarch
InaccessiblePaths=-/usr/bin/setcifsacl
InaccessiblePaths=-/usr/bin/setfacl
InaccessiblePaths=-/usr/bin/setfattr
InaccessiblePaths=-/usr/bin/setpriv
InaccessiblePaths=-/usr/bin/setsid
InaccessiblePaths=-/usr/bin/setterm
InaccessiblePaths=-/usr/bin/setxkbmap
InaccessiblePaths=-/usr/bin/sftp
InaccessiblePaths=-/usr/bin/sh
InaccessiblePaths=-/usr/bin/skill
InaccessiblePaths=-/usr/bin/slabtop
InaccessiblePaths=-/usr/bin/snice
InaccessiblePaths=-/usr/bin/ssh
InaccessiblePaths=-/usr/bin/ssh-add
InaccessiblePaths=-/usr/bin/ssh-agent
InaccessiblePaths=-/usr/bin/ssh-copy-id
InaccessiblePaths=-/usr/bin/ssh-keyscan
InaccessiblePaths=-/usr/bin/strace
InaccessiblePaths=-/usr/bin/strace-log-merg
InaccessiblePaths=-/usr/bin/strings
InaccessiblePaths=-/usr/bin/stty
InaccessiblePaths=-/usr/bin/su
InaccessiblePaths=-/usr/bin/sudo
InaccessiblePaths=-/usr/bin/systemctl
InaccessiblePaths=-/usr/bin/systemd-tty-ask-password-agent
InaccessiblePaths=-/usr/bin/tcl
InaccessiblePaths=-/usr/bin/tcptraceroute
InaccessiblePaths=-/usr/bin/tcsh
InaccessiblePaths=-/usr/bin/telnet
InaccessiblePaths=-/usr/bin/timedatectl
InaccessiblePaths=-/usr/bin/tload
InaccessiblePaths=-/usr/bin/tmux
InaccessiblePaths=-/usr/bin/top
InaccessiblePaths=-/usr/bin/touch
InaccessiblePaths=-/usr/bin/tracepath
InaccessiblePaths=-/usr/bin/traceroute
InaccessiblePaths=-/usr/bin/traceroute6
InaccessiblePaths=-/usr/bin/tricklectl
InaccessiblePaths=-/usr/bin/tty
InaccessiblePaths=-/usr/bin/udevadm
InaccessiblePaths=-/usr/bin/udisksctl
InaccessiblePaths=-/usr/bin/umount
InaccessiblePaths=-/usr/bin/uname
InaccessiblePaths=-/usr/bin/unlink
InaccessiblePaths=-/usr/bin/updatedb
InaccessiblePaths=-/usr/bin/uptime
InaccessiblePaths=-/usr/bin/users
InaccessiblePaths=-/usr/bin/vi
InaccessiblePaths=-/usr/bin/vim
InaccessiblePaths=-/usr/bin/vim.nox
InaccessiblePaths=-/usr/bin/vim.tiny
InaccessiblePaths=-/usr/bin/vimtutor
InaccessiblePaths=-/usr/bin/vmware-checkvm
InaccessiblePaths=-/usr/bin/vmware-namespace-cmd
InaccessiblePaths=-/usr/bin/vmware-rpctool
InaccessiblePaths=-/usr/bin/vmware-toolbox-cmd
InaccessiblePaths=-/usr/bin/vmware-xferlogs
InaccessiblePaths=-/usr/bin/w
InaccessiblePaths=-/usr/bin/wall
InaccessiblePaths=-/usr/bin/watch
InaccessiblePaths=-/usr/bin/wdctl
InaccessiblePaths=-/usr/bin/wg
InaccessiblePaths=-/usr/bin/wget
InaccessiblePaths=-/usr/bin/who
InaccessiblePaths=-/usr/bin/whoami
InaccessiblePaths=-/usr/bin/zsh
InaccessiblePaths=-/usr/local
InaccessiblePaths=-/usr/sbin
InaccessiblePaths=-/proc/irq
InaccessiblePaths=-/proc/kallsyms
InaccessiblePaths=-/proc/kcore
InaccessiblePaths=-/proc/kmem
#*InaccessiblePaths=-/proc/kmsg
InaccessiblePaths=-/proc/mem
InaccessiblePaths=-/proc/sched_debug
InaccessiblePaths=-/proc/sys/efi/vars
InaccessiblePaths=-/proc/sys/fs/binfmt_misc
#*InaccessiblePaths=-/proc/sys/kernel/core_pattern
InaccessiblePaths=-/proc/sys/kernel/hotplug
#*InaccessiblePaths=-/proc/sys/kernel/modprobe
InaccessiblePaths=-/proc/sys/security
#*InaccessiblePaths=-/proc/sys/vm/panic_on_oom
InaccessiblePaths=-/proc/sysrq-trigger
InaccessiblePaths=-/proc/timer_list
InaccessiblePaths=-/proc/timer_stats
InaccessiblePaths=-/selinux
InaccessiblePaths=-/sys/firmware
InaccessiblePaths=-/sys/fs
InaccessiblePaths=-/sys/hypervisor
InaccessiblePaths=-/sys/kernel/debug
InaccessiblePaths=-/sys/kernel/uevent_helper
InaccessiblePaths=-/sys/kernel/vmcoreinfo
InaccessiblePaths=-/sys/module
InaccessiblePaths=-/sys/power
#*InaccessiblePaths=-/usr/lib/debug
InaccessiblePaths=-/usr/src/linux

LockPersonality=true

LogsDirectory=coraza-spoa
ConfigurationDirectory=coraza-spoa
# coraza-geoip
ReadOnlyPaths=/usr/share/GeoIP
#ReadOnlyPaths=/proc

MemoryDenyWriteExecute=yes

NoNewPrivileges=true

ProtectHome=true
PrivateDevices=true

PrivateUsers=true
PrivateTmp=true

RemoveIPC=true

RestrictAddressFamilies=AF_INET AF_INET6
#RestrictNamespaces=uts ipc pid user cgroup

SystemCallArchitectures=native
SystemCallFilter=@system-service -@setuid -@ipc -@mount

IPAddressDeny=any
IPAddressAllow=localhost

CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

« Назад к списку записей