FAQ

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

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

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

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

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

Преглед

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

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

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

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

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

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

Два ритъма на работа. Страниците на панела питат инструментите в момента на отваряне — винаги виждате текущото състояние. Освен това по разписание (cron) работят фонови задачи:

  • на всеки 5 минути — моментна снимка на натоварването за страницата „Производителност“;
  • на всеки 5 минути — сензорът за събития по сигурността: нови блокировки, сработвания на IDS, спряла защита, отворен порт (раздел „Събития по сигурността“);
  • веднъж дневно — докладът за сигурността в Telegram и по имейл, както и тежките проверки (Lynis, AIDE, ClamAV, debsums, Logwatch);
  • на всеки 15 минути — обзорът на сървъра към личния профил, ако е включен.

Пълният списък със задачи е в раздела „Всички cron-задачи на едно място“.

За няколко сървъра инсталирайте монитора на всеки поотделно, със собствен домейн. За да ги виждате в един списък, включете обзора на сървърите (раздел „Обзор на сървърите в личния профил“).

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
  • Включен е вход с парола по SSH (PasswordAuthentication yes) — −10
  • Дребни настройки на SSH: включен X11Forwarding, MaxAuthTries над 3 или файлът sshd_config може да се чете от всички акаунти — −5
  • Защита на уеб сървъра: в отговорите се вижда версията на уеб сървъра или PHP, методът TRACE е включен или липсва заглавката Strict-Transport-Security или X-Frame-Options — −5
  • Има чакащи 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, имейл, webhook и push

Каналите са четири: Telegram, имейл, webhook и push в браузъра. Те са независими — включете които пожелаете, дори и четирите. По същите канали вървят ежедневният доклад за сигурността, известията за натоварване и находките на сензора за събития; настройват се веднъж, тук, в раздел „Настройки“.

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_...) и потвърден домейн на подателя.

Webhook. Един-единствен адрес, който приема POST, покрива Slack, Discord, Mattermost, n8n и собствен обработчик. „Настройки“ → Webhook: поставете адреса и включете превключвателя.

  • към Slack и Mattermost се изпраща {"text": …}, към Discord — {"content": …} (Discord отхвърля съобщения над 2000 знака, затова текстът се съкращава);
  • всеки друг адрес получава структуриран JSON: text, event, severity, source, count, host, ts — не е нужно текстът на съобщението да се разбира отново.

Push известия. Съобщението пристига направо в браузъра, а ако панелът е добавен към началния екран на телефона — като обикновено известие на приложение, без бот и без пощенски сървър по средата. „Настройки“ → Push известия: включете превключвателя и натиснете „Свържи това устройство“ на всяко устройство, което трябва да получава известия. Броячът „Свързани устройства“ показва колко са.

Push работи само през HTTPS (както и WebAuthn), а разрешението е нужно два пъти: първо в браузъра — запитването се появява след бутона „Свържи това устройство“ — и след това в самата операционна система. Ако в Windows е изключен главният превключвател Настройки → Система → Известия, браузърът ще даде разрешение, панелът ще отчете изпращането, а на екрана няма да се появи нищо. Същото правят режимът „Не безпокойте“ и изключените известия на браузъра в macOS (Системни настройки → Известия).
Всеки канал има собствен бутон „Изпрати тест“, който го проверява веднага. Разписанието на автоматичния доклад минава през cron (раздел „Всички 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. API само за четене (JSON и Prometheus)

Панелът е защитен с вход по парола и, ако е включен, с IP филтър. На програма това не върши работа, затова за външните системи има отделен вход — два адреса само за четене, защитени с токен. Токенът не променя нищо на сървъра: с него могат само да се получат показатели.

Включване — „Настройки“ → „API само за четене“: превключвателят „Включване на API“; токенът се създава автоматично при първото записване. Бутонът „Нов токен“ издава друг и в същия момент изключва всички, които са ползвали предишния.

  • /api/status.php — JSON: оценка за сигурност, състояние на модулите, последното измерване на натоварването с топ процесите и събитията по сигурността за 24 часа;
  • /api/metrics.php — същите числа в текстовия формат на Prometheus (метрики arciveo_*: arciveo_security_score, arciveo_fail2ban_banned, arciveo_cpu_busy_pct и т.н.).
curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/status.php curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/metrics.php

Ако клиентът не може да поставя заглавка, токенът се приема и като параметър — ?token=…. Имайте предвид, че в този вид той попада в журнала за достъп на уеб сървъра, затова заглавката е за предпочитане.

Prometheus. Готов блок за scrape_configs:

scrape_configs: - job_name: arciveo metrics_path: /api/metrics.php scheme: https authorization: credentials: <TOKEN> static_configs: - targets: ['monitor.example.com']
Отговорът се кешира за 5 минути: зад тези числа стои същото тежко събиране на данни, което стои и зад таблото. Честото запитване не струва нищо на сървъра — стойностите просто се повтарят до следващото обновяване — но и интервал под минута няма смисъл.
401 — токенът е грешен или не е подаден. 404 с текст api disabled — API е изключено в настройките. Отхвърлените заявки се записват в журнала на приложението заедно с IP на подателя, така че опитите за налучкване на токена се виждат на страницата „Логове на приложението“.

10. Обзор на сървърите в личния профил

Панелът се инсталира на всеки сървър поотделно и отговаря добре на въпроса „как е тази машина“. На въпроса „как са всички мои машини“ той не отговаря — затова всеки панел може да изпраща кратък обзор към личния профил, където сървърите се виждат в един списък.

Какво да вземете в личния профил my.arciveo.com → раздел „Моите сървъри“: там се издава токен (от вида fk_…) и е посочен адресът на получателя https://my.arciveo.com/api/fleet.php. Токенът е един за целия акаунт — еднакъв за всички ваши сървъри.

Какво да настроите в панела — „Настройки“ → „Обзор на сървърите“: адрес на получателя, токен, име на сървъра (както ще бъде подписан в списъка; ако го оставите празно, се взема домейнът на панела) и превключвателят „Изпращане на обзора“. Бутонът „Изпрати сега“ проверява връзката веднага, без да чака разписанието.

След това обзорът тръгва по cron, на всеки 15 минути:

# на всеки 15 минути — обзор на сървъра към личния профил 3,18,33,48 * * * * /usr/local/bin/fleet-push-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Какво точно се изпраща: име и домейн на сървъра, ОС, време на работа, версия на PHP; оценката за сигурност; състоянието на модулите (UFW, брой jail-ове на Fail2ban, блокировки за днес, дали работят CrowdSec, Suricata и Falco, заплахи от ClamAV, промени по AIDE, индекс на Lynis, чакащи обновявания, дали е нужен рестарт, дни до изтичане на SSL, брой опасни отворени портове); последното измерване на натоварването (load, CPU, RAM, диск, inodes); броячите на събития за 24 часа и последното критично събитие. В обзора няма журнали, пароли или съдържание на файлове.

Изпраща сървърът, а личният профил не пита. Затова към вашата мрежа не е нужно да се отваря вход отвън, а панел, затворен с IP филтър, също се отчита. Възелът се разпознава по домейна на панела, така че списъкът не се удвоява след рестарт или смяна на IP.
Сървър, отбелязан в профила като мълчащ, означава, че обзорът отдавна не е идвал. Проверете по ред: превключвателя „Изпращане на обзора“, реда в cron (sudo crontab -l) и какво отговаря бутонът „Изпрати сега“. Грешките при изпращане се записват в журнала на приложението с етикет FLEET — там се вижда дали токенът е отхвърлен (HTTP 401), или самата връзка не е осъществена.

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

11. Защитна стена 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 съобщава, че точно такова правило вече съществува и не го добавя повторно. При повторно стартиране на автоматичната настройка (тя е идемпотентна) това е нормално съобщение — не е нужно да реагирате.

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

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

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

13. Работеща конфигурация 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 са само истинските рецидивисти, а превантивното е изцяло на защитната стена.

14. Блоклист 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 е по-горе). При автоматична инсталация не е нужно да правите нищо ръчно.

15. Инсталиране на 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.

16. Инсталиране на 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.

17. Инсталиране на 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.

18. Инсталиране на 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 — вижте раздела „Страницата е празна, макар данните на сървъра да ги има“.

19. Инсталиране на 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
Автоматичното инсталиране прави това само — ръчно не е нужно.

20. Инсталиране на 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 (логът се чете от уеб сървъра). При нова инсталация не е нужно да настройвате това ръчно.

21. Инсталиране на 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 и ги добавете в списъка. Ако обвивката е стара (без тази секция) — разделът просто ще покаже предупреждение „недостъпно“, останалата част от страницата работи както преди.

22. Инсталиране на 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.

23. Инсталиране на 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

24. Инсталиране на 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 страницата ще е празна — това е нормално, докато няма извършени сканирания.

25. 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 са друго нещо: там правилата вече са написани, само че не се прилагат.

26. Инсталиране на 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 и т.н.) — картата „Бинарни файлове / библиотеки“ показва именно тях.

27. Настройка на отчетите на 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

28. Настройка на отчетите на 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

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

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

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

  • интерфейси и трафик — от /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“ и „Карта на атаките“. Празен блок със зелена отметка = за денонощието не е имало мрежови сривове.

30. Диск и 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“, а температурата, часовете на работа и преразпределените сектори може да са празни — това е нормално. На физически сървър се показват всички атрибути.

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

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

Данните се събират от 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.

Две дълбочини на съхранение. „Суровите“ петминутни снимки живеят едно денонощие (плюс час резерв, за да има най-старата точка на графиката предшественик за изчислението). Всеки завършил час се сгъва в един ред; този почасов ред се пази 30 дни и точно него четат изгледите „7 дни“ и „30 дни“. Така един месец история струва около 720 реда вместо приблизително 8600.

На периодите 7 и 30 дни са показани средни стойности по часове, а не отделни измервания — кратък скок от пет минути в този мащаб се изглажда и страницата предупреждава за това. За Load Average почасовият ред пази и средното, и пика за часа, затова графиката показва двете линии. Веднага след обновяване дългите периоди са празни („за този период още няма история“) — почасовият ред започва да се натрупва от този момент.
# 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 минути след инсталацията), страницата показва „данните се събират“ — на графиките е нужна поне една двойка съседни точки, за да се изчислят скоростите и процентите.

Топ процеси. Под графиките има две таблици с петте най-натоварващи процесора процеса:

  • „Процеси при последното измерване“ — какво натоварваше сървъра в момента на последната снимка (часът е в заглавието на картата);
  • „Процеси при пика за денонощието“ — същите пет, но взети при измерването с най-високия Load Average за последните 24 часа. Това е отговорът на въпроса „какво беше това през нощта“, когато пикът на графиката отдавна е отминал.

И двете таблици винаги описват последните 24 часа, дори когато графиките показват месец: снимка на процесите имат само петминутните редове, а те не се пазят по-дълго от денонощие.

Собствените процеси на измерването (ps, PHP скриптът за събиране и веригата cron/sudo над него) се изключват от списъка — иначе биха заемали първите редове във всяка снимка: ps в момента на стартиране показва почти 100 % CPU. Другите cron-задачи, стартирали в същата минута, се появяват — точно за това е таблицата.

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

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

32. Събития по сигурността (сензор на всеки 5 минути)

Ежедневният доклад отговаря на въпроса „как е сървърът“. Сензорът отговаря на друг — „какво се случи току-що“. На всеки 5 минути той пита бързите източници и записва само това, което се е променило от предишната проверка; страницата „Събития по сигурността“ в менюто показва списъка с находки.

Бавните проверки — Lynis, debsums, обновявания на пакети, срок на SSL — сензорът не пипа: техните числа така или иначе се променят веднъж дневно и остават работа на ежедневния доклад.

Какво забелязва — девет източника:

  • Fail2ban — нови блокировки (сравнява се списъкът с блокирани адреси, така че разблокирането не е събитие, а действаща блокировка се съобщава точно веднъж);
  • CrowdSec — нови решения;
  • Falco — събития от ниво Emergency, Alert и Critical;
  • Suricata — нови сработвания; отбелязването [Priority: 1] вдига находката до критична;
  • ClamAV — нови редове FOUND в журнала на сканирането;
  • AIDE — промени по файловете според последната проверка (тоест не по-често, отколкото тя се изпълнява по собственото си разписание);
  • SSH — успешно влизане като root (критично) и влизане от адрес, който не е срещан преди (предупреждение);
  • Услуги за защита — UFW, Fail2ban, CrowdSec, Suricata, Falco: едно съобщение, когато услуга спре, и едно, когато отново заработи;
  • Портове — порт, който е станал достъпен отвън; ако зад него стои база данни или кеш — критично.

Инструмент, който не е инсталиран или чийто журнал панелът не може да чете, просто мълчи — това не е грешка и не е събитие.

Първата проверка не изпраща нищо. Всеки източник пази отметка „докъде вече е прочетено“ (файл data/secwatch_state.json), а първото минаване само записва тази отметка. Иначе при включване на наблюдението би дошло известие за всичко, което журналите са натрупали с месеци.

Настройка — „Настройки“ → „Наблюдение на събития“:

  • Включване на наблюдението — докато е изключено, cron-задачата работи напразно и списъкът не се пълни;
  • Известяване от — „Предупреждение“ или „Критично“. Находките под прага пак попадат в списъка, но не и в известията;
  • Пауза, мин — минимум между известията, по подразбиране 15;
  • Тихи часове — прозорец във формат 23-7, в който предупрежденията не се изпращат.
Критичните находки тръгват веднага — не ги задържат нито паузата, нито тихите часове: точно заради тях съществува сензор на 5 минути. Предпазител все пак има: не повече от 6 известия на час — за случай, че някой източник започне да „мига“.

Известията вървят по същите канали като ежедневния доклад (Telegram, имейл, webhook, push) — не е нужно да се включва нищо отделно. Всички находки се записват в списъка независимо от това дали е изпратено известие, и се пазят 90 дни.

Списъкът със събития. Филтри: период (24 часа, 7, 30 или 90 дни), важност и източник; показват се последните 500 записа. Бутонът „Провери сега“ стартира точно същата проверка като cron — удобно веднага след настройката, за да не се чака пет минути; той посочва и причината, когато известие не е изпратено („под прага на важност“, „тихи часове“, „не е настроен нито един канал за известия“). Червеният брояч до елемента от менюто е броят критични събития за последните 24 часа.

Карта на адреса. Щракване върху ред в списъка със събития или в блока Свързани адреси отваря всичко, което се знае за един адрес: хронологията на събитията му, държавата и на първия ред заключението. Ред от списъка отваря картата, когато събитието се отнася точно за един адрес; ако адресите са няколко, връзките са самите адреси в реда. Заключенията са четири:

  • Възможен достъп — от адреса е имало успешен вход и същият адрес е бил засечен от други защити, или веднага след входа са се задействали AIDE, ClamAV или е отворен нов порт. Единственият случай, който си струва да проверите веднага;
  • Вход от този адрес — има вход и нищо друго. Обикновено това е собственикът от ново място, затова картата не се оцветява в червено;
  • Блокиран — адресът е засечен и блокиран: защитата е свършила работата си, няма какво да се прави;
  • Изисква проверка — има задействания, но няма блокиране. Ако адресът се връща, затворете го ръчно.

Под хронологията е блокът Какво се е случвало на сървъра по същото време: събития, които изобщо нямат адрес. AIDE не знае кой е променил файла, ClamAV не знае кой е донесъл заразения. Показани са тези, които попадат в активността на адреса и шестте часа след нея. Именно връзката между входа и това, което последва, отличава опита от осъществен достъп.

Връзката се гради по адрес. Нападател, който сменя адреса си, я прекъсва. Картата показва това, което са видели защитите, и не се наема да различи пробив от вашия собствен вход от ново място.

Разписание. Задачата се добавя в root-crontab (sudo crontab -e), изместена с 2 минути спрямо събирането на метрики, за да не стартират двете едновременно:

# на всеки 5 минути — проверка на събитията по сигурността 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Стартирайте проверката само през обвивката, никога направо с php cron/security_watch.php. Обвивката намира всички инсталации на панела на сървъра и стартира проверката от името на собственика на сайта — със същите права sudo, които панелът използва от уеб. Пряко извикване от root-crontab би създало файла на състоянието data/secwatch_state.json със собственик root и бутонът „Провери сега“ би спрял да работи.
Ако сървърът е подготвен с автоматичната инсталация, задачата вече е добавена — остава само да включите наблюдението в настройките.

33. Уеб сървър: заявки и кодове на отговор

Страницата „Уеб сървър“ разбира журнала за достъп и показва колко заявки е имало, каква част от тях е завършила с грешка и кой ги е правил. ModSecurity отговаря на въпроса „какво е блокирано“, тази страница — на въпроса „какво изобщо е стигало до сайта“.

Какво се вижда: брой заявки, RPS, дял на грешките, отделен брояч 5xx и обемът отдаден трафик; графика на заявките по часове; разпределение на кодовете 2xx/3xx/4xx/5xx; чести адреси, чести IP, чести грешки (код плюс път) и клиенти (User-Agent). Период: 24 часа или 7 дни.

Източникът е журналът за достъп във формат combined, затова стават и Nginx, и Apache, и не е нужен допълнителен модул. Панелът търси журнала сред стандартните файлове:

  • /var/log/nginx/access.log
  • /var/log/apache2/access.log
  • /var/log/apache2/other_vhosts_access.log
  • /var/log/httpd/access_log

Освен тях панелът проверява файловете *access*.log и *requests*.log в директориите /var/log/nginx/, /var/log/apache2/ и /var/log/httpd/. Така се намира и журналът, който сайтът записва в собствен файл с директивата CustomLog — например arciveo-monitor_requests.log, който създава инсталаторът на Arcivéo.

Чете се само един журнал: когато Nginx стои пред Apache, събирането на два журнала би преброило всяка заявка два пъти. Взема се първият журнал от списъка по-горе, в който е писано през последното денонощие (намерените по маска се проверяват след него, от най-новите към по-старите); ако през денонощието не е писано в нито един — най-новият непразен. Затова журнал, изпразнен от logrotate или останал от спрян уеб сървър, не закрива работещия. Чете се последният фрагмент от журнала (3 MB), а резултатът се кешира за 5 минути — затова на натоварен сайт избраният период може да не е покрит изцяло; действителният обхват е изписан над графиката.

„Панелът не може да чете журнала на уеб сървъра“. Причината почти винаги са правата: журналите и директорията им принадлежат на групата adm, а уеб потребителят не е в нея. Инсталаторът на Arcivéo го добавя в тази група; след ръчна инсталация помага малка обвивка от root, на която е позволено точно едно нещо — да покаже журнала (страницата за ModSecurity работи по същия начин). Обвивката избира журнала по същите правила като панела. Командата се извежда на самата страница; ето я и тук. Поставете я цялата — това е една команда:
sudo tee /usr/local/bin/monitor-weblog >/dev/null <<'EOF' && sudo chmod 755 /usr/local/bin/monitor-weblog && echo 'www-data ALL=(root) NOPASSWD: /usr/local/bin/monitor-weblog' | sudo tee /etc/sudoers.d/monitor-weblog >/dev/null && sudo visudo -c #!/bin/sh L="/var/log/nginx/access.log /var/log/apache2/access.log /var/log/apache2/other_vhosts_access.log /var/log/httpd/access_log $(ls -t /var/log/nginx/*access*.log /var/log/apache2/*access*.log /var/log/apache2/*requests*.log /var/log/httpd/*access_log 2>/dev/null)" for f in $L; do [ -r "$f" ] && [ -n "$(find "$f" -size +0 -mmin -1440 2>/dev/null)" ] && exec tail -c 3000000 "$f"; done for f in $(ls -t $L 2>/dev/null); do [ -r "$f" ] && [ -s "$f" ] && exec tail -c 3000000 "$f"; done EOF

Уеб потребителят може да е различен от www-data — проверете под кого работи PHP-FPM пулът на сайта (ps -o user= -C php-fpm) и го поставете в реда за sudoers. Ако в името на журнала няма нито access, нито requests, добавете пътя му в началото на реда L=… вътре в обвивката.

„За избрания период няма записи“ — журналът е прочетен, но подходящи редове не са намерени: или сайтът наистина не е отварян, или журналът току-що се е завъртял (logrotate) и започва отначало.

Опити за известни уязвимости. Панелът сравнява заявките от журнала със сигнатурите на около двадесет разпространени експлойта: PHP-CGI, обхождане на директории в Apache, PHPUnit, Log4Shell, уязвимости на рутери, камери и VPN шлюзове. За всеки опит отговаря дали може да сработи на този сървър и се опира на факти: инсталираните версии на Apache и PHP, наличието на Java и кода, с който сървърът е отговорил на заявката за файла. В червено е отбелязано само това, което наистина може да сработи.

Защита на уеб сървъра. Панелът изпраща заявка към всеки сайт на сървъра през 127.0.0.1 и проверява какво получава посетителят: виждат ли се версиите на уеб сървъра и PHP, включен ли е методът TRACE и има ли защитни заглавки Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy и Content-Security-Policy. Сайтовете се вземат от адреса, на който е отворен панелът, и от файловете на виртуалните хостове, ако панелът може да ги прочете. Резултатът се обновява на всеки 10 минути.

Ако нещо липсва, под таблицата се появява една команда. Тя създава отделен файл zz-arciveo-hardening.conf и презарежда уеб сървъра само след успешна проверка на конфигурацията; заглавките, които сайтът вече изпраща сам, не се дублират. CSP не се предлага като един ред: политиката се изгражда за конкретния сайт, иначе той спира да зарежда собствените си скриптове, стилове и шрифтове. Отменяне на промяната при Apache:

sudo a2disconf zz-arciveo-hardening && sudo systemctl reload apache2
Подписът на страниците за грешки (ServerSignature) не се отбелязва, ако версията на уеб сървъра вече е скрита: без версия той показва само името на сървъра и името на хоста.

34. Карта на атаките (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) се зарежда в браузъра — нужен е интернет на компютъра, на който е отворен панелът.

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

Две вградени карти в таблото, които показват не „вкл./изкл.“ на даден инструмент, а реалната защитеност на сървъра. Не изискват настройка, четат се локално без 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

Поддръжка

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

Резервното копие е основната застраховка: загубата на данни е по-страшна от всеки пробив. Нужни са две неща — резервно копие на сървъра/сайтовете и отделно резервно копие на базата данни на панела (там са потребителите, 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 в облак). Проверявайте дали възстановяването наистина работи.

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

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

  • презаписване (код): 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_DENIED — Permission 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. Лицензът е обвързан с домейна — ако домейнът е същият, ключът ще продължи да работи.

38. Втори сайт на този сървър (още един домейн)

Панелът вече работи, а на същия сървър е нужен още един сайт — със собствен домейн до монитора. След автоматичната настройка сървърът е обикновен Apache + PHP-FPM, затова на сайта са нужни три неща: собствена директория, собствен vhost и собствен сертификат. Панелът не се пипа: той наблюдава целия сървър, втори екземпляр за втория домейн не е нужен.

Този раздел е за сървър без хостинг панел. Ако е инсталиран HestiaCP или подобен панел, добавете домейна в него, а не ръчно. А ако планирате много сайтове (при това с поща), инсталирайте панела преди автоматичната настройка: скриптът го разпознава и минава в добавящ режим, докато панел, инсталиран по-късно, преизгражда конфигурацията на Apache, защитната стена и пощата.
Какво да замените в командите. site2.example.com е адресът на новия сайт. Може да бъде както отделен домейн (mycompany.com), така и поддомейн (shop.mycompany.com) — за Apache няма разлика, различават се само DNS записът (стъпка 1) и издаването на сертификата (стъпка 5). site2 е просто кратко име на сайта: така се казват директорията /var/www/site2 и конфигурационният файл site2.conf. С домейна няма нищо общо, Apache взема адреса единствено от ServerName; името може да е произволно — за shop.mycompany.com например е удобно shop: директория /var/www/shop, конфигурация shop.conf.

1. DNS. В DNS панела при регистратора на домейна създайте A запис към IP на този сървър:

# Поддомейн (shop.mycompany.com): Тип: A Име: shop Стойност: 203.0.113.10 TTL: 3600 # Отделен домейн (mycompany.com) — два записа, за да работи и адресът с www: Тип: A Име: @ Стойност: 203.0.113.10 TTL: 3600 Тип: A Име: www Стойност: 203.0.113.10 TTL: 3600

След няколко минути проверете: dig +short site2.example.com трябва да върне IP на сървъра.

2. Директория на сайта.

sudo mkdir -p /var/www/site2 sudo chown -R www-data:www-data /var/www/site2

3. vhost. Блокът се поставя в терминала изцяло — пътят до сокета на PHP-FPM се определя сам:

PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # автоматично разпознаване на сокета на PHP-FPM sudo tee /etc/apache2/sites-available/site2.conf > /dev/null <<'EOF' <VirtualHost *:80> ServerName site2.example.com # Отделен домейн: махнете # от реда по-долу, за да се отваря сайтът и с www. # За поддомейн този ред не е нужен. #ServerAlias www.site2.example.com DocumentRoot /var/www/site2 <Directory /var/www/site2> Options -Indexes +FollowSymLinks AllowOverride All Require all granted </Directory> <FilesMatch \.php$> SetHandler "proxy:unix:__PHPSOCK__|fcgi://localhost" </FilesMatch> ErrorLog ${APACHE_LOG_DIR}/site2_error.log CustomLog ${APACHE_LOG_DIR}/site2_access.log combined </VirtualHost> EOF sudo sed -i "s#__PHPSOCK__#${PHPSOCK}#" /etc/apache2/sites-available/site2.conf

4. Включете сайта и проверете конфигурацията преди презареждане:

sudo a2ensite site2.conf sudo apache2ctl configtest # очаква се: Syntax OK sudo systemctl reload apache2

5. SSL. certbot вече е инсталиран от автоматичната настройка; към този момент DNS трябва да сочи към сървъра:

# Поддомейн — един адрес: sudo certbot --apache -d site2.example.com # Отделен домейн — веднага и с www (и двата A записа от стъпка 1 трябва да сочат към # сървъра, а www трябва да е в ServerAlias, иначе certbot не може да провери втория адрес): sudo certbot --apache -d site2.example.com -d www.site2.example.com

Третият и следващите домейни се добавят по същия начин — повторете стъпки 1–5, като смените домейна и директорията.

Кой отговаря на „чуждите“ заявки. Ако Host не съвпада с нито един ServerName (отваряне по IP или чужд домейн, насочен към вашия сървър), Apache отдава първия по азбучен ред включен сайт от /etc/apache2/sites-enabled/. Стандартният 000-default се изключва от автоматичната настройка, затова тази „дежурна“ роля остава за vhost на панела (arciveo-monitor.conf) — това не влияе на сайтовете, отваряни по собствените им имена. Ако по IP трябва да се отваря друг сайт, наименувайте файла му така, че да е пръв по азбучен ред (например 000-site2.conf).
Защитата е за целия сървър: UFW, Fail2ban, CrowdSec, ModSecurity и Suricata вече работят и покриват новия сайт автоматично, не е нужно да се настройват отделно. Портовете 80/443 също вече са отворени. Сайтът има собствени логове: site2_error.log и site2_access.log в /var/log/apache2/.
Не поставяйте директорията на новия сайт вътре в директорията на панела — уеб коренът на панела се управлява от собствен .htaccess (фронт контролер) и вложен сайт би отдавал нещо различно от очакваното. Дръжте сайтовете един до друг: /var/www/monitor, /var/www/site2.

39. Възстановяване на достъп (изгубен ключ, парола, 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-филтъра.

40. Всички 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 # на всеки 5 мин, с изместване спрямо снимката по-горе — сензор за събития по # сигурността: нови блокировки, сработвания на IDS, спряла защита, отворен порт. # Докато наблюдението е изключено в настройките, задачата не прави нищо. 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # на всеки 15 мин — обзор на сървъра към личния профил, за да се виждат няколко # сървъра в един списък. Докато обзорът е изключен, задачата не прави нищо. 3,18,33,48 * * * * /usr/local/bin/fleet-push-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 вече е включен в панела, не е нужно да се поставя отделно;
  • security-watch-all.sh → /usr/local/bin/ (chmod +x) — стартира cron/security_watch.php на панела от името на собственика на сайта (страница „Събития по сигурността“, ред 2-57/5 в crontab по-горе); security_watch.php вече е част от панела и не се инсталира отделно;
  • fleet-push-all.sh → /usr/local/bin/ (chmod +x) — изпраща обзора на сървъра към личния профил чрез cron/fleet_push.php на панела (ред 3,18,33,48 по-горе);
  • 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

Диагностика

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

Мониторът разпознава наличието на инструменти чрез 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

42. Отстраняване на проблеми (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 и събитията на ядрото).

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

Симптом: на сървъра има данни (виждат се през 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 не е нужно и е по-малко сигурно.

44. 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 и се проверяват по мрежата — дори ако са разположени на други сървъри. Не е нужно да добавяте нищо ръчно.

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

Мониторът се свързва с 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 връзка.

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

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

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Security 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 просто ще остане неактивна.

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

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

  • Карта на атаките / много банове от 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 задачи): изключете сървъра от външен достъп, направете резервно копие за анализ и, ако данните са критични, вдигнете чист сървър от доверено резервно копие — надеждното изчистване на руткит е трудно.