FAQ

Това е ръководство за инсталиране, настройка и поддръжка на Arcivéo Monitor. Разделите са групирани: общ преглед, разгръщане на панела, свързване на инструментите за сигурност, вградени модули и диагностика. Командите могат да се копират с бутона вдясно.

Откъде да започна

01. Инсталиране на панела — изберете начин

Инсталирането на панела е на отделни страници стъпка по стъпка. Изберете начин:

Ако не сте сигурни — изберете автоматичното. Този справочник остава единен източник за SSL, инструменти, cron и диагностика — install-страниците препращат към неговите раздели, без да дублират нищо.

Преглед

02. Какво представлява Arcivéo Monitor

Arcivéo Monitor — панел за сигурност на сървъра. Събира данни от инсталираните инструменти (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco и др.) и ги показва в единен интерфейс с табло, карта на атаките и подробни страници за всеки инструмент.

Мониторът не е активно средство за защита — той сам по себе си не блокира атаки. Задачата му е да обедини информацията от вече работещите инструменти и да я представи в удобен вид.

03. Как мониторът работи на сървъра

Мониторът работи само локално — трябва да е инсталиран на същия сървър, който наблюдава. Няма SSH или отдалечен API.

Всички команди (fail2ban-client, ufw status, ipset list и т.н.) панелът изпълнява от името на потребителя на уеб сървъра (обикновено www-data, при хостинг панелите — акаунтът на сайта) с ограничен набор права sudo — само за конкретни инструменти, без общ root достъп. Резултатите се обработват и показват в браузъра.

За няколко сървъра инсталирайте монитора на всеки поотделно, с уникален домейн.

04. Как се изчислява Оценката за сигурност

Оценката започва от максимума и намалява за всеки открит проблем:

  • UFW не е активен — −30
  • Fail2ban не е стартиран (няма активни jail) — −25
  • Няма ключове WebAuthn — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum не е зареден — −10
  • Открити заплахи от ClamAV — −20
  • Промени по файлове от AIDE — −15
  • Изтекъл SSL — −30, изтича след <14 дни — −15, <30 дни — −5
  • CrowdSec е инсталиран, но не е стартиран — −5
  • Suricata е инсталирана, но не е стартирана — −5
  • СУБД/кеш (MySQL, PostgreSQL, Redis…) са достъпни отвън — −10
  • Разрешен е вход като root по SSH (PermitRootLogin yes) — −20
  • Има чакащи security-обновления — −5

Резултат: 80+ = Защитен, 60–79 = Внимание, <60 = Под заплаха.

Отнеманията за ClamAV, AIDE, CrowdSec и Suricata се прилагат само ако инструментът е инсталиран. Lynis и AIDE без инициализирана база се показват като „няма данни“ и не намаляват точките. Броят атаки за днес се показва на таблото, но не влияе на Оценката за сигурност.

Настройки и лиценз

05. WebAuthn — двуфакторно удостоверяване

WebAuthn — стандарт за удостоверяване без парола чрез хардуерен ключ. Поддържа YubiKey, Touch ID, Face ID, Windows Hello, Passkey.

След вход с парола системата изисква потвърждение чрез регистриран ключ. Дори паролата да изтече — без физически ключ или биометрия вход е невъзможен.

За настройка отворете Ключове WebAuthn в страничното меню и натиснете „Регистриране на ключ“. Регистрирайте веднага два ключа: ако единственият ключ се изгуби или повреди, входът в панела с него ще е невъзможен.

WebAuthn работи само през HTTPS. При HTTP връзка регистрацията и входът с ключ не са достъпни.

06. Известия: Telegram и имейл

Панелът може да изпраща отчет за сигурността в Telegram и по имейл (ръчно и по график). Настройва се в раздел „Настройки“.

Telegram. Нужни са токен на бота и chat id:

  1. В Telegram напишете на @BotFather/newbot → получете токен от вида 123456:ABC....
  2. Напишете на новия си бот произволно съобщение (за да може да ви отговаря).
  3. Разберете своя chat id: напишете на бота @userinfobot или отворете https://api.telegram.org/bot<TOKEN>/getUpdates и намерете "chat":{"id":...}.
  4. Въведете токена и chat id в „Настройки“ → Telegram и натиснете „Запази и изпрати тест“.

Имейл. Два начина по избор в „Настройки“ → Email:

  • SMTP — хост, порт (465/SSL или 587/TLS), потребител и парола на пощенската ви кутия;
  • Resend — модерен API: посочете API ключ (re_...) и потвърден домейн на подателя.
Бутонът „Изпрати тест“ веднага проверява канала. Графикът на автоматичния отчет е през cron (раздел „Всички cron задачи“): той задейства изпращането, а каналите се вземат от настройките.

Статус на отчета: „ВНИМАНИЕ“ или „ОК“. Заглавието става „ВНИМАНИЕ“ само при реален проблем или чакащо действие: открита заплаха от ClamAV, промени по файлове в AIDE, критични събития на Falco (Emergency/Alert/Critical за последните 24 ч), паднала услуга в Monit, нужно рестартиране, изтичащ SSL (≤14 дни) или чакащи обновления за сигурност. Фоновият шум — SSH опити на ботове, IP адреси, банати от fail2ban, известия на Suricata, предупреждения на Lynis и вече отбити заявки на ModSecurity — не вдига статуса, затова тези числа в отчета сами по себе не означават „ВНИМАНИЕ“.

07. Лиценз — въвеждане и активиране

Подробните модули за наблюдение (Lynis, UFW, ModSecurity, карта на атаките, AIDE, ClamAV и др.) се отключват при наличие на валиден лиценз. Без него таблото, настройките и акаунтът работят, а модулите показват картата „Изисква се лиценз“.

След покупката в профила разполагате с код за активиране от вида ARCIVEO-XXXX-XXXX-XXXX-XXXX. Той трябва да се „активира“ за домейна на вашия панел — това превръща кода в подписан лицензионен файл (блок [license]), който поставяте в панела.

Как да активирате (3 стъпки):

  1. Вземете кода за активиране. Личен профил my.arciveo.com → раздел „Лицензи“ / „Активиране на лиценз“ — копирайте кода ARCIVEO-….
  2. Активирайте кода за вашия домейн. Пак там в профила отворете „Активиране на лиценз“, въведете: кода за активиране, вашия имейл и домейна на панела (адресът, на който се отваря мониторът, напр. monitor.example.com). Натиснете „Активиране“ — системата ще генерира лицензионен файл, обвързан с този домейн, и ще го покаже в поле с бутон „Копиране“.
  3. Поставете ключа в панела. Копирайте целия текст на лиценза → в панела отворете „Настройки“ → блок „Лиценз“, поставете го и натиснете „Запазване“. Модулите се отключват веднага.

Панелът проверява ключа криптографски: подписа, обвързването с домейна и срока на валидност.

Домейнът при активиране трябва точно да съвпада с адреса на панела. Вземете го от константата APP_URL в config.php и въведете само името на хоста — без https:// и без префикса www. Активирането е еднократно: кодът се превръща в лиценз за въведения домейн и не се активира повторно — при грешка в домейна ключът няма да пасне на вашия панел, а кодът ще бъде изразходван. Затова въвеждайте домейна внимателно.
Изтекъл срок или сменен домейн — в горната част на панела ще се появи предупреждение. Лицензът е обвързан с домейна завинаги и не се прехвърля на друг домейн: за нов срок или нов домейн е нужен нов ключ (купува се в профила и се активира еднократно).

08. Файл config.php — всички настройки на панела

Всички основни параметри на панела са зададени в един файл config.php в главната директория (до папката public/) с обикновени константи define(). Файлът се създава при инсталацията; ръчно редактиране рядко е нужно — основно при смяна на домейна, преместване или свързване към друга база. След всяка промяна рестартирайте PHP-FPM (иначе заради OPcache промените няма да се приложат).

Заменете със своите стойности осветените места; останалото оставете както е:

// --- База данных --- define('DB_HOST', 'localhost'); // оставить define('DB_NAME', 'db_name'); // что задали при создании БД define('DB_USER', 'user'); // что задали при создании БД define('DB_PASS', 'db_password'); // что задали при создании БД define('DB_CHARSET', 'utf8mb4'); // оставить // --- Приложение --- define('APP_URL', 'https://monitor.example.com'); // адрес панели, без слэша в конце define('TIMEZONE', 'Europe/Sofia'); // ваш часовой пояс // --- Время сессии --- define('SESSION_LIFETIME', 28800); // простой до повторного входа, сек (28800 = 8 ч)

База данни. Данни за връзка с MySQL/MariaDB:

  • DB_HOST — хост на СУБД, почти винаги localhost;
  • DB_NAME — име на базата данни на панела;
  • DB_USER — потребител на БД (достъп само до своята база);
  • DB_PASS — паролата на този потребител;
  • DB_CHARSET — кодировка на връзката, оставете utf8mb4.

Приложение.

  • APP_URL — пълният адрес на панела (напр. https://monitor.example.com). Трябва да съвпада с домейна, за който е активиран лицензът — иначе ключът ще бъде отхвърлен (вж. раздел „Лиценз“);
  • TIMEZONE — часовата зона на PHP: влияе само на това как панелът показва дати и часове. Върху времето на изпълнение на cron-задачите не влияе — там важи зоната на системата (вж. „Всички cron-задачи“).

Време на сесията. SESSION_LIFETIME — таймаут за бездействие на сесията в секунди (плъзгащ се: обновява се при активност). По подразбиране 28800 = 8 часа; след това време на бездействие панелът ще поиска повторно влизане. Например 3600 = 1 час, 86400 = едно денонощие.

Логване на грешки. Грешките никога не се показват на посетителите, а се записват в logs/php_errors.log — виждат се на страницата „Логове на приложението“. Тези редове (display_errors=0, log_errors=1, пътят error_log) обикновено не е нужно да се променят — настройките са зададени директно във файла и не зависят от php.ini.

config.php — секретен файл. В него е паролата на БД. Намира се в главната директория на панела (до public/), а уеб-коренът (DocumentRoot) на този панел е именно главната директория, не public/. Сам по себе си файлът не „изтича“: в главния .htaccess за него има изрична забрана (Require all denied) — сървърът връща 403. Дори без това правило кодът не би изтекъл: това е PHP — сървърът го изпълнява, а не го отдава като текст. За всеки случай: не го публикувайте в публични хранилища и не го изпращайте в поддръжката с реалната парола. Правата на файла — 640.
При преместване или възстановяване на достъпа този файл е основният източник на данните: името на БД, потребителят и паролата се вземат именно оттук (вж. разделите „Обновяване и преместване на панела“ и „Възстановяване на достъпа“).

Инструменти за сигурност

09. Защитна стена UFW

UFW (Uncomplicated Firewall) — прост интерфейс към nftables/iptables. Затваря всички входящи портове освен изрично разрешените. Страницата „Защитна стена UFW“ показва състоянието и правилата.

sudo apt install ufw # Разреши SSH (задължително ПРЕДИ включване!) и уеб sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Затвори БД отвън (достъп само локално) sudo ufw deny 3306 # Включи и провери sudo ufw enable sudo ufw status verbose
Преди ufw enable задължително разрешете SSH (ufw allow OpenSSH), иначе ще загубите достъп до сървъра.
„Външната експозиция“ на таблото отчита UFW: порт, затворен с правило deny, не се смята за достъпен отвън.
Skipping adding existing rule — това не е грешка. Така UFW съобщава, че точно такова правило вече съществува и не го добавя повторно. При повторно стартиране на автоматичната настройка (тя е идемпотентна) това е нормално съобщение — не е нужно да реагирате.

10. Инсталиране на Fail2ban

Автоматично блокира IP адрес след превишаване на броя неуспешни опити за вход. Анализира логовете на SSH, nginx, Apache и други услуги.

sudo apt install fail2ban sudo systemctl enable --now fail2ban # Проверка на състоянието: sudo fail2ban-client status
Работеща конфигурация (jail.local с десетки jail-ове и автоматичен бан от ipsum) — в следващия раздел.

11. Работеща конфигурация Fail2ban + ipsum

Базовата инсталация е по-горе. Тук е работещата конфигурация, която дава десетки активни jail-ове и хиляди блокирания: общи настройки, ключови jail-ове и автоматичен бан на злонамерени IP от списъка ipsum.

Файлът /etc/fail2ban/jail.local — общи настройки и най-важните jail-ове:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # Прогресивен бан: всяко повторение е за по-дълго bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # перманентен бан за brute-force на SSH findtime = 3600 # Рецидивисти: който е получил няколко бана, се банва завинаги [recidive] enabled = true logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = -1 findtime = 86400 maxretry = 2 [http-get-dos] enabled = true maxretry = 100 findtime = 300 bantime = 1w # Уеб услуги (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … и останалите jail-ове по услуги (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
В ignoreip задължително впишете своя IP и доверените мрежи, иначе можете да банете сами себе си. След промените: sudo fail2ban-client reload.

Автоматично зареждане на блок-списъка ipsum — в root-крон (sudo crontab -e): level 1 (100+ хиляди IP) се зарежда в набора ipsum, който се отсича на защитната стена (повече в раздела „Блок-списък IPset“):

# 04:00 — обновяване на ipset ipsum (level 1, максимален обхват): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
Наборът трябва да се казва ipsum — точно него чете таблото (картата „IPset ipsum“). Нива: levels/1.txt — максимален обхват, levels/3.txt — по-точно (3+ източника).

Защо „Мониторът за сигурност“ е разделен на две зони. Защитата работи на две нива и таблото не ги смесва:

  • Реални атаки (реактивно) — всичко, което fail2ban е хванал: живи опити за пробив (jail-ове sshd, apache-*, nginx-* и т.н.) и злостни рецидивисти (jail recidive — тези, които вече са банени няколко пъти). Това са IP, които реално са влизали при вас — те са на картата на атаките и „Времевата линия“.
  • Превантивен блок (проактивно) — публичен блок-списък с известни злонамерени IP ipset ipsum, отсичан на защитната стена с правило DROP. Тези адреси в повечето случаи изобщо не са докосвали вашия сървър — режат се предварително; броячът „IPset ipsum“ показва колко са отсечени превантивно.

Разликата е проста: реактивно — „тези атакуваха и получиха бан“, превантивно — „тези бяха блокирани още преди опита“. Преди в recidive изкуствено се вкарваше list-3 ipsum (оттам старото деление „списъчни recidive“); сега recidive са само истинските рецидивисти, а превантивното е изцяло на защитната стена.

12. Блоклист IPset (ipsum)

ipsum — публичен списък със зловредни IP адреси, обновяван ежедневно. Мониторът показва броя заредени адреси на таблото и картата на атаките и го отчита в Оценката за сигурност (−10, ако наборът не е зареден).

Минималният вариант без fail2ban е отделен набор ipsum с блокиране през iptables:

# Създаване на набор (еднократно): sudo ipset create ipsum hash:ip # Скрипт за обновяване /usr/local/bin/update-ipsum.sh: #!/bin/bash ipset flush ipsum for ip in $(curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt); do ipset add ipsum "$ip" 2>/dev/null done iptables -C INPUT -m set --match-set ipsum src -j DROP 2>/dev/null \ || iptables -I INPUT -m set --match-set ipsum src -j DROP # Cron (sudo crontab -e, ежедневно в 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
Разширеният вариант с fail2ban-recidive е в раздела „Работна конфигурация Fail2ban + ipsum“.
ipset живее в паметта и се губи при рестарт. Само ежедневен крон ще остави набора празен от момента на рестарта до следващото стартиране (таблото ще покаже 0). Зареждайте набора и при стартиране — изнесете зареждането в скрипт и го закачете на @reboot. Заедно с това командата create … -exist задава лимита maxelem 300000 (по подразбиране 65536 — level 1 не се събира, ще излезе „Hash is full“):
# /usr/local/bin/load-ipsum.sh #!/bin/bash curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt \ | grep -v '^#' | sed 's/^/add ipsum /' \ | (echo "create ipsum hash:ip hashsize 131072 maxelem 300000 -exist"; echo "flush ipsum"; cat) \ | ipset restore -exist # sudo crontab -e — ежедневно в 04:00 И при всяко стартиране: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
Как работи при автоматична инсталация. Скриптът зарежда пълния списък level 1 (100+ хиляди IP) в набора ipsum и, ако защитната стена се управлява от инсталатора (нов VPS — профили „Пълна“/„Олекотена“), свързва набора към UFW с правило DROP — трафикът от тези IP реално се блокира. Правилото е след ESTABLISHED,RELATED, затова текущите връзки (вкл. вашият SSH) не се прекъсват — режат се само новите връзки от списъка. Наборът се възстановява при стартиране на услугата ipsum-load.service преди защитната стена (иначе UFW не би се вдигнал) и се обновява от крон в 04:00. На вече конфигуриран сървър (панел, собствена защитна стена) инсталаторът не пипа защитната стена — там ipsum остава списък за таблото и картата на атаките, а правилото DROP при желание се добавя ръчно (минималният вариант с iptables … --match-set ipsum … -j DROP е по-горе). При автоматична инсталация не е нужно да правите нищо ръчно.

13. Инсталиране на CrowdSec

Модерна замяна на Fail2ban с колективен threat intelligence: блокирания от общността плюс собствени правила. Изисква отделен bouncer за прилагане на блокиранията към защитната стена.

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash sudo apt install crowdsec sudo systemctl enable --now crowdsec # Bouncer за iptables/nftables: sudo apt install crowdsec-firewall-bouncer-iptables # Проверка на състоянието: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
Състояние „Не е стартиран“ в панела = сервисът е инсталиран, но услугата не е активна (мониторът я проверява чрез systemctl is-active crowdsec). Стартиране: sudo systemctl enable --now crowdsec; при срив вижте sudo journalctl -u crowdsec -n 30. Същото важи за всеки сервис в състояние „Не е стартиран“ (Suricata, Falco, Monit, MySQL).
„0 сценария“ или „0 bouncers“ на таблото. CrowdSec идва почти празен по подразбиране — без колекции не засича нищо, а без регистриран bouncer блокиранията не се прилагат към защитната стена. Инсталирайте базовите колекции и се уверете, че bouncer е в списъка:
# Базови колекции (Linux + SSH + уеб сървър): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer трябва да е в списъка и със състояние на активна връзка: sudo cscli bouncers list
В лога на bouncer stream halted / блокиранията не се прилагат. Това е осиротял api-ключ: bouncer е премахнат от cscli bouncers list, но старият му ключ е останал в /etc/crowdsec/bouncers/*.yaml. Регистрирайте bouncer наново и запишете свеж ключ:
sudo cscli bouncers add fw-bouncer # ще изведе нов api_key # впишете този ключ в api_key: в /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml sudo systemctl restart crowdsec-firewall-bouncer
Автоматичното инсталиране (профил „Пълна защита“) само инсталира колекциите и регистрира firewall-bouncer — ръчно това е нужно само при ръчно инсталиране или след ръчна намеса в CrowdSec.

14. Инсталиране на AIDE

AIDE (Advanced Intrusion Detection Environment) прави снимка на файловата система и при всяка проверка съобщава за промени в /etc, /bin, /usr. След инсталирането е задължителна инициализация на базата (aideinit).

sudo apt install aide # Инициализация на базата (5–15 минути): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: каталогът /var/lib/aide се създава в режим 700 (собственик _aide), # и панелът (www-data) не вижда базата → показва „Не е инициализирана“. # Отворете каталога за преминаване (файловете на базата остават 600): sudo chmod 755 /var/lib/aide # Първа проверка СЪС ЗАПИС в лога, който чете мониторът. # На Ubuntu/Debian aide изисква явен --config (иначе „missing configuration“; # бинарният aide.wrapper вече не се доставя в новите версии): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
По време на aideinit терминалът стои 5–15 минути на реда Running aide --init... — това е нормално (хеширане на цялата ФС, натоварване на диска). Не прекъсвайте с Ctrl+C. Ако процесът „виси“, но нищо не изписва — вероятно чака отговор на скрито запитване Overwrite existing aide.db.new [Yn]? (натиснете Y). Проверете активността от друга сесия: pgrep -af aide.
Грешка при aideinit: „21_aide_spamassassin … printf: invalid number“ (return code 20) — известен бъг в конфигурационния сниппет на AIDE в Ubuntu 22.04. Базата не се създава. Извадете счупения сниппет и опитайте отново:
sudo mv /etc/aide/aide.conf.d/21_aide_spamassassin /etc/aide/21_aide_spamassassin.disabled sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
Статуси в таблото. „Не е инициализирана“ = панелът не вижда файла на базата: или aideinit не е стартиран, или (Ubuntu 24.04) каталогът /var/lib/aide е създаден в режим 700 и е недостъпен за www-data — решава се със sudo chmod 755 /var/lib/aide (вж. блока по-горе). „Няма проверки“ = базата съществува, но проверка още не е извършвана — това не е грешка. Резултатите мониторът чете от /var/log/aide/aide.log.
Редовна проверка → лог за панела. Стандартният /etc/cron.daily/aide на новите Ubuntu/Debian може да не записва /var/log/aide/aide.log в нужния вид (а aide.wrapper вече го няма в тях). По-надеждно е да добавите свой cron с явен --config — той записва лога от root в режим 644 и мониторът го чете без допълнителни групи:
# sudo crontab -e — ежедневна проверка в 02:00: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # Стартирайте сега, без да чакате разписанието: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Автоматичната инсталация вече прави всичко това: chmod 755 /var/lib/aide и cron за проверка в 02:00 — ръчно не е нужно нищо.
Първата инициализация правете на чист сървър — преди инсталирането на уеб приложенията. След легитимни промени пресъздавайте базата: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.

15. Инсталиране на ClamAV

Антивирусен скенер за Linux. Особено полезен за проверка на /var/www за PHP-шелове и зловреден код.

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # Обновяване на базата със сигнатури: sudo freshclam # Ръчно сканиране на папка: sudo clamscan -r /var/www --infected
Демонът clamd показва „Неактивен“ след enable --now? Три типични причини:

1. В конфигурацията е останал редът Example — clamd отказва да стартира, докато той е там:

sudo sed -i '/^Example/d' /etc/clamav/clamd.conf sudo systemctl restart clamav-daemon

2. Не е свалена базата със сигнатури — clamd не стартира без нея:

sudo systemctl stop clamav-freshclam sudo freshclam sudo systemctl start clamav-freshclam sudo systemctl restart clamav-daemon

3. Просто зарежда — clamd зарежда ~8 млн. сигнатури в паметта за 30–60 сек. Изчакайте и проверете: systemctl is-active clamav-daemon (статус activating → все още зарежда).

Диагностика: sudo journalctl -u clamav-daemon -n 30 --no-pager.
На таблото „Проверени файлове: 0“ / „Последно сканиране: —“? Демонът clamd само държи сигнатурите в паметта, сам той не сканира нищо по разписание. Панелът показва резултатите от планово сканиране, затова е нужен крон, който сканира и пише лог. Автоматичното инсталиране поставя обвивката /usr/local/bin/clamav-scan.sh и крон в 01:30 — след първото стартиране ще се попълнят „Проверени файлове“ и „Последно сканиране“. За да стартирате веднага, без да чакате разписанието: sudo /usr/local/bin/clamav-scan.sh.

16. Инсталиране на Linux Malware Detect (maldet)

Linux Malware Detect (LMD) — скенер за зловреден софтуер срещу уеб заплахи: PHP шелове, уеб бекдори, товарачи. Използва двигателя на ClamAV и го допълва със свои сигнатури.

wget https://www.rfxn.com/downloads/maldetect-current.tar.gz tar -xzf maldetect-current.tar.gz dir=$(ls -d maldetect-*/ | head -1) && cd "$dir" && sudo bash install.sh && cd ~ rm -rf maldetect-* maldetect-current.tar.gz # Обновяване на сигнатурите: sudo maldet -u # Сканиране на /var/www: sudo maldet -a /var/www
LMD и ClamAV работят добре заедно. Последен отчет: maldet --report.
При инсталирането е възможно да се появи редът update-rc.d: error: unable to read /etc/init.d/maldet — той е безвреден. maldet не използва init.d, обновяването на сигнатурите и сканиранията се стартират чрез /etc/cron.daily/maldet. Ако по-долу се вижда installation completed — всичко е инсталирано.
На страницата LMD пише „Не е инсталиран“, макар да е инсталиран? maldet не се инсталира чрез apt, а в /usr/local/maldetect, и при включен open_basedir наличието му се проверява чрез shell — вижте раздела „Страницата е празна, макар данните на сървъра да ги има“.

17. Инсталиране на Suricata

Мрежова система за откриване на прониквания: анализира трафика на ниво пакети и разпознава хиляди сигнатури на атаки. Допълва ModSecurity (той работи на ниво HTTP, Suricata — на ниво TCP/IP).

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # Изтегляне на актуалните правила: sudo suricata-update sudo systemctl enable --now suricata
Suricata е „Активен“, но панелът не показва известия / броят събития е 0? Suricata записва /var/log/suricata/eve.json под root в режим 750 върху директорията, а уеб сървърът (www-data) не може да я прочете. Отворете директорията за преминаване — файловете вътре остават защитени:
sudo chmod o+rx /var/log/suricata
Автоматичното инсталиране прави това само — ръчно не е нужно.

18. Инсталиране на Falco

Прихваща системни извиквания през eBPF/kernel module и открива аномалии в реално време: shell от nginx, четене на /etc/passwd от уеб процес, запис в /bin и т.н.

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc > /tmp/falco.asc gpg --dearmor < /tmp/falco.asc | sudo tee /usr/share/keyrings/falco-archive-keyring.gpg > /dev/null sudo chmod 644 /usr/share/keyrings/falco-archive-keyring.gpg && rm /tmp/falco.asc echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" \ | sudo tee /etc/apt/sources.list.d/falcosecurity.list sudo apt update && sudo apt install falco sudo systemctl enable --now falco
Мониторът чете събитията на Falco през journalctl -u falco (без sudo — чрез групата systemd-journal). Уверете се, че www-data е в тази група — вж. „Настройка на sudo“ (т.2) на страницата за ръчно инсталиране.
„0 събития за 24 часа“ е нормално, а не грешка. Falco е event-driven: мълчи, докато всичко е наред, и записва събитие само при аномалия (shell от уеб процес, четене на /etc/passwd, запис в системни директории). Нула критични за денонощие на спокоен сървър е здравословно състояние.
За таблото е по-надеждно извеждане във файл. Четенето през journalctl изисква права върху журнала; за да вижда таблото събитията стабилно, автоматичното инсталиране включва при Falco file_output/var/log/falco/falco.log и задава на услугата UMask=0022 (логът се чете от уеб сървъра). При нова инсталация не е нужно да настройвате това ръчно.

19. Инсталиране на ModSecurity (WAF)

ModSecurity — уеб-защитна стена (WAF) за Apache или Nginx. Блокира атаки на ниво приложение: SQL инжекции, XSS, обход на пътища, скенери.

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # Набор правила OWASP Core Rule Set: sudo apt install modsecurity-crs # ЗАДЪЛЖИТЕЛНО: без този файл ядрото за правила е изключено sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf sudo apache2ctl configtest && sudo systemctl reload apache2 # Проверка: трябва да върне 403 curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
Инсталирането на пакета само по себе си не защитава нищо. Apache зарежда конфигурациите с реда IncludeOptional /etc/modsecurity/*.conf, а пакетът поставя само modsecurity.conf-recommended — под маската *.conf той не попада. Ако не го копирате в modsecurity.conf, SecRuleEngine остава Off: модулът е зареден, правилата CRS са заредени, но трафикът не се проверява и одит-логът не се създава. Междинният режим DetectionOnly само записва събития в лога, без да блокира заявките — панелът го показва в жълто.

Достъп на панела до одит-лога. Логът /var/log/apache2/modsec_audit.log принадлежи на root (права 640), уеб-потребителят не може да го прочете. Панелът взима данните през обвивка — създайте я:

sudo tee /usr/local/bin/monitor-modsec >/dev/null <<'EOF' #!/bin/sh echo "ENGINE=$(grep -hE '^SecRuleEngine[[:space:]]+' /etc/modsecurity/*.conf 2>/dev/null | tail -1 | awk '{print $2}')" echo "---LOG---" tail -n 3000 /var/log/apache2/modsec_audit.log 2>/dev/null echo "---RULES---" for f in /etc/modsecurity/crs/rules/*.conf /usr/share/modsecurity-crs/rules/*.conf /etc/modsecurity/custom-rules.conf; do [ -f "$f" ] && { echo "===FILE:$(basename "$f")==="; cat "$f"; } done EOF sudo chown root:root /usr/local/bin/monitor-modsec sudo chmod 755 /usr/local/bin/monitor-modsec # в /etc/sudoers.d/monitor (потребител = този, под който работи PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
Обвивката взима последната директива SecRuleEngine без отстъп: редовете с отстъп са вътре в блокове <LocationMatch>/<Directory> (например изключване на WAF за phpMyAdmin) и не определят глобалния режим.
Потребителят в sudoers трябва да съвпада с потребителя на FPM-пула: на обикновен Apache/Debian това е www-data, в HestiaCP пулът на сайта работи от собственика на сайта (например admin) — проверете с grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
Ако сайтът е зад Nginx-прокси (HestiaCP), Apache вижда като клиент самото прокси — панелът взима реалния IP адрес на атакуващия от хедъра X-Forwarded-For. В статистиката попадат само транзакциите със сработило правило: директивата SecAuditLogRelevantStatus записва в одит-лога всякакви отговори 4xx/5xx, затова там попадат и обикновените 403/500 — панелът не ги брои за събития на WAF.
Блокът ---RULES--- е нужен на раздела „Всички активни правила“ — панелът показва не само сработилите, а изобщо всички заредени CRS правила + персонализираните. Трите пътя в цикъла for f in … са типичните места за CRS правила и локални допълнения; ако при вас подредбата е различна (пакетът поставя файловете в своя директория, или персонализираните правила не са в /etc/modsecurity/custom-rules.conf), намерете реалните пътища с командата sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null и ги добавете в списъка. Ако обвивката е стара (без тази секция) — разделът просто ще покаже предупреждение „недостъпно“, останалата част от страницата работи както преди.

20. Инсталиране на Auditd

Auditd (Linux Audit Daemon) записва системните извиквания на ниво ядро: входове и изходи, sudo команди, неуспешни опити за удостоверяване, промени на файлове. Мониторът показва входовете, неуспешните опити и sudo командите за днес.

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # Проверка на статуса и събитията: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
Мониторът чете събитията чрез ausearch (/usr/sbin/ausearch) и при нужда от /var/log/audit/audit.log с командата tail. И двете трябва да са в sudoers.

21. Инсталиране на Monit

Следи услугите (nginx, php-fpm, mysql и т.н.) и ги рестартира при срив. Може да изпраща известия по имейл.

sudo apt install monit sudo systemctl enable --now monit # Конфигурации: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
Мониторът получава списъка с услуги чрез monit status. В /etc/monit/monitrc трябва да е включен HTTP интерфейсът (блокът set httpd с allow localhost), иначе monit status ще върне грешка.
На таблото пише „0 услуги под наблюдение“? Две причини. (1) HTTP интерфейсът е изключен — в monitrc редът set httpd е закоментиран (по подразбиране е като # set httpd port 2812 …). Разкоментирайте блока и разрешете localhost. (2) Включеният httpd сам по себе си не следи нищо — Monit отчита само това, което е описано с check-станси; без тях списъкът е празен дори при работещ интерфейс. Минимална работеща конфигурация:
# /etc/monit/conf.d/00-httpd — HTTP интерфейс за localhost: set httpd port 2812 use address localhost allow localhost # примери за check-станси (какво да се следи): check process sshd with pidfile /run/sshd.pid start program = "/usr/bin/systemctl start ssh" stop program = "/usr/bin/systemctl stop ssh" check filesystem rootfs with path / if space usage > 90% then alert
sudo monit -t # проверка на синтаксиса (Control file syntax OK) sudo systemctl reload monit sudo monit status
Автоматичното инсталиране поставя готов conf.d с httpd на 2812 и набор от проверки — на нова инсталация не се налага ръчна настройка.
Услуга в състояние „С грешки“? Мониторът само показва състоянието и умишлено не рестартира услуги от уеб панела (това би било отдалечено изпълнение на root команди в панел за сигурност). Диагностиката и рестартът стават по SSH чрез Monit:
sudo monit status <service> # причина за грешката sudo monit restart <service> # рестарт през Monit # ако Monit не вдига услугата — вижте нейния собствен юнит: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

22. Инсталиране на PSAD (засичане на сканиране на портове)

PSAD анализира дневника на iptables и открива сканиране на портове и мрежови атаки, като присвоява на всеки източник ниво на заплаха (1–5). Допълва fail2ban и Suricata.

sudo apt install psad # PSAD чете лога на iptables — трябва да се включи журналирането (UFW го прави сам). # За чист iptables добавете правила LOG към веригите INPUT/FORWARD. sudo psad --sig-update sudo systemctl enable --now psad
Мониторът чете данните през psad --Status (необходим е в sudoers). Без журналиране на iptables страницата ще е празна — това е нормално, докато няма извършени сканирания.

23. AppArmor / SELinux (контрол на достъпа)

Mandatory Access Control ограничава до какви файлове и ресурси може да достъпва дадена програма, дори ако е била хакната. В Ubuntu/Debian по подразбиране се използва AppArmor (обикновено вече е инсталиран и активен).

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # проверка на профилите
Мониторът чете състоянието чрез aa-status (нужен е в sudoers). Показва броя профили в режим enforce/complain и процесите без профил.

„Заредени профили“ повече от enforce + complain — това е нормално. В AppArmor 4.x (Ubuntu 24.04 и по-нов) се появи режимът unconfined: профилът е зареден в ядрото, но не ограничава нищо. Ubuntu маркира така десетки профили за програми, използващи user namespaces (браузъри, torrent клиенти и подобни). Когато има такива профили, картата „Заредени профили“ става кехлибарена и показва техния брой — например unconfined: 90 при 120 заредени и 26 в enforce. Реално защитават само профилите в enforce; на Ubuntu 22.04 (AppArmor 3.x) този режим липсва и числата винаги съвпадат.

sudo aa-status | grep -E "profiles are" # разбивка по режими sudo aa-enforce /etc/apparmor.d/profile-name # прехвърляне на профил в enforce
Прехвърлянето в enforce на профили, които Ubuntu умишлено е оставила в unconfined, си струва само осъзнато: те не са изключени по грешка, а защото иначе се нарушава работата на самите програми. Профилите в complain са друго нещо: там правилата вече са написани, само че не се прилагат.

24. Инсталиране на debsums (цялост на пакетите)

debsums проверява дали файловете на инсталираните пакети съвпадат с контролните суми от хранилището — открива подменени системни бинарни файлове (допълва AIDE). Пълната проверка отнема 1–2 минути, затова се стартира по cron, а панелът чете резултата от data/debsums/debsums.log и сам го разпределя по категории (важни са само бинарните файлове и библиотеките).

Задачата е в root-крон (sudo crontab -e). Готовата обвивка debsums-scan.sh се поставя в /usr/local/bin/ (chmod +x; вж. обобщението на cron-задачите) и сама записва отчета в data/debsums/ на панела.

sudo apt install debsums # Cron-строка (ежедневно 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Обвивката debsums-scan.sh сама намира data/ на панела — не е нужно да задавате пътя.

Промените в /etc/ (конфигурации) и /usr/share/ (ресурси) на сървъра обикновено са нормални — панелът ги отбелязва с отделен цвят. Тревожни са промените в бинарните файлове и библиотеките (/bin, /sbin, /usr/lib и т.н.) — картата „Бинарни файлове / библиотеки“ показва именно тях.

25. Настройка на отчетите на Lynis

Lynis се стартира ръчно или чрез cron. Отчетът трябва да се записва в папката data/lynis/ на проекта — мониторът чете файла lynis-report.dat.

# Еднократно стартиране (заменете със своя път до корена на панела): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # Ежедневен одит — cron ред (готовата обвивка lynis-scan.sh в /usr/local/bin/, вижте обобщението): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
След първото стартиране страницата „Одит Lynis“ веднага ще покаже hardening index, предупрежденията и препоръките.
Бутон „Стартиране на одит“ на страницата Lynis. Той стартира lynis-scan.sh във фонов режим директно от панела (без да чака cron): показва „Сканиране…“ и след завършване сам обновява отчета. За целта уеб потребителят се нуждае от sudoers ред за стартиране на скрипта — инсталаторът го добавя автоматично в /etc/sudoers.d/monitor. Ако панелът е инсталиран ръчно/по-рано, добавете го със същия потребител, който вече е посочен във файла:
u=$(sudo awk '/NOPASSWD/ && !/lynis-scan/ {print $1; exit}' /etc/sudoers.d/monitor) [ -n "$u" ] && echo "$u ALL=(ALL) NOPASSWD: /usr/local/bin/lynis-scan.sh" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c && sudo chmod 440 /etc/sudoers.d/monitor

26. Настройка на отчетите на Logwatch

Logwatch трябва да записва ежедневните отчети в папката data/logwatch/ на проекта във формат .txt. Мониторът показва последния отчет и архива.

# Ежедневно (6:00) — cron-ред (готова обвивка logwatch_daily.sh в /usr/local/bin/, вижте обобщението): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

Модули на панела

27. Мрежов монитор (вграден)

Мрежовият монитор не изисква инсталация — това е вградена страница на панела. Тя показва мрежовото състояние на сървъра от локални източници:

  • интерфейси и трафик — от /proc/net/dev;
  • състояние на връзките (UP/DOWN) и IP — чрез ip;
  • връзки и слушащи портове — чрез ss;
  • мрежови събития на ядрото за 24 ч — чрез journalctl -k.

Първите три източника работят без sudo, затова интерфейсите, трафикът, връзките и портовете се виждат веднага. Блокът „Събития на ядрото“ използва journalctl -k — той се чете чрез групата systemd-journal („Настройка на sudo“, т.2), sudo не е нужен. Проверете дали всичко е достъпно за уеб потребителя:

# Проверка от името на www-data (под него работи PHP): sudo -u www-data bash -c 'cat /proc/net/dev' sudo -u www-data bash -c 'ip -o link show' sudo -u www-data bash -c 'ss -s' sudo -u www-data journalctl -k --no-pager -n 5
Блокът „Мрежови събития на ядрото“ показва събития на мрежовия стек на ядрото (смяна на връзка up/down, грешки на носещата, „network unreachable“). Записите на защитната стена UFW BLOCK не попадат тук — те са на страниците „Защитна стена UFW“ и „Карта на атаките“. Празен блок със зелена отметка = за денонощието не е имало мрежови сривове.

28. Диск и SMART

Вградената страница показва три неща:

  • Файлови системи — запълване на дяловете (df); скалата почервенява при ≥90%;
  • Устройства за съхранение — списък с дискове (lsblk), само реалните (loop/snap са скрити);
  • Състояние (SMART) — статус на диска и атрибути (smartctl).

Заетото място и списъкът с устройства работят веднага, без настройка. За SMART е нужен пакетът smartmontools. Уеб-процесът няма пряк достъп до дисковите устройства, затова SMART се снема чрез cron във файла data/disk/smart.txt, а панелът го чете.

Заданието е в root-крон (sudo crontab -e). Готовата обвивка smart-scan.sh се поставя в /usr/local/bin/ (chmod +x; вижте обобщението на cron-задачите) и сама пише в data/disk/ на панела.

sudo apt install smartmontools # Cron-строка (каждые 30 минут): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Обвивката smart-scan.sh сама намира data/ на панела — не е нужно да задавате пътя. Вътре lsblk -e7,11 изключва loop/cdrom.

На виртуални дискове (QEMU/KVM и подобни) обикновено е достъпен само общият статус „състояние: OK“, а температурата, часовете на работа и преразпределените сектори може да са празни — това е нормално. На физически сървър се показват всички атрибути.

29. Производителност (CPU/RAM/мрежа/диск)

Страницата показва историята на натоварването на сървъра за последните 24 часа — Load Average, натоварване на CPU и изчакване за I/O, RAM/Swap, мрежов трафик (приемане/предаване), дисков I/O (четене/запис), запълване на диска и inodes, отворени файлови дескриптори и MySQL-връзки, плюс текущия брой TCP-връзки и процеси.

Данните се събират от cron/collect_metrics.php — веднъж на 5 минути записва една „сурова“ снимка на брояча (/proc/loadavg, /proc/meminfo, /proc/stat, /proc/net/dev, /proc/diskstats, df/df -i, /proc/sys/fs/file-nr, SHOW GLOBAL STATUS LIKE 'Threads_connected') в таблицата в БД system_metrics; процентите и скоростите страницата изчислява сама по разликата между съседни снимки (запълване на диска/inodes/дескриптори/MySQL-връзки — моментни стойности, без преизчисляване). Sudo не е необходимо — източниците се четат без права на root. Точките по-стари от 24 часа се изтриват автоматично при всеки запис.

# Cron-ред (на всеки 5 минути): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Обвивката collect-metrics-all.sh (вж. обобщението на cron-задачите) сама намира всички инсталирани инстанции на панела на сървъра и стартира cron/collect_metrics.php на всяка от името на собственика на сайта.

Докато колекторът не се задейства поне два пъти (първите ~10 минути след инсталацията), страницата показва „данните се събират“ — на графиките е нужна поне една двойка съседни точки, за да се изчислят скоростите и процентите.

Известия за натоварване (раздел „Настройки“ → „Известия за натоварване“) — при превишаване на прага за CPU/RAM/диск/inodes панелът изпраща известие в Telegram/Email (същите канали като при дневния отчет — не е нужно да ги включвате отделно за известията), и още едно — когато метриката се върне в норма. По време на задържане на прага не спами повторно: следващото известие ще дойде едва след цикъла „върна се в норма → отново превиши“.

Праговете се проверяват от същия collect_metrics.php при всяко стартиране (веднъж на 5 минути) — отделен cron не е нужен. Състоянието „вече известено / още не“ се съхранява в data/alerts_state.json, а праговете — в настройките на панела.

30. Карта на атаките (GeoIP)

Страницата „Карта на атаките“ определя държавата по IP с командата geoiplookup. Без пакета GeoIP държавите няма да бъдат определени и точките на картата няма да се появят:

sudo apt install geoip-bin geoip-database # Проверка: geoiplookup 8.8.8.8
Sudo не е необходимо — базата /usr/share/GeoIP/GeoIP.dat се чете от всички, резултатите се кешират в tmp/geoip_cache.json. Самата карта (Leaflet + плочки от OpenStreetMap) се зарежда в браузъра — нужен е интернет на компютъра, на който е отворен панелът.

31. Външна експозиция, обновления и автообновления

Две вградени карти в таблото, които показват не „вкл./изкл.“ на даден инструмент, а реалната защитеност на сървъра. Не изискват настройка, четат се локално без sudo.

Външна експозиция — колко услуги слушат на всички интерфейси (0.0.0.0/[::]) и са достъпни отвън. Подсветва в червено, ако навън стърчат СУБД или кеш (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — това е пряка дупка (−10 към Оценката за сигурност). Източник: ss -tuln.

Ако картата е червена — затворете СУБД за външния свят: вържете я към 127.0.0.1 (bind-address в конфигурацията на MySQL/PostgreSQL, bind 127.0.0.1 в Redis) или затворете порта в UFW.
„Отворен порт“ ≠ „достъпен отвън“. Услуга, която слуша на 127.0.0.1 (loopback), е видима само за самия сървър — отвън не се достига до нея, дори портът да е „отворен“. Затова Postfix на порт 25, вързан към loopback, е безопасен: автонастройката задава inet_interfaces = loopback-only (плюс неутрален smtpd_banner — затваря забележката на Lynis MAIL-8818 за разкриване на версията). Картата „Външна експозиция“ брои като навън само това, което слуша на 0.0.0.0/[::]; loopback услугите не попадат там.
Lynis MAIL-8818 ръчно (ако сте настройвали пощата сами): в /etc/postfix/main.cf задайте smtpd_banner = $myhostname ESMTP (без версия и ОС) и inet_interfaces = loopback-only, след което sudo systemctl restart postfix.

Обновления за сигурност — колко пачове за сигурност чакат инсталиране и нужно ли е рестартиране след обновяване на ядрото (−5 към Оценката за сигурност при наличие на пачове). Източник: /usr/lib/update-notifier/apt-check, файл /var/run/reboot-required. Подробен списък — на страницата „Обновления за сигурност“.

# Инсталиране на обновления: sudo apt update && sudo apt upgrade # Проверка какво слуша навън: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
Картата за обновления работи на Ubuntu/Debian (update-notifier-common). Ако apt-check липсва — Мониторът брои пачовете чрез apt-get -s upgrade.

Автообновления за сигурност (unattended-upgrades) — на страницата „Обновления за сигурност“ отделна карта показва дали е включено автоматичното инсталиране на пачове за сигурност и кога е стартирало за последно. Не е нужен sudo — статусът се чете чрез apt-config dump.

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # включване # Проверка какво е включено: apt-config dump | grep Unattended-Upgrade

Поддръжка

32. Резервно копиране

Резервното копие е основната застраховка: загубата на данни е по-страшна от всеки пробив. Нужни са две неща — резервно копие на сървъра/сайтовете и отделно резервно копие на базата данни на панела (там са потребителите, WebAuthn ключовете, настройките, лицензията).

Вариант A — HestiaCP: раздел Backup при потребителя → бутон за създаване на резервно копие (или по график в настройките на сървъра). Резервното копие включва сайтовете и техните бази данни.

Вариант B — ръчно (cron): дъмп на базата данни + архив на каталога data/ на панела:

# root-крон (sudo crontab -e) — ежедневно резервно копие в 2:30 (заменете със своите имена/пътища): 30 2 * * * mysqldump -u root MY_DB | gzip > /var/backups/monitor-db-$(date +\%F).sql.gz 40 2 * * * tar czf /var/backups/monitor-data-$(date +\%F).tar.gz -C /path/to/monitor data # Изтриване на архиви по-стари от 14 дни: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
Резервно копие на същия сървър спасява от грешки, но не и от загуба на сървъра. Копирайте архивите във външно хранилище (друг сървър, S3, rclone в облак). Проверявайте дали възстановяването наистина работи.

33. Обновяване и мигриране на панела

Обновяване до нова версия. Първо направете резервно копие. След това презапишете файловете с код, като запазите данните си:

  • презаписване (код): public/, includes/, assets/, cron/, database/, както и главните .htaccess (фронт-контролер — маршрутизацията не бива да остава от старата версия), manifest.json, sw.js;
  • не докосвайте: config.php (данни за БД), data/ (отчети), logs/, tmp/ (сесии и кеш).
# След качването — изчистете кеша на PHP (ако opcache е включен): sudo systemctl reload php*-fpm
FileZilla съобщава SSH_FX_PERMISSION_DENIEDPermission denied. Файловете на панела принадлежат на www-data (така бяха зададени при инсталацията), а SFTP клиентът се свързва с вашия собствен потребител, който няма право на запис. Да дадете на www-data целия панел „за да работи“ е точно това, което води до тази грешка; по-долу има три начина, всеки решава проблема.
# Вариант A (препоръчителен) — разделяне на собствениците: кодът е ваш, работните папки на уеб сървъра. # Уеб сървърът изобщо не получава право на запис върху КОДА на панела: sudo chown -R deploy:www-data /path/to/monitor sudo chown -R www-data:www-data /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo find /path/to/monitor -type d -exec chmod 755 {} \; sudo find /path/to/monitor -type f -exec chmod 644 {} \; sudo chmod 750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo chmod 640 /path/to/monitor/config.php # Вариант B — ACL върху текущите собственици (нищо не преместваме): sudo apt install -y acl sudo setfacl -R -m u:deploy:rwX /path/to/monitor sudo setfacl -R -d -m u:deploy:rwX /path/to/monitor # Вариант C — през групата www-data. По-прост, но право на запис върху файловете # на панела получава и уеб сървърът (при уязвимост в PHP кодът може да се подмени): sudo usermod -aG www-data deploy sudo find /path/to/monitor -type d -exec chmod 2775 {} \; sudo find /path/to/monitor -type f -exec chmod 664 {} \; sudo chmod 640 /path/to/monitor/config.php sudo chmod 2750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs
Защо вариант A е безопасен. Панелът пише само в три каталога — data/ (отчети), tmp/ (сесии и кеш), logs/; те остават на www-data. Останалото е код, а на уеб сървъра той му трябва само за четене, което дава групата www-data с права 644. Страничен плюс: при уязвимост в PHP файловете на панела вече не могат да се презапишат. На хостинг панели (HestiaCP и подобни) вариант A не е нужен: там файловете на сайта така или иначе принадлежат на акаунта, с който влизате по SFTP, а уеб сървърът ги чете по група.
Капанът на вариант B: всеки следващ chmod върху файловете нулира ACL маската и достъпът тихо изчезва. Ако след „подреждане на правата“ качването отново опре в Permission denied — повторете двете команди setfacl.
Битът 2 във вариант C е setgid: качените по SFTP файлове остават в групата www-data, иначе панелът няма да може да ги презапише. След вариант C свържете се наново във FileZilla — новата група се прилага само при ново влизане. Проверка: id deploy (трябва да се появи групата www-data) и ls -ld /path/to/monitor (drwxrwsr-x — буквата s означава, че setgid е зададен).

Мигриране на друг сървър:

  1. На новия сървър вдигнете сайта + HTTPS (вж. страницата за ръчна инсталация).
  2. Копирайте всички файлове на панела заедно с config.php, data/.
  3. Прехвърлете БД: mysqldump на стария → импорт на новия; коригирайте данните за БД в config.php.
  4. Повторете на новия сървър: sudoers, членство в групата adm, cron-задачи.
  5. Лицензът е обвързан с домейна — ако домейнът е същият, ключът ще продължи да работи.

34. Възстановяване на достъп (изгубен ключ, парола, IP-блокировка)

Ако не можете да влезете — всичко се поправя директно в базата данни от сървъра. Отворете базата данни (името е от config.php):

sudo mysql MY_DB

Изгубен ключ WebAuthn (вторият фактор не минава) — изключете 2FA, влезте с парола, регистрирайте нов ключ:

UPDATE users SET webauthn_enabled = 0;

Забравена парола — задайте нов хеш (генерирайте го на сървъра и го поставете):

# Генериране на хеш за новата парола: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # В базата данни (поставете получения хеш): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

Блокирахте себе си с IP-филтъра — изключете ограничението:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
Достъп до базата данни има винаги: sudo mysql на сървъра или phpMyAdmin / разделът за база данни в панела на хостинга. След възстановяването включете отново WebAuthn и IP-филтъра.

35. Всички cron-задачи на едно място

Обобщението на задачите е в root-crontab на сървъра (добавят се чрез sudo crontab -e). Оставете само редовете за инструментите, които използвате; коригирайте пътищата спрямо своя сървър.

# Сървърен cron на монитора (root) — впишете чрез: sudo crontab -e # 01:30 — сканиране с ClamAV по опасни пътища (web, home, temp) → картите „Проверени файлове“ и „Последно сканиране“ 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — проверка на целостността на файловете с AIDE (нужен е явен --config) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # при старт — възстановяване на правата на /var/lib/aide (пакетният tmpfiles-файл # aide-common.conf ги връща на 0700 и панелът престава да вижда базата) @reboot chmod 755 /var/lib/aide # 03:00 — одит на сигурността с Lynis 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — обновяване на блок-списъка ipsum (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # наборът ipsum при старт се вдига от услугата ipsum-load.service (ПРЕДИ файъруола, иначе # UFW няма да види набора в before.rules) — не е cron. Тук е само ежедневното опресняване горе. # 06:00 — отчет от Logwatch 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # на всеки 30 мин — проверка на дисковете SMART */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — целостност на пакетите с debsums 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — планиран отчет на Email и Telegram 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # на всеки час — обновяване на списъците с пакети (за картата „Обновления за сигурност“) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # на всеки 5 мин — снимка на ресурсите (CPU/RAM/мрежа/диск) за страницата „Производителност“ */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Подробности за всяка — в съответните раздели. Задачите за резервни копия (предишния раздел) се добавят в същия cron. След промени проверете: sudo crontab -l и че cron-услугата е активна.
Времето на cron = часовата зона на сървъра, а не TIMEZONE от config.php. Константата TIMEZONE влияе само на PHP (как панелът показва датите), но cron-демонът стартира задачите по системното време на ОС. Ако зоната на сървъра не съвпада с вашата, отчетът „08:00“ ще дойде в друго време. Пример: сървърът е в друга зона (Europe/Berlin, UTC+2), а вие сте в София (UTC+3) → отчетът „08:00“ ще дойде в 09:00 по вашето време. Проверете и при нужда приведете системната зона към своята:
# Проверка на текущата зона на сървъра: timedatectl # Задаване на своята зона (пример) и рестарт на cron: sudo timedatectl set-timezone Europe/Sofia sudo systemctl restart cron
След това редът 0 8 * * * ще сработи в 08:00 по местно време. Иначе би трябвало да отмествате самия cron, но при преминаване към зимно/лятно време отместването пак ще се разминава — затова е по-правилно да настроите системната зона.
Готови скриптове-обвивки. Работните им копия и образец на crontab (crontab.txt) са в папката system/ до проекта, извън public_html. Това не е част от сайта — не е нужно да ги качвате в уеб-корена; разположете ги на сървъра по системните пътища (както в crontab по-горе):
  • lynis-scan.sh/usr/local/bin/ (chmod +x) — стартира lynis audit system, за времето на сканирането поставя флаг /tmp/lynis-running и копира lynis-report.dat в data/lynis/ на панела;
  • logwatch_daily.sh/usr/local/bin/ (chmod +x) — формира ежедневния отчет на Logwatch (sshd, fail2ban, sudo, postfix) в data/logwatch/;
  • smart-scan.sh/usr/local/bin/ (chmod +x) — снема състоянието на дисковете (smartctl) в data/disk/;
  • debsums-scan.sh/usr/local/bin/ (chmod +x) — проверява целостността на пакетите (debsums) в data/debsums/;
  • clamav-scan.sh/usr/local/bin/ (chmod +x) — антивирусно сканиране с ClamAV по опасни пътища (web, home, temp); записва обобщение в /var/log/clamav/scan.log, откъдето го чете страницата ClamAV (редът 01:30 в crontab по-горе);
  • load-ipsum.sh/usr/local/bin/ (chmod +x) — обновява ipset-набора ipsum (level 1) на място, без да къса действащите правила на защитната стена (редът 04:00 в crontab по-горе);
  • daily-report-all.sh/usr/local/bin/ (chmod +x) — стартира отчета cron/daily_report.php на панела (редът 08:00 в crontab по-горе);
  • daily_report.php — вече е включен в панела (cron/daily_report.php), стартира се чрез daily-report-all.sh, не е нужно да се поставя отделно;
  • collect-metrics-all.sh/usr/local/bin/ (chmod +x) — стартира cron/collect_metrics.php на панела (страницата „Производителност“, редът */5 в crontab по-горе); collect_metrics.php вече е включен в панела, не е нужно да се поставя отделно;
  • crontab.txt (system/cron/) — образец на задачите; впишете нужните редове чрез sudo crontab -e.
Пътят до скрипта в crontab трябва да съвпада с това, където сте го поставили.
Как да поставите скрипт в /usr/local/bin/. Директно от FileZilla там не може да се запише — каталогът принадлежи на root и SFTP-клиентът ще получи SSH_FX_PERMISSION_DENIED. Редът е такъв: първо качете файла в /tmp (там пишат всички), после го преместете на място с една команда:
# във FileZilla: в полето „Отдалечен сайт“ въведете /tmp и качете там скрипта, # после по SSH (install веднага задава собственика и правата, chown/chmod не са нужни): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # проверка: файлът е на място, права rwxr-xr-x, синтаксисът е цял bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
Не бъркайте каталозите: нужен е /tmp в корена на сървъра — не /var/tmp и не tmp/ вътре в самия панел (последният принадлежи на www-data и е затворен за вашия потребител). В дървото на FileZilla /tmp е клон от най-горно ниво, до var, а не вътре в него.
Инсталирахте сървъра с автонастройка? Тези обвивки и техните cron-задачи вече са инсталирани от скрипта (в /usr/local/bin/, лог — /var/log/arciveo-cron.log) — не е нужно да правите нищо ръчно.
Къде скриптовете търсят панела. Обвивките са домейн-неутрални: намират инсталациите на панела, обхождайки /home/*/web/*/public_html и /var/www/*, и слагат отчетите в техния data/. Ако панелът е по друг път — добавете го в реда for app in … вътре в скриптовете, иначе отчетите на Lynis/SMART/debsums/Logwatch няма да попаднат в панела.
cron.log и права за достъп. Файлът logs/cron.log се създава пръв от root-cron — той ще принадлежи на root и разделът „Журнал на cron“ в панела няма да може нито да го чете, нито да го изчиства. Създайте файла предварително от името на уеб-потребителя (собственик на каталога на сайта; при HestiaCP това е акаунт, напр. admin) — тогава root-cron само ще дописва, без да сменя собственика:
# създай предварително от уеб-потребителя (преди добавяне на cron-редове): sudo -u OWNER touch /path/to/monitor/logs/cron.log # ако cron.log вече е създаден от root-cron — дай го на уеб-потребителя: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
За да разберете собственика на каталога: stat -c %U /path/to/monitor.
Управление от панела. В раздел „Система“ има страница „Crontab“ — задачите могат да се преглеждат и добавят без SSH. Панелът редактира само задачите, добавени чрез него (отделен блок в root-crontab, отбелязан със служебни коментари); всичко, което вече е в crontab (списъка по-горе), се показва там като read-only списък „Други задачи на сървъра“ с бутон „Копирай в редактора“ — той само пренася разписанието/командата във формата за добавяне, без да пипа изходния ред. За да „преведете“ съществуваща задача под управление на панела — копирайте я в редактора, запазете, после изтрийте стария ред ръчно (sudo crontab -e), иначе тя ще се изпълнява два пъти.
Еднократна настройка на сървъра. Страницата се нуждае от привилегирован скрипт-обвивка — не гол sudo crontab (това би било пряка ескалация до root от всеки, който получи достъп до сесията на панела), а тесен скрипт с две команди (list/set), който пипа само своя блок между служебните коментари. Инсталирайте веднъж:
sudo install -m 0755 -o root -g root /dev/stdin /usr/local/sbin/arciveo-cron <<'ARCIVEO_CRON_EOF' #!/bin/bash set -euo pipefail BEGIN='# >>> ARCIVEO-CRON-MANAGED (edited from the panel; do not edit by hand) >>>' END='# <<< ARCIVEO-CRON-MANAGED <<<' cmd=${1:-} case "$cmd" in list) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} list" >&2; exit 2; } crontab -l -u root 2>/dev/null || true ;; set) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} set (body on stdin)" >&2; exit 2; } body=$(cat) if grep -qF "$BEGIN" <<<"$body" || grep -qF "$END" <<<"$body"; then echo "invalid body: markers not allowed" >&2; exit 2 fi current=$(crontab -l -u root 2>/dev/null || true) tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT { if grep -qF "$BEGIN" <<<"$current"; then awk -v b="$BEGIN" '{print} $0==b{exit}' <<<"$current" else [ -n "$current" ] && printf '%s\n' "$current" echo "$BEGIN" fi printf '%s\n' "$body" echo "$END" if grep -qF "$END" <<<"$current"; then awk -v e="$END" 'f{print} $0==e{f=1}' <<<"$current" fi } > "$tmp" crontab -u root "$tmp" ;; *) echo "usage: ${0##*/} <list|set>" >&2; exit 2 ;; esac ARCIVEO_CRON_EOF echo "www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/arciveo-cron" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c
Уеб-потребителят може да се различава от www-data — проверете под кого работи PHP-FPM пулът на сайта (ps -o user= -C php-fpm) и го поставете в sudoers-реда.
Новият файл е качен с грешен собственик — страницата отговаря „Access denied.“. Ако файлът public/crontab_monitor.php е качен по FTP/SFTP под друг системен потребител (например root), различен от останалите файлове на сайта, уеб-сървърът няма да може да го прочете. Сверете собственика и правата със съседен файл и ги приведете в съответствие:
ls -la public/crontab_monitor.php public/ssl_monitor.php sudo chown OWNER:OWNER public/crontab_monitor.php sudo chmod 644 public/crontab_monitor.php

Диагностика

36. Инструментът е инсталиран, но се показва „Не е инсталиран“

Мониторът разпознава наличието на инструменти чрез dpkg-query — базата с пакети на APT. Ако инструментът е инсталиран не чрез apt (ръчно, от snap или от изходен код), dpkg не го вижда.

# Проверка чрез dpkg: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # Намиране на пътя до binary файла: which ufw fail2ban-client auditctl # Тест на sudo от www-data: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

37. Отстраняване на проблеми (500, липсват данни)

Грешка 500 — проверете логовете на PHP, nginx и на самия монитор:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # Логове на монитора: tail -50 logs/monitor_$(date +%Y-%m-%d).log # Права на папките: ls -la data/ tmp/ logs/
Панелът е на хостинг панел (HestiaCP, ISPmanager, cPanel)? Там PHP не работи под www-data, а под потребителския акаунт (например admin — собственик на директорията на сайта). Всички sudo правила и членства в групи (adm, systemd-journal) трябва да се зададат за този потребител, иначе модулите ще покажат „Неактивен / 0“ при работещи услуги. Как да разберете реалния потребител на PHP: ps -o user= -C php-fpm | sort -u или собственика на директорията на сайта stat -c '%U' /path/to/monitor. По-нататък във всички команди по-долу поставяйте него вместо www-data. Автоматичната инсталация сама определя уеб потребителя и записва sudoers за него.

Данните не се показват — почти винаги са незададени sudo права. Проверете конкретната команда от името на уеб потребителя (заменете www-data със своя). Флагът -n = без парола, както при PHP — ако иска парола, значи правилото го няма в sudoers:

sudo -u www-data sudo -n fail2ban-client status sudo -u www-data sudo -n ufw status verbose sudo -u www-data sudo -n ipset list -t ipsum sudo -u www-data sudo -n /usr/sbin/ausearch -m USER_LOGIN -ts today sudo -u www-data sudo -n /usr/sbin/aa-status sudo -u www-data sudo -n /usr/sbin/psad --Status sudo -u www-data journalctl -u falco --no-pager -n 5
Модулът показва „Неактивен“ / „0“, макар инструментът да работи (например sudo aa-status в терминала показва профили, а страницата „AppArmor“ — „Неактивен“). Причина: уеб потребителят няма sudo право за командата на този модул. Проверете я от списъка по-горе: ако иска парола — добавете липсващия ред в /etc/sudoers.d/monitor („Настройка на sudo“). Чести „нови“ команди: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
Ако конкретна страница (Falco, ModSecurity, Auditd, отворени портове на UFW) е празна — сверете със списъка в раздела за sudo: вероятно не е разрешен apache2ctl, ausearch, aa-status или ss, или уеб потребителят не е в групите adm/systemd-journal (оттам се четат логовете на fail2ban/auth/modsec и journalctl — Falco и събитията на ядрото).

38. Страницата е празна, макар че на сървъра има данни

Симптом: на сървъра има данни (виждат се през shell), а страницата показва „няма данни“ или грешен статус — например AIDE изписва „Не е инициализирана“, макар че базата е създадена.

Причината е open_basedir: много панели и хостинги ограничават пула PHP-FPM до каталога на домейна, затова PHP-функциите file_exists(), file_get_contents(), filemtime() се блокират по системните пътища (/var/lib/aide, /var/log, /proc…). Мониторът заобикаля това, като чете тези пътища със стандартни системни команди (cat, test, stat).

# Вижда ли се файлът през shell (така чете мониторът): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # Текуща стойност на open_basedir за пула на домейна: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
Ако shell „вижда“ файла (VISIBLE), а страницата — не, това е open_basedir. Правилното решение е четене със системни команди (вече е реализирано за AIDE и Мрежовия монитор). Разширяването на open_basedir върху /var, /proc не е нужно и е по-малко сигурно.

39. SSL страницата не работи

Мониторът проверява сертификатите, като се свързва с домейните директно през порт 443. Ако домейнът е недостъпен от самия сървър или портът е затворен от защитната стена — проверката няма да премине.

# Ръчна проверка на сертификата: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # Проверка на достъпността: curl -I https://monitor.example.com
Мониторът взема домейните автоматично от конфигурациите на nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) и Apache (/etc/apache2/sites-enabled/) плюс текущия хост от HTTP_HOST.
Автоматично откриване на поддомейни. Поддомейните се откриват автоматично от публичните логове на Certificate Transparency и се проверяват по мрежата — дори ако са разположени на други сървъри. Не е нужно да добавяте нищо ръчно.

40. Вижда се само една БД от няколко

Мониторът се свързва с MySQL с потребителя от config.php, който има достъп само до своята база. MySQL показва в information_schema само базите с привилегии — затова останалите не се виждат.

За да вижда мониторът всички БД, дайте на този потребител само право за четене (еднократно от root; заменете с потребителското име от config.php):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* дава само право за четене — не може да се променя, изтрива или създава нищо, което е безопасно за наблюдение.
Без този GRANT панелът вижда само своята база — това не е грешка, а ограничение на правата. Панелът не използва никакъв sudo mysql: списъкът с базите се взима през собствената ѝ PDO връзка.

41. PostgreSQL не се показва на страницата „База данни“

PostgreSQL изисква достъп на ниво потребител postgres, какъвто уеб потребителят на панела няма. Отварянето на широк sudo psql от PHP е несигурно — вместо това панелът извиква тясна обвивка без параметри, която само отпечатва версията, броя връзки и списъка с бази с техните размери. Създайте я:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Monitor - read-only PostgreSQL version, connections and per-database size sudo -u postgres psql -tAc "SELECT version();" | grep -oE 'PostgreSQL [0-9.]+' echo "---" sudo -u postgres psql -tAc "SELECT count(*) FROM pg_stat_activity;" echo "---" sudo -u postgres psql -tAc "SELECT datname || '|' || pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;" EOF sudo chown root:root /usr/local/bin/monitor-pgstat sudo chmod 755 /usr/local/bin/monitor-pgstat # в /etc/sudoers.d/monitor (потребител = този, под който работи PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
Ако не използвате PostgreSQL — премахнете реда monitor-pgstat от sudoers (стъпка 13 от ръчната инсталация) и не създавайте самия скрипт: картата на PostgreSQL просто ще остане неактивна.

42. Задейства се известие — какво да правя

Панелът показва какво се случва; по-долу е какво да правите в типични ситуации. Общ принцип: не се паникьосвайте, сверете с легитимната активност (вашите действия, обновявания, резервни копия) и реагирайте според сериозността.

  • Карта на атаките / много банове от fail2ban — това е нормално за всеки сървър в интернет (ботове постоянно опитват SSH/уеб). Важното е бановете да се задействат. Уверете се, че влизането по SSH е само с ключ (паролата е изключена) и че вашият IP е в ignoreip.
  • ModSecurity блокира заявки — WAF отбива атаки срещу сайта, това му е работата. Ако блокира ваш легитимен трафик (фалшиво задействане) — намерете rule id в детайлите и добавете изключение в конфигурацията на CRS.
  • AIDE: променени файлове — сверете списъка с това, което сте правили (обновяване на пакети, редакция на конфигурации — нормално). Промени по системни двоични файлове, които не сте пипали — повод за тревога. След легитимни промени обновете базата на AIDE.
  • debsums: променени двоични файлове/библиотеки (извън /etc, извън /usr/share) — потенциална подмяна. Сверете пакета: debsums PACKAGE_NAME, при съмнение го преинсталирайте (apt install --reinstall).
  • ClamAV / maldet: открита заплаха — проверете файла в карантина, не го отваряйте. Ако е уеб шел в директорията на сайта — изолирайте сървъра и търсете входната точка (уязвим плъгин, изтичане на достъпи).
  • Falco: критични събития (стартиране на shell в контейнер, достъп до чувствителни файлове) — анализирайте събитието: чий процес, какво го е стартирало. Често това е легитимна администраторска активност.
  • Външна експозиция: червено при СУБД/кеш — затворете незабавно: привържете услугата към 127.0.0.1 или затворете порта в UFW. Това е реална дупка.
  • SSL изтича / е изтекъл — подновете сертификата (Let's Encrypt се подновява сам; ако не — проверете certbot renew или настройките в панела).
  • Чакат обновявания за сигурност — инсталирайте: sudo apt update && sudo apt upgrade; след обновяване на ядрото рестартирайте сървъра.
Признаци за реален пробив (непознати процеси/потребители, променени двоични файлове, изходящ спам, непознати cron задачи): изключете сървъра от външен достъп, направете резервно копие за анализ и, ако данните са критични, вдигнете чист сървър от доверено резервно копие — надеждното изчистване на руткит е трудно.
Arcivéo - Security Monitor © 2026