FAQ

Acesta este ghidul de instalare, configurare și întreținere a Arcivéo Monitor. Secțiunile sunt grupate: prezentare generală, implementarea panoului, conectarea instrumentelor de securitate, module integrate și diagnosticare. Comenzile pot fi copiate cu butonul din dreapta.

De unde încep

01. Instalarea panoului — alegeți metoda

Instalarea panoului este descrisă pe pagini separate, pas cu pas. Alegeți metoda:

Dacă nu sunteți sigur, alegeți varianta automată. Acest ghid rămâne sursa unică pentru SSL, instrumente, cron și diagnosticare — paginile de instalare trimit la secțiunile sale, fără a dubla nimic.

Prezentare generală

02. Ce este Arcivéo Monitor

Arcivéo Monitor — panoul de securitate al serverului. Colectează date de la instrumentele instalate (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco etc.) și le afișează într-o interfață unică, cu dashboard, hartă a atacurilor și pagini detaliate pentru fiecare instrument.

Monitorul nu este un mijloc activ de protecție — el nu blochează atacurile de unul singur. Rolul său este să agrege informațiile de la instrumentele deja active și să le prezinte într-o formă comodă.

03. Cum funcționează monitorul pe server

Monitorul funcționează doar local — trebuie instalat pe același server pe care îl monitorizează. Nu există niciun SSH sau API la distanță.

Toate comenzile (fail2ban-client, ufw status, ipset list etc.) sunt executate de panou în numele utilizatorului serverului web (de obicei www-data, iar pe panourile de hosting — contul site-ului) cu un set restrâns de drepturi sudo — doar pentru utilitare concrete, fără acces root general. Rezultatele sunt analizate și afișate în browser.

Pentru mai multe servere, instalați monitorul pe fiecare separat, cu un domeniu unic.

04. Cum se calculează Scorul de securitate

Scorul pornește de la maxim și scade pentru fiecare problemă identificată:

  • UFW nu este activ — −30
  • Fail2ban nu este pornit (niciun jail activ) — −25
  • Nu există chei WebAuthn — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum nu este încărcat — −10
  • Amenințări găsite de ClamAV — −20
  • Modificări de fișiere AIDE — −15
  • SSL expirat — −30, expiră în <14 zile — −15, <30 zile — −5
  • CrowdSec instalat, dar nepornit — −5
  • Suricata instalată, dar nepornită — −5
  • SGBD/cache (MySQL, PostgreSQL, Redis…) accesibile din exterior — −10
  • Autentificare root prin SSH permisă (PermitRootLogin yes) — −20
  • Actualizări de securitate în așteptare — −5

Rezultat: 80+ = Protejat, 60–79 = Atenție, <60 = În pericol.

Scăderile pentru ClamAV, AIDE, CrowdSec și Suricata se aplică doar dacă instrumentul este instalat. Lynis și AIDE fără o bază inițializată sunt afișate ca „fără date” și nu reduc punctajul. Numărul de atacuri de azi este afișat pe dashboard, dar nu influențează Scorul de securitate.

Setări și licență

05. WebAuthn — autentificare cu doi factori

WebAuthn — standard de autentificare fără parolă printr-o cheie hardware. Acceptă YubiKey, Touch ID, Face ID, Windows Hello, Passkey.

După autentificarea cu parolă, sistemul solicită confirmarea prin cheia înregistrată. Chiar dacă parola este compromisă, fără cheia fizică sau biometrie autentificarea este imposibilă.

Pentru configurare, deschideți Chei WebAuthn din meniul lateral și apăsați „Înregistrează cheia”. Înregistrați imediat două chei: dacă singura cheie se pierde sau se defectează, autentificarea în panou cu ea va fi imposibilă.

WebAuthn funcționează doar prin HTTPS. Pe o conexiune HTTP, înregistrarea și autentificarea cu cheie nu sunt disponibile.

06. Notificări: Telegram și Email

Panoul poate trimite raportul de securitate în Telegram și pe e-mail (la apăsarea unui buton și programat). Se configurează în secțiunea „Setări”.

Telegram. Sunt necesare tokenul botului și chat id:

  1. În Telegram scrieți-i lui @BotFather/newbot → primiți tokenul de forma 123456:ABC....
  2. Trimiteți noului bot orice mesaj (ca să vă poată răspunde).
  3. Aflați-vă chat id: scrieți-i botului @userinfobot sau deschideți https://api.telegram.org/bot<TOKEN>/getUpdates și găsiți "chat":{"id":...}.
  4. Introduceți tokenul și chat id în „Setări” → Telegram, apăsați „Salvează și trimite test”.

Email. Două metode la alegere în „Setări” → Email:

  • SMTP — host, port (465/SSL sau 587/TLS), utilizatorul și parola căsuței dumneavoastră de e-mail;
  • Resend — un API modern: indicați cheia API (re_...) și domeniul expeditor confirmat.
Butonul „Trimite test” verifică imediat canalul. Programarea raportului automat se face prin cron (secțiunea „Toate sarcinile cron”): el declanșează trimiterea, iar canalele se preiau din setări.

Statusul raportului: „ATENȚIE” sau „OK”. Titlul devine „ATENȚIE” doar la o problemă reală sau o acțiune în așteptare: amenințare găsită de ClamAV, modificări de fișiere în AIDE, evenimente critice Falco (Emergency/Alert/Critical în ultimele 24 h), un serviciu picat în Monit, este necesară o repornire, expiră SSL (≤14 zile) sau așteaptă actualizări de securitate. Zgomotul de fond — atacuri SSH prin forță brută ale boților, IP-uri banate de fail2ban, alerte Suricata, avertizări Lynis și cererile deja respinse de ModSecurity — nu ridică statusul, așa că astfel de cifre din raport nu înseamnă „ATENȚIE” prin ele însele.

07. Licență — introducere și activare

Modulele detaliate de monitorizare (Lynis, UFW, ModSecurity, harta atacurilor, AIDE, ClamAV etc.) se deblochează dacă aveți o licență validă. Fără ea funcționează dashboardul, setările și contul, iar modulele afișează cardul „Necesită licență”.

După achiziția din cont, aveți un cod de activare de forma ARCIVEO-XXXX-XXXX-XXXX-XXXX. Acesta trebuie „activat” pe domeniul panoului dumneavoastră — astfel codul devine un fișier de licență semnat (blocul [license]), pe care îl introduceți în panou.

Cum se activează (3 pași):

  1. Luați codul de activare. Contul personal my.arciveo.com → secțiunea „Licențe” / „Activare licență” — copiați codul ARCIVEO-….
  2. Activați codul pe domeniul dumneavoastră. Tot în cont, deschideți „Activare licență”, introduceți: codul de activare, emailul dumneavoastră și domeniul panoului (adresa la care se deschide monitorul, ex. monitor.example.com). Apăsați activare — sistemul va genera fișierul de licență legat de acest domeniu și îl va afișa în câmpul cu butonul „Copiază”.
  3. Introduceți cheia în panou. Copiați tot textul licenței → în panou deschideți „Setări” → blocul „Licență”, lipiți și apăsați „Salvează”. Modulele se deblochează imediat.

Panoul verifică cheia criptografic: semnătura, legarea la domeniu și termenul de valabilitate.

La activare, domeniul trebuie să coincidă exact cu adresa panoului. Luați-l din constanta APP_URL din config.php și introduceți doar numele hostului — fără https:// și fără prefixul www. Activarea este unică: codul devine licență pentru domeniul introdus și nu se mai poate activa a doua oară — la o greșeală în domeniu, cheia nu se va potrivi panoului dumneavoastră, iar codul va fi consumat. De aceea introduceți domeniul cu atenție.
Dacă termenul a expirat sau domeniul s-a schimbat, în antetul panoului va apărea un avertisment. Licența este legată de domeniu pentru totdeauna și nu se transferă pe alt domeniu: pentru un nou termen sau un nou domeniu este nevoie de o cheie nouă (se cumpără din cont și se activează o singură dată).

08. Fișierul config.php — toate setările panoului

Toți parametrii principali ai panoului sunt definiți într-un singur fișier config.php din rădăcină (lângă folderul public/) prin constante obișnuite define(). Fișierul este creat la instalare; rareori trebuie editat manual — în principal la schimbarea domeniului, la migrare sau la conectarea la altă bază de date. După orice modificare reporniți PHP-FPM (altfel, din cauza OPcache, modificările nu se aplică).

Introduceți propriile valori în locurile evidențiate; restul lăsați-l așa cum este:

// --- Bază de date --- define('DB_HOST', 'localhost'); // lăsați define('DB_NAME', 'db_name'); // ce ați stabilit la crearea BD define('DB_USER', 'user'); // ce ați stabilit la crearea BD define('DB_PASS', 'db_password'); // ce ați stabilit la crearea BD define('DB_CHARSET', 'utf8mb4'); // lăsați // --- Aplicație --- define('APP_URL', 'https://monitor.example.com'); // adresa panoului, fără slash la final define('TIMEZONE', 'Europe/Bucharest'); // fusul dumneavoastră orar // --- Durata sesiunii --- define('SESSION_LIFETIME', 28800); // inactivitate până la reautentificare, sec (28800 = 8 h)

Baza de date. Datele de conectare la MySQL/MariaDB:

  • DB_HOST — gazda SGBD, aproape întotdeauna localhost;
  • DB_NAME — numele bazei de date a panoului;
  • DB_USER — utilizatorul BD (acces doar la propria bază);
  • DB_PASS — parola acestui utilizator;
  • DB_CHARSET — codificarea conexiunii, lăsați utf8mb4.

Aplicație.

  • APP_URL — adresa completă a panoului (ex. https://monitor.example.com). Trebuie să coincidă cu domeniul pe care este activată licența — altfel cheia va fi respinsă (vezi secțiunea „Licență”);
  • TIMEZONE — fusul orar PHP: influențează doar modul în care panoul afișează datele și orele. Asupra momentului rulării sarcinilor cron nu influențează — acolo se aplică fusul sistemului (vezi „Toate sarcinile cron”).

Durata sesiunii. SESSION_LIFETIME — timpul de expirare al inactivității sesiunii, în secunde (glisant: se reînnoiește la activitate). Implicit 28800 = 8 ore; după acest timp de inactivitate panoul va cere reautentificarea. De exemplu, 3600 = 1 oră, 86400 = o zi.

Înregistrarea erorilor. Erorile nu sunt niciodată afișate vizitatorilor, ci sunt scrise în logs/php_errors.log — se văd pe pagina „Jurnale aplicație”. Aceste linii (display_errors=0, log_errors=1, calea error_log) de obicei nu trebuie modificate — setările sunt definite direct în fișier și nu depind de php.ini.

config.php — fișier secret. Conține parola BD. Se află în rădăcina panoului (lângă public/), iar la acest panou rădăcina web (DocumentRoot) este chiar rădăcina panoului, nu public/. Fișierul în sine nu „se scurge”: în .htaccess din rădăcină există o interdicție explicită pentru el (Require all denied) — serverul returnează 403. Chiar și fără această regulă, codul sursă nu s-ar scurge: este PHP — serverul îl execută, nu îl livrează ca text. Pentru orice eventualitate: nu îl publicați în depozite publice și nu îl trimiteți la suport cu parola reală. Drepturile fișierului — 640.
La migrare sau la restabilirea accesului, acest fișier este principala sursă de date de conectare: numele BD, utilizatorul și parola se preiau chiar de aici (vezi secțiunile „Actualizarea și migrarea panoului” și „Restabilirea accesului”).

Instrumente de securitate

09. Firewall UFW

UFW (Uncomplicated Firewall) — o interfață simplă pentru nftables/iptables. Închide toate porturile de intrare, cu excepția celor permise explicit. Pagina „Firewall UFW” afișează starea și regulile.

sudo apt install ufw # Permite SSH (obligatoriu ÎNAINTE de activare!) și web sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Închide BD din exterior (acces doar local) sudo ufw deny 3306 # Activează și verifică sudo ufw enable sudo ufw status verbose
Înainte de ufw enable permiteți obligatoriu SSH (ufw allow OpenSSH), altfel veți pierde accesul la server.
„Expunere externă” de pe dashboard ține cont de UFW: un port închis printr-o regulă deny nu este considerat accesibil din exterior.
Skipping adding existing rule — nu este o eroare. Astfel UFW anunță că exact aceeași regulă există deja și nu o adaugă din nou. La reluarea autoconfigurării (care este idempotentă) acesta este un mesaj normal — nu trebuie să reacționați.

10. Instalarea Fail2ban

Blochează automat adresa IP după depășirea numărului de încercări eșuate de autentificare. Analizează jurnalele SSH, nginx, Apache și ale altor servicii.

sudo apt install fail2ban sudo systemctl enable --now fail2ban # Verifică starea: sudo fail2ban-client status
Configurația funcțională (jail.local cu zeci de jail-uri și autoban din ipsum) — în secțiunea următoare.

11. Configurație funcțională Fail2ban + ipsum

Instalarea de bază — mai sus. Aici — configurația funcțională care oferă zeci de jail-uri active și mii de blocări: setări generale, jail-urile cheie și banarea automată a IP-urilor malițioase din lista ipsum.

Fișierul /etc/fail2ban/jail.local — setări generale și cele mai importante jail-uri:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # Ban progresiv: fiecare recidivă — mai lung bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # ban permanent pentru brute-force SSH findtime = 3600 # Recidiviști: cine a prins mai multe ban-uri — se banează definitiv [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 # Servicii web (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … și restul jail-urilor pe servicii (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
În ignoreip treceți obligatoriu propriul IP și rețelele de încredere, altfel vă puteți bana pe dumneavoastră înșivă. După modificări: sudo fail2ban-client reload.

Încărcarea automată a listei de blocare ipsum — în cronul root (sudo crontab -e): level 1 (100+ mii de IP-uri) se încarcă în setul ipsum, care este blocat pe firewall (mai multe — în secțiunea „Listă de blocare IPset”):

# 04:00 — actualizare ipset ipsum (level 1, acoperire maximă): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
Setul trebuie să se numească ipsum — exact pe acesta îl citește dashboardul (cardul „IPset ipsum”). Niveluri: levels/1.txt — acoperire maximă, levels/3.txt — mai precis (3+ surse).

De ce „Monitorul de securitate” este împărțit în două zone. Protecția funcționează pe două niveluri, iar dashboardul nu le amestecă:

  • Atacuri reale (reactiv) — tot ce a prins fail2ban: încercări reale de intruziune (jail-urile sshd, apache-*, nginx-* etc.) și recidiviști periculoși (jail-ul recidive — cei care au fost deja banați de mai multe ori). Acestea sunt IP-uri care chiar au încercat să vă spargă serverul — apar pe harta atacurilor și în „Cronologie”.
  • Blocare preventivă (proactiv) — lista publică de blocare a IP-urilor malițioase cunoscute ipset ipsum, blocată pe firewall prin regula DROP. Aceste adrese, în majoritate, nici nu au atins serverul dumneavoastră — sunt blocate din timp; contorul „IPset ipsum” arată câte au fost blocate preventiv.

Diferența e simplă: reactiv — „aceștia au atacat și au primit ban”, preventiv — „aceștia au fost blocați încă înainte de încercare”. Anterior, în recidive se introducea artificial list-3 ipsum (de aici vechea împărțire „recidive de listă”); acum recidive conține doar recidiviști reali, iar preventivul este integral pe firewall.

12. Listă de blocare IPset (ipsum)

ipsum — listă publică de IP-uri periculoase, actualizată zilnic. Monitorul afișează numărul de adrese încărcate pe dashboard și pe harta atacurilor și îl ia în calcul în Scorul de securitate (−10 dacă setul nu este încărcat).

Varianta minimă fără fail2ban — un set separat ipsum cu blocare prin iptables:

# Creează setul (o singură dată): sudo ipset create ipsum hash:ip # Script de actualizare /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, zilnic la 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
Varianta extinsă cu fail2ban-recidive — în secțiunea „Configurația funcțională Fail2ban + ipsum”.
ipset trăiește în memorie și se pierde la repornire. Un simplu cron zilnic va lăsa setul gol din momentul reboot-ului până la următoarea rulare (dashboard-ul va afișa 0). Încărcați setul și la pornire — mutați încărcarea într-un script și legați-l de @reboot. În același timp, comanda create … -exist stabilește limita maxelem 300000 (implicit 65536 — level 1 nu încape, va apărea „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 — zilnic la 04:00 ȘI la fiecare pornire: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
Cum funcționează la instalarea automată. Scriptul încarcă lista completă level 1 (100+ mii de IP-uri) în setul ipsum și, dacă firewallul este gestionat de programul de instalare (VPS nou — profilurile „Completă”/„Ușoară”), conectează setul la UFW printr-o regulă DROP — traficul de la aceste IP-uri este blocat efectiv. Regula este plasată după ESTABLISHED,RELATED, așa că conexiunile curente (inclusiv SSH-ul dumneavoastră) nu se întrerup — se blochează doar conexiunile noi din listă. Setul se restaurează la pornirea serviciului ipsum-load.service înainte de firewall (altfel UFW nu ar porni) și se actualizează prin cron la 04:00. Pe un server deja configurat (panou, firewall propriu), programul de instalare nu atinge firewallul — acolo ipsum rămâne o listă pentru dashboard și harta atacurilor, iar regula DROP se adaugă manual la dorință (varianta minimă cu iptables … --match-set ipsum … -j DROP — mai sus). La instalarea automată nu trebuie făcut nimic manual.

13. Instalarea CrowdSec

Înlocuitor modern pentru Fail2ban cu threat intelligence colectiv: blocări de la comunitate plus reguli proprii. Necesită un bouncer separat pentru a aplica blocările la firewall.

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash sudo apt install crowdsec sudo systemctl enable --now crowdsec # Bouncer pentru iptables/nftables: sudo apt install crowdsec-firewall-bouncer-iptables # Verifică starea: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
Starea „Nepornit” în panou = pachetul este instalat, dar serviciul nu este activ (monitorul îl verifică prin systemctl is-active crowdsec). Pornire: sudo systemctl enable --now crowdsec; la cădere consultați sudo journalctl -u crowdsec -n 30. Aceeași regulă pentru orice serviciu în starea „Nepornit” (Suricata, Falco, Monit, MySQL).
„0 scenarii” sau „0 bouncers” pe dashboard. CrowdSec vine implicit aproape gol — fără colecții nu detectează nimic, iar fără un bouncer înregistrat blocările nu se aplică la firewall. Instalați colecțiile de bază și asigurați-vă că bouncer-ul apare în listă:
# Colecții de bază (Linux + SSH + server web): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer-ul trebuie să fie în listă și cu starea de conexiune activă: sudo cscli bouncers list
În jurnalul bouncer-ului stream halted / blocările nu se aplică. Este o cheie api orfană: bouncer-ul a fost șters din cscli bouncers list, dar cheia lui veche a rămas în /etc/crowdsec/bouncers/*.yaml. Reînregistrați bouncer-ul și treceți cheia nouă:
sudo cscli bouncers add fw-bouncer # va afișa noul api_key # treceți această cheie în api_key: în /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml sudo systemctl restart crowdsec-firewall-bouncer
Instalarea automată (profilul „Protecție completă”) instalează singură colecțiile și înregistrează firewall-bouncer — manual acest lucru este necesar doar la instalarea manuală sau după o intervenție manuală în CrowdSec.

14. Instalarea AIDE

AIDE (Advanced Intrusion Detection Environment) realizează o imagine a sistemului de fișiere și, la fiecare verificare, raportează modificările din /etc, /bin, /usr. După instalare este obligatorie inițializarea bazei (aideinit).

sudo apt install aide # Inițializarea bazei (5–15 minute): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: directorul /var/lib/aide se creează în modul 700 (proprietar _aide), # iar panoul (www-data) nu vede baza → afișează „Neinițializat”. # Deschideți directorul pentru traversare (fișierele bazei rămân 600): sudo chmod 755 /var/lib/aide # Prima verificare CU SCRIERE în jurnalul pe care îl citește monitorul. # Pe Ubuntu/Debian aide necesită --config explicit (altfel „missing configuration”; # binarul aide.wrapper nu mai este livrat în versiunile noi): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
În timpul aideinit terminalul rămâne 5–15 minute pe linia Running aide --init... — este normal (hashing-ul întregului sistem de fișiere, încărcare pe disc). Nu întrerupeți cu Ctrl+C. Dacă procesul „stă blocat”, dar nu scrie nimic — probabil așteaptă un răspuns la o solicitare ascunsă Overwrite existing aide.db.new [Yn]? (apăsați Y). Verificați activitatea dintr-o altă sesiune: pgrep -af aide.
Eroare aideinit: „21_aide_spamassassin … printf: invalid number” (return code 20) — un bug cunoscut al fragmentului de configurare AIDE în Ubuntu 22.04. Baza nu se creează. Scoateți fragmentul defect și reîncercați:
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
Stările pe dashboard. „Neinițializat” = panoul nu vede fișierul bazei: fie aideinit nu a fost rulat, fie (Ubuntu 24.04) directorul /var/lib/aide a fost creat în modul 700 și este inaccesibil pentru www-data — se rezolvă cu sudo chmod 755 /var/lib/aide (vezi blocul de mai sus). „Nicio verificare” = baza există, dar verificarea nu a fost încă efectuată — nu este o eroare. Monitorul citește rezultatele din /var/log/aide/aide.log.
Verificare periodică → jurnal pentru panou. Standardul /etc/cron.daily/aide pe versiunile noi de Ubuntu/Debian poate să nu scrie /var/log/aide/aide.log în forma necesară (iar aide.wrapper nu mai există în ele). Mai sigur este să adăugați propriul cron cu --config explicit — acesta scrie jurnalul de la root în modul 644, iar monitorul îl citește fără grupuri suplimentare:
# sudo crontab -e — verificare zilnică la 02:00: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # Rulați acum, fără a aștepta programarea: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Instalarea automată face deja toate acestea: chmod 755 /var/lib/aide și cronul de verificare la 02:00 — nu este nevoie de nimic manual.
Prima inițializare faceți-o pe un server curat — înainte de instalarea aplicațiilor web. După modificări legitime, recreați baza: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.

15. Instalarea ClamAV

Scaner antivirus pentru Linux. Este util mai ales pentru verificarea /var/www în privința shell-urilor PHP și a codului malițios.

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # Actualizează baza de semnături: sudo freshclam # Scanează un folder manual: sudo clamscan -r /var/www --infected
Demonul clamd afișează „Inactiv” după enable --now? Trei cauze tipice:

1. În configurație a rămas linia Example — clamd refuză să pornească atât timp cât aceasta există:

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

2. Baza de semnături nu a fost descărcată — clamd nu pornește fără ea:

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

3. Pur și simplu se încarcă — clamd încarcă ~8 mln. de semnături în memorie în 30–60 sec. Așteptați și verificați: systemctl is-active clamav-daemon (statusul activating → încă se încarcă).

Diagnosticare: sudo journalctl -u clamav-daemon -n 30 --no-pager.
Pe dashboard „Fișiere verificate: 0” / „Ultima scanare: —”? Demonul clamd doar ține semnăturile în memorie, el nu scanează nimic după un program. Panoul afișează rezultatele scanării programate, de aceea este nevoie de un cron care scanează și scrie în jurnal. Instalarea automată pune wrapper-ul /usr/local/bin/clamav-scan.sh și un cron la 01:30 — după prima rulare se vor completa „Fișiere verificate” și „Ultima scanare”. Porniți imediat, fără a aștepta programul: sudo /usr/local/bin/clamav-scan.sh.

16. Instalarea Linux Malware Detect (maldet)

Linux Malware Detect (LMD) — scaner de programe malițioase pentru amenințări web: shell-uri PHP, backdoor-uri web, downloadere. Folosește motorul ClamAV și îl completează cu propriile semnături.

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 # Actualizează semnăturile: sudo maldet -u # Scanează /var/www: sudo maldet -a /var/www
LMD și ClamAV funcționează bine împreună. Ultimul raport: maldet --report.
La instalare poate apărea linia update-rc.d: error: unable to read /etc/init.d/maldet — este inofensivă. maldet nu folosește init.d, actualizarea semnăturilor și scanările se lansează prin /etc/cron.daily/maldet. Dacă mai jos vedeți installation completed — totul s-a instalat.
Pe pagină LMD apare „Neinstalat”, deși este instalat? maldet nu se instalează prin apt, ci în /usr/local/maldetect, iar cu open_basedir activat prezența sa se verifică prin shell — vedeți secțiunea „Pagina este goală, deși datele există pe server”.

17. Instalarea Suricata

Sistem de detectare a intruziunilor la nivel de rețea: analizează traficul la nivel de pachete și cunoaște mii de semnături de atac. Completează ModSecurity (acela funcționează la nivel HTTP, Suricata — la nivel TCP/IP).

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # Descarcă regulile actuale: sudo suricata-update sudo systemctl enable --now suricata
Suricata este „Activ”, dar panoul nu afișează alerte / numărul de evenimente e 0? Suricata scrie în /var/log/suricata/eve.json sub root, cu modul 750 pe director, iar serverul web (www-data) nu îl poate citi. Deschideți directorul pentru parcurgere — fișierele din interior rămân protejate:
sudo chmod o+rx /var/log/suricata
Instalarea automată face acest lucru singură — nu este nevoie manual.

18. Instalarea Falco

Interceptează apelurile de sistem prin eBPF/kernel module și detectează anomalii în timp real: shell din nginx, citirea /etc/passwd de către un proces web, scriere în /bin etc.

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
Monitorul citește evenimentele Falco prin journalctl -u falco (fără sudo — prin grupul systemd-journal). Asigurați-vă că www-data este în acest grup — vedeți „Configurarea sudo” (pct. 2) pe pagina de instalare manuală.
„0 evenimente în 24 de ore” este normal, nu o eroare. Falco este event-driven: tace cât timp totul e în ordine și scrie un eveniment doar la o anomalie (shell dintr-un proces web, citirea /etc/passwd, scriere în directoarele de sistem). Zero evenimente critice într-o zi pe un server liniștit este o stare sănătoasă.
Pentru dashboard este mai fiabilă ieșirea în fișier. Citirea prin journalctl necesită drepturi pe jurnal; pentru ca dashboardul să vadă evenimentele stabil, instalarea automată activează la Falco file_output/var/log/falco/falco.log și setează serviciului UMask=0022 (jurnalul este citit de serverul web). Pe o instalare nouă nu este nevoie să configurați asta manual.

19. Instalarea ModSecurity (WAF)

ModSecurity — firewall web (WAF) pentru Apache sau Nginx. Blochează atacurile la nivel de aplicație: injecții SQL, XSS, traversare de căi, scanere.

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # Setul de reguli OWASP Core Rule Set: sudo apt install modsecurity-crs # OBLIGATORIU: fără acest fișier motorul de reguli este dezactivat 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 # Verificare: trebuie să returneze 403 curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
Instalarea pachetului în sine nu protejează cu nimic. Apache include configurațiile prin linia IncludeOptional /etc/modsecurity/*.conf, iar pachetul pune doar modsecurity.conf-recommended — care nu se încadrează în masca *.conf. Dacă nu îl copiați în modsecurity.conf, SecRuleEngine rămâne Off: modulul este încărcat, regulile CRS sunt încărcate, dar traficul nu este verificat și jurnalul de audit nu este creat. Modul intermediar DetectionOnly doar scrie evenimentele în jurnal, fără a bloca cererile — panoul îl afișează cu galben.

Accesul panoului la jurnalul de audit. Jurnalul /var/log/apache2/modsec_audit.log aparține root (drepturi 640), utilizatorul web nu îl poate citi. Panoul preia datele printr-un wrapper — creați-l:

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 # în /etc/sudoers.d/monitor (utilizatorul = cel sub care rulează PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
Wrapper-ul preia ultima directivă SecRuleEngine fără indentare: liniile indentate se află în interiorul blocurilor <LocationMatch>/<Directory> (de exemplu, dezactivarea WAF pentru phpMyAdmin) și nu definesc modul global.
Utilizatorul din sudoers trebuie să coincidă cu utilizatorul pool-ului FPM: pe un Apache/Debian obișnuit acesta este www-data, în HestiaCP pool-ul site-ului rulează de la proprietarul site-ului (de exemplu, admin) — verificați cu grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
Dacă site-ul se află în spatele unui proxy Nginx (HestiaCP), Apache vede ca client proxy-ul însuși — panoul preia IP-ul real al atacatorului din antetul X-Forwarded-For. În statistici ajung doar tranzacțiile cu o regulă declanșată: directiva SecAuditLogRelevantStatus scrie în jurnalul de audit orice răspunsuri 4xx/5xx, așa că acolo ajung și obișnuitele 403/500 — panoul nu le consideră evenimente WAF.
Blocul ---RULES--- este necesar secțiunii „Toate regulile active” — panoul afișează nu doar regulile declanșate, ci în general toate regulile CRS încărcate + cele personalizate. Cele trei căi din bucla for f in … sunt locurile tipice pentru regulile CRS și adăugările locale; dacă aveți altă structură (pachetul pune fișierele în propriul director sau regulile personalizate nu se află în /etc/modsecurity/custom-rules.conf), găsiți căile reale cu comanda sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null și introduceți-le în listă. Dacă wrapper-ul este vechi (fără această secțiune) — secțiunea va afișa doar avertismentul „indisponibil”, restul paginii funcționează ca înainte.

20. Instalarea Auditd

Auditd (Linux Audit Daemon) înregistrează apelurile de sistem la nivelul nucleului: autentificări și deconectări, comenzi sudo, tentative de autentificare eșuate, modificări ale fișierelor. Monitorul afișează autentificările, tentativele eșuate și comenzile sudo de astăzi.

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # Verificați starea și evenimentele: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
Monitorul citește evenimentele prin ausearch (/usr/sbin/ausearch) și, la nevoie, din /var/log/audit/audit.log cu comanda tail. Ambele trebuie să fie în sudoers.

21. Instalarea Monit

Supraveghează serviciile (nginx, php-fpm, mysql etc.) și le repornește la cădere. Poate trimite alerte pe email.

sudo apt install monit sudo systemctl enable --now monit # Fișiere de configurare: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
Monitorul obține lista serviciilor prin monit status. În /etc/monit/monitrc trebuie activată interfața HTTP (blocul set httpd cu allow localhost), altfel monit status va returna o eroare.
Pe dashboard apare „0 servicii sub supraveghere”? Două cauze. (1) Interfața HTTP este dezactivată — în monitrc linia set httpd este comentată (implicit apare ca # set httpd port 2812 …). Decomentați blocul și permiteți localhost. (2) Doar httpd activat nu supraveghează nimic — Monit ia în calcul doar ceea ce este descris prin stanțe check; fără ele lista este goală chiar și cu interfața funcțională. Configurație minimă funcțională:
# /etc/monit/conf.d/00-httpd — interfața HTTP pentru localhost: set httpd port 2812 use address localhost allow localhost # exemple de stanțe check (ce se supraveghează): 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 # verifică sintaxa (Control file syntax OK) sudo systemctl reload monit sudo monit status
Instalarea automată pune un conf.d gata pregătit, cu httpd pe 2812 și un set de verificări — pe o instalare nouă nu este nevoie de configurare manuală.
Serviciul are statusul „Cu erori”? Monitorul doar afișează starea și, în mod intenționat, nu repornește serviciile din panoul web (ar însemna execuție la distanță de comenzi root într-un panou de securitate). Diagnosticarea și repornirea — prin SSH cu Monit:
sudo monit status <service> # cauza erorii sudo monit restart <service> # repornire prin Monit # dacă Monit nu pornește serviciul — verificați unitatea sa proprie: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

22. Instalarea PSAD (detectarea scanării de porturi)

PSAD analizează jurnalul iptables și detectează scanările de porturi și atacurile de rețea, atribuind fiecărei surse un nivel de amenințare (1–5). Completează fail2ban și Suricata.

sudo apt install psad # PSAD citește jurnalul iptables — trebuie activată jurnalizarea (UFW o face singur). # Pentru iptables pur, adăugați reguli LOG în lanțurile INPUT/FORWARD. sudo psad --sig-update sudo systemctl enable --now psad
Monitorul citește datele prin psad --Status (necesar în sudoers). Fără jurnalizarea iptables, pagina va fi goală — este normal, atât timp cât nu au existat scanări.

23. AppArmor / SELinux (control acces)

Mandatory Access Control limitează fișierele și resursele pe care le poate accesa un program, chiar dacă acesta a fost compromis. În Ubuntu/Debian se folosește implicit AppArmor (de obicei deja instalat și activ).

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # verifică profilurile
Monitorul citește starea prin aa-status (necesar în sudoers). Afișează numărul de profiluri în modul enforce/complain și procesele fără profil.

„Profiluri încărcate” mai multe decât enforce + complain — este normal. În AppArmor 4.x (Ubuntu 24.04 și mai nou) a apărut modul unconfined: profilul este încărcat în nucleu, dar nu limitează nimic. Ubuntu marchează astfel zeci de profiluri pentru programe care folosesc user namespaces (browsere, clienți torrent și altele asemenea). Când există astfel de profiluri, cardul „Profiluri încărcate” devine chihlimbariu și le afișează numărul — de exemplu unconfined: 90 la 120 încărcate și 26 în enforce. Protejează cu adevărat doar profilurile în enforce; pe Ubuntu 22.04 (AppArmor 3.x) acest mod nu există și cifrele se potrivesc întotdeauna.

sudo aa-status | grep -E "profiles are" # defalcare pe moduri sudo aa-enforce /etc/apparmor.d/profile-name # trece profilul în enforce
Trecerea în enforce a profilurilor pe care Ubuntu le-a lăsat intenționat în unconfined merită făcută doar în cunoștință de cauză: ele nu sunt dezactivate din greșeală, ci pentru că altfel se strică funcționarea programelor înseși. Profilurile în complain sunt altă poveste: acolo regulile sunt deja scrise și doar nu se aplică.

24. Instalarea debsums (integritatea pachetelor)

debsums verifică dacă fișierele pachetelor instalate corespund sumelor de control din depozit — depistează binarele de sistem înlocuite (completează AIDE). Verificarea completă durează 1–2 minute, de aceea rulează prin cron, iar panoul citește rezultatul din data/debsums/debsums.log și îl împarte singur pe categorii (contează doar binarele și bibliotecile).

Sarcina se pune în cron-ul root (sudo crontab -e). Wrapper-ul gata pregătit debsums-scan.sh se pune în /usr/local/bin/ (chmod +x; vezi rezumatul sarcinilor cron) și scrie singur raportul în data/debsums/ al panoului.

sudo apt install debsums # Linie cron (zilnic 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Wrapper-ul debsums-scan.sh găsește singur data/ al panoului — nu trebuie să specificați calea.

Modificările din /etc/ (configurări) și /usr/share/ (resurse) de pe server sunt de obicei normale — panoul le marchează cu o culoare separată. Îngrijorătoare sunt modificările binarelor și bibliotecilor (/bin, /sbin, /usr/lib etc.) — cardul „Binare / biblioteci” le arată exact pe acestea.

25. Configurarea rapoartelor Lynis

Lynis se pornește manual sau prin cron. Raportul trebuie salvat în folderul data/lynis/ al proiectului — monitorul citește fișierul lynis-report.dat.

# Rulare unică (introduceți propria cale către rădăcina panoului): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # Audit zilnic — linie cron (wrapper-ul lynis-scan.sh gata pregătit în /usr/local/bin/, vezi rezumatul): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
După prima rulare, pagina „Audit Lynis” va afișa imediat hardening index-ul, avertismentele și recomandările.
Butonul „Pornește auditul” de pe pagina Lynis. Acesta rulează lynis-scan.sh în fundal direct din panou (fără a aștepta cron-ul): afișează „Se scanează…” și la finalizare actualizează singur raportul. Pentru aceasta, utilizatorul web are nevoie de o linie sudoers pentru rularea scriptului — programul de instalare o adaugă automat în /etc/sudoers.d/monitor. Dacă panoul a fost instalat manual/mai demult, adăugați-o cu același utilizator care este deja indicat în fișier:
u=$(sudo awk '/NOPASSWD/ && !/lynis-scan/ {print $1; exit}' /etc/sudoers.d/monitor) [ -n "$u" ] && echo "$u ALL=(ALL) NOPASSWD: /usr/local/bin/lynis-scan.sh" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c && sudo chmod 440 /etc/sudoers.d/monitor

26. Configurarea rapoartelor Logwatch

Logwatch trebuie să salveze rapoartele zilnice în folderul data/logwatch/ al proiectului, în format .txt. Monitorul afișează ultimul raport și arhiva.

# Zilnic (6:00) — linie cron (wrapperul gata logwatch_daily.sh în /usr/local/bin/, vezi sumarul): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

Module panou

27. Monitor de rețea (integrat)

Monitorul de rețea nu necesită instalare — este o pagină integrată în panou. Ea afișează starea rețelei serverului din surse locale:

  • interfețe și trafic — din /proc/net/dev;
  • starea legăturilor (UP/DOWN) și IP — prin ip;
  • conexiuni și porturi în ascultare — prin ss;
  • evenimente de rețea ale nucleului din ultimele 24 h — prin journalctl -k.

Primele trei surse funcționează fără sudo, de aceea interfețele, traficul, conexiunile și porturile sunt vizibile imediat. Blocul „Evenimente ale nucleului” folosește journalctl -k — se citește prin grupul systemd-journal („Configurarea sudo”, pct. 2), sudo nu este necesar. Verificați că totul este accesibil pentru utilizatorul web:

# Verificare în numele www-data (sub el rulează 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
Blocul „Evenimente de rețea ale nucleului” afișează evenimentele stivei de rețea a nucleului (schimbarea legăturii up/down, erori de purtătoare, „network unreachable”). Înregistrările firewall-ului UFW BLOCK nu ajung aici — ele se află pe paginile „Firewall UFW” și „Harta atacurilor”. Un bloc gol cu bifă verde = în ultimele 24 h nu au existat defecțiuni de rețea.

28. Disc și SMART

Pagina integrată afișează trei lucruri:

  • Sisteme de fișiere — gradul de ocupare al partițiilor (df); scala devine roșie la ≥90%;
  • Unități de stocare — lista discurilor (lsblk), doar cele reale (loop/snap sunt ascunse);
  • Sănătate (SMART) — starea discului și atributele (smartctl).

Spațiul și lista dispozitivelor funcționează imediat, fără configurare. Pentru SMART este necesar pachetul smartmontools. Procesul web nu are acces direct la dispozitivele de disc, de aceea SMART este preluat prin cron în fișierul data/disk/smart.txt, iar panoul îl citește.

Sarcina se pune în crontabul root (sudo crontab -e). Wrapperul gata făcut smart-scan.sh se plasează în /usr/local/bin/ (chmod +x; vedeți sumarul sarcinilor cron) și scrie singur în data/disk/ al panoului.

sudo apt install smartmontools # Linia cron (la fiecare 30 de minute): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Wrapperul smart-scan.sh găsește singur data/ al panoului — nu este nevoie să specificați calea. În interior, lsblk -e7,11 exclude loop/cdrom.

Pe discuri virtuale (QEMU/KVM și similare) este de obicei disponibil doar statusul general „sănătate: OK”, iar temperatura, orele de funcționare și sectoarele realocate pot fi goale — este normal. Pe un server fizic sunt afișate toate atributele.

29. Performanță (CPU/RAM/Rețea/Disc)

Pagina afișează istoricul încărcării serverului din ultimele 24 de ore — Load Average, ocuparea CPU și așteptarea I/O, RAM/Swap, traficul de rețea (recepție/transmisie), I/O de disc (citire/scriere), umplerea discului și inodes, descriptorii de fișiere deschiși și conexiunile MySQL, plus numărul curent de conexiuni TCP și procese.

Datele sunt colectate de cron/collect_metrics.php — o dată la 5 minute scrie un instantaneu „brut” al contoarelor (/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') în tabelul BD system_metrics; procentele și vitezele sunt calculate de pagină însăși pe baza diferenței dintre instantaneele vecine (umplerea discului/inodes/descriptori/conexiuni MySQL — valori instantanee, fără recalculare). Sudo nu este necesar — sursele se citesc fără drepturi root. Punctele mai vechi de 24 de ore se șterg automat la fiecare scriere.

# Linie Cron (la fiecare 5 minute): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Wrapper-ul collect-metrics-all.sh (vezi sumarul sarcinilor cron) găsește singur toate instanțele panoului instalate pe server și rulează cron/collect_metrics.php al fiecăreia în numele proprietarului site-ului.

Până când colectorul nu rulează cel puțin de două ori (primele ~10 minute după instalare), pagina afișează „se colectează datele” — graficele au nevoie de cel puțin o pereche de puncte vecine pentru a calcula vitezele și procentele.

Alerte de încărcare (secțiunea „Setări” → „Alerte de încărcare”) — la depășirea pragului CPU/RAM/disc/inodes, panoul trimite o notificare pe Telegram/Email (aceleași canale ca raportul zilnic — nu este nevoie să le activați separat pentru alerte), plus încă una — când metrica a revenit la normal. Nu spamează repetat în timp ce pragul se menține: următoarea notificare va veni doar după ciclul „revenit → depășit din nou”.

Pragurile sunt verificate de același collect_metrics.php la fiecare rulare (o dată la 5 minute) — nu este nevoie de un cron separat. Starea „deja notificat / încă nu” este stocată în data/alerts_state.json, iar pragurile — în setările panoului.

30. Harta atacurilor (GeoIP)

Pagina „Harta atacurilor” determină țara după IP cu comanda geoiplookup. Fără pachetul GeoIP țările nu vor fi determinate și punctele nu vor apărea pe hartă:

sudo apt install geoip-bin geoip-database # Verificare: geoiplookup 8.8.8.8
Sudo nu este necesar — baza /usr/share/GeoIP/GeoIP.dat poate fi citită de toți, rezultatele sunt stocate în cache în tmp/geoip_cache.json. Harta în sine (Leaflet + dale OpenStreetMap) se încarcă în browser — este nevoie de internet pe computerul unde este deschis panoul.

31. Expunere externă, actualizări și actualizări automate

Două carduri integrate în tabloul de bord care arată nu „pornit/oprit” al unui instrument, ci gradul real de protecție al serverului. Nu necesită instalare, se citesc local fără sudo.

Expunere externă — câte servicii ascultă pe toate interfețele (0.0.0.0/[::]) și sunt accesibile din exterior. Evidențiază cu roșu dacă o bază de date sau un cache este expus în exterior (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — este o breșă directă (−10 la Scorul de securitate). Sursă: ss -tuln.

Dacă cardul este roșu — închideți baza de date față de exterior: legați-o la 127.0.0.1 (bind-address în configurația MySQL/PostgreSQL, bind 127.0.0.1 în Redis) sau închideți portul în UFW.
„Port deschis” ≠ „accesibil din exterior”. Un serviciu care ascultă pe 127.0.0.1 (loopback) este vizibil doar pentru serverul însuși — din exterior nu poate fi accesat, chiar dacă portul este „deschis”. De aceea Postfix pe portul 25, legat la loopback, este sigur: configurarea automată setează inet_interfaces = loopback-only (plus un smtpd_banner neutru — închide observația Lynis MAIL-8818 despre dezvăluirea versiunii). Cardul „Expunere externă” consideră expus doar ceea ce ascultă pe 0.0.0.0/[::]; serviciile loopback nu intră acolo.
Lynis MAIL-8818 manual (dacă ați instalat poșta manual): în /etc/postfix/main.cf setați smtpd_banner = $myhostname ESMTP (fără versiune și OS) și inet_interfaces = loopback-only, apoi sudo systemctl restart postfix.

Actualizări de securitate — câte patch-uri de securitate așteaptă instalarea și dacă este necesară o repornire după actualizarea kernelului (−5 la Scorul de securitate când există patch-uri). Sursă: /usr/lib/update-notifier/apt-check, fișierul /var/run/reboot-required. Lista detaliată — pe pagina „Actualizări de securitate”.

# Instalați actualizările: sudo apt update && sudo apt upgrade # Verificați ce ascultă spre exterior: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
Cardul de actualizări funcționează pe Ubuntu/Debian (update-notifier-common). Dacă apt-check lipsește — monitorul numără patch-urile prin apt-get -s upgrade.

Actualizări automate de securitate (unattended-upgrades) — pe pagina „Actualizări de securitate” un card separat arată dacă instalarea automată a patch-urilor de securitate este activată și când a rulat ultima dată. Nu este nevoie de sudo — starea se citește prin apt-config dump.

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # activare # Verificați ce este activat: apt-config dump | grep Unattended-Upgrade

Întreținere

32. Copii de rezervă

Copia de rezervă este asigurarea principală: pierderea datelor este mai gravă decât orice atac. Aveți nevoie de două lucruri — o copie de rezervă a serverului/site-urilor și separat o copie de rezervă a bazei de date a panoului (acolo se află utilizatorii, cheile WebAuthn, setările, licența).

Varianta A — HestiaCP: fila Backup a utilizatorului → butonul de creare a copiei de rezervă (sau programat în setările serverului). Copia include site-urile și bazele lor de date.

Varianta B — manual (cron): dump al bazei de date + arhivă a directorului data/ al panoului:

# cron root (sudo crontab -e) — copie zilnică la 2:30 (introduceți propriile nume/căi): 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 # Șterge arhivele mai vechi de 14 zile: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
O copie de rezervă pe același server vă salvează de erori, dar nu și de pierderea serverului. Copiați arhivele pe un spațiu de stocare extern (alt server, S3, rclone în cloud). Verificați că restaurarea chiar funcționează.

33. Actualizarea și migrarea panoului

Actualizarea la o versiune nouă. Faceți mai întâi o copie de rezervă. Apoi reîncărcați fișierele de cod, păstrându-vă datele:

  • de suprascris (cod): public/, includes/, assets/, cron/, database/, precum și fișierele rădăcină .htaccess (controllerul frontal — rutarea nu poate rămâne din versiunea veche), manifest.json, sw.js;
  • de nu atins: config.php (datele BD), data/ (rapoarte), logs/, tmp/ (sesiuni și cache).
# După încărcare — resetați cache-ul PHP (dacă opcache este activat): sudo systemctl reload php*-fpm
FileZilla afișează SSH_FX_PERMISSION_DENIEDPermission denied. Fișierele panoului aparțin lui www-data (așa au fost setate la instalare), în timp ce clientul SFTP se conectează cu utilizatorul dumneavoastră, care nu are drept de scriere. A da lui www-data întregul panou „ca să funcționeze” este tocmai ceea ce duce la această eroare; mai jos sunt trei metode, oricare rezolvă problema.
# Varianta A (recomandată) — separați proprietarii: codul e al dumneavoastră, folderele de lucru sunt ale serverului web. # Serverul web nu primește deloc drept de scriere asupra CODULUI panoului: 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 # Varianta B — ACL peste proprietarii actuali (nu mutăm nimic): 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 # Varianta C — prin grupul www-data. Mai simplă, dar dreptul de scriere asupra # fișierelor panoului îl primește și serverul web (cu o breșă în PHP codul e înlocuibil): 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
De ce varianta A este sigură. Panoul scrie doar în trei directoare — data/ (rapoarte), tmp/ (sesiuni și cache), logs/; acestea rămân ale lui www-data. Restul este cod, iar serverului web îi este necesar doar pentru citire, pe care o oferă grupul www-data cu drepturile 644. Câștig secundar: în caz de breșă în PHP, fișierele panoului nu mai pot fi rescrise. Pe panourile de hosting (HestiaCP și similare) varianta A nu este necesară: acolo fișierele site-ului aparțin oricum contului cu care vă conectați prin SFTP, iar serverul web le citește prin grup.
Capcana variantei B: orice chmod ulterior asupra fișierelor resetează masca ACL, iar accesul dispare în tăcere. Dacă după „punerea în ordine a drepturilor” încărcarea se lovește din nou de Permission denied — repetați ambele comenzi setfacl.
Bitul 2 din varianta C este setgid: fișierele încărcate prin SFTP rămân în grupul www-data, altfel panoul nu le va putea rescrie. După varianta C reconectați-vă în FileZilla — grupul nou se aplică abia la o autentificare nouă. Verificare: id deploy (trebuie să apară grupul www-data) și ls -ld /path/to/monitor (drwxrwsr-x — litera s înseamnă că setgid este activat).

Migrarea pe alt server:

  1. Pe noul server configurați site-ul + HTTPS (vezi pagina de instalare manuală).
  2. Copiați toate fișierele panoului împreună cu config.php, data/.
  3. Migrați BD: mysqldump pe cel vechi → import pe cel nou; corectați datele BD în config.php.
  4. Repetați pe noul server: sudoers, apartenența la grupul adm, sarcinile cron.
  5. Licența este legată de domeniu — dacă domeniul este același, cheia va continua să funcționeze.

34. Recuperarea accesului (cheie pierdută, parolă, blocare IP)

Dacă nu vă puteți autentifica — totul se repară direct în BD de pe server. Deschideți BD (numele — din config.php):

sudo mysql MY_DB

Cheie WebAuthn pierdută (nu trece al doilea factor) — dezactivați 2FA, autentificați-vă cu parola, înregistrați o cheie nouă:

UPDATE users SET webauthn_enabled = 0;

Ați uitat parola — setați un hash nou (generați-l pe server și inserați-l):

# Generați hash-ul noii parole: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # În BD (inserați hash-ul obținut): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

V-ați blocat singur cu filtrul IP — dezactivați restricția:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
Accesul la BD este mereu disponibil: sudo mysql pe server, ori phpMyAdmin / secțiunea BD din panoul de hosting. După recuperare, reactivați WebAuthn și filtrul IP.

35. Toate sarcinile cron într-un singur loc

Sumarul sarcinilor — în cron-ul root al serverului (se adaugă prin sudo crontab -e). Păstrați doar liniile instrumentelor pe care le folosiți; ajustați căile la propriul server.

# Cron-ul de server al monitorului (root) — adăugați prin: sudo crontab -e # 01:30 — scanare ClamAV pe căi periculoase (web, home, temp) → cardurile „Fișiere verificate” și „Ultima scanare” 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — verificarea integrității fișierelor AIDE (necesită explicit --config) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # la pornire — restaurează drepturile /var/lib/aide (fișierul tmpfiles al pachetului # aide-common.conf le resetează la 0700, iar panoul nu mai vede baza) @reboot chmod 755 /var/lib/aide # 03:00 — audit de securitate Lynis 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — actualizarea listei de blocare ipsum (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # setul ipsum la pornire este ridicat de serviciul ipsum-load.service (ÎNAINTEA firewallului, altfel # UFW nu va vedea setul în before.rules) — nu cron. Aici doar reîmprospătarea zilnică de mai sus. # 06:00 — raport Logwatch 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # la fiecare 30 min — verificarea discurilor SMART */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — integritatea pachetelor debsums 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — raport programat pe Email și Telegram 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # la fiecare oră — actualizarea listelor de pachete (pentru cardul „Actualizări de securitate”) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # la fiecare 5 min — instantaneu al resurselor (CPU/RAM/rețea/disc) pentru pagina „Performanță” */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Detalii pentru fiecare — în secțiunile corespunzătoare. Sarcinile de backup (secțiunea anterioară) se adaugă în același cron. După modificări verificați: sudo crontab -l și că serviciul cron este activ.
Ora cron = fusul orar al serverului, nu TIMEZONE din config.php. Constanta TIMEZONE afectează doar PHP (cum afișează panoul datele), dar demonul cron rulează sarcinile după ora de sistem a OS. Dacă fusul serverului nu coincide cu al dumneavoastră, raportul „08:00” va sosi la altă oră. Exemplu: serverul e în alt fus (Europe/Berlin, UTC+2), iar dumneavoastră — la București (UTC+3) → raportul „08:00” va sosi la 09:00 la dumneavoastră. Verificați și, dacă e nevoie, aliniați fusul sistemului la al dumneavoastră:
# Verificați fusul curent al serverului: timedatectl # Setați propriul fus (exemplu) și reporniți cron: sudo timedatectl set-timezone Europe/Bucharest sudo systemctl restart cron
După aceasta, linia 0 8 * * * se va declanșa la 08:00 ora locală. Altfel ar trebui deplasat cron-ul însuși, dar la trecerea la ora de iarnă/vară deplasarea s-ar dezacorda din nou — de aceea e mai corect să configurați fusul sistemului.
Scripturi-wrapper gata făcute. Copiile lor funcționale și un model de crontab (crontab.txt) se află în folderul system/ lângă proiect, în afara public_html. Aceasta nu face parte din site — nu trebuie încărcate în rădăcina web; plasați-le pe server la căile de sistem (ca în crontab de mai sus):
  • lynis-scan.sh/usr/local/bin/ (chmod +x) — rulează lynis audit system, pe durata scanării pune indicatorul /tmp/lynis-running și copiază lynis-report.dat în data/lynis/ al panoului;
  • logwatch_daily.sh/usr/local/bin/ (chmod +x) — generează raportul zilnic Logwatch (sshd, fail2ban, sudo, postfix) în data/logwatch/;
  • smart-scan.sh/usr/local/bin/ (chmod +x) — preia starea discurilor (smartctl) în data/disk/;
  • debsums-scan.sh/usr/local/bin/ (chmod +x) — verifică integritatea pachetelor (debsums) în data/debsums/;
  • clamav-scan.sh/usr/local/bin/ (chmod +x) — scanare antivirus ClamAV pe căi periculoase (web, home, temp); scrie sumarul în /var/log/clamav/scan.log, de unde îl citește pagina ClamAV (linia 01:30 în crontab de mai sus);
  • load-ipsum.sh/usr/local/bin/ (chmod +x) — actualizează setul ipset ipsum (level 1) pe loc, fără a rupe regulile active ale firewallului (linia 04:00 din crontabul de mai sus);
  • daily-report-all.sh/usr/local/bin/ (chmod +x) — rulează raportul cron/daily_report.php al panoului (linia 08:00 în crontab de mai sus);
  • daily_report.php — este deja inclus în panou (cron/daily_report.php), se rulează prin daily-report-all.sh, nu trebuie instalat separat;
  • collect-metrics-all.sh/usr/local/bin/ (chmod +x) — rulează cron/collect_metrics.php al panoului (pagina „Performanță”, linia */5 în crontab de mai sus); collect_metrics.php este deja inclus în panou, nu trebuie instalat separat;
  • crontab.txt (system/cron/) — model de sarcini; introduceți liniile necesare prin sudo crontab -e.
Calea către script în crontab trebuie să coincidă cu locul unde l-ați pus.
Cum să puneți scriptul în /usr/local/bin/. Direct din FileZilla nu se poate scrie acolo — directorul aparține lui root, iar clientul SFTP va primi SSH_FX_PERMISSION_DENIED. Ordinea e următoarea: mai întâi încărcați fișierul în /tmp (acolo scriu toți), apoi mutați-l la locul lui cu o singură comandă:
# în FileZilla: în câmpul „Site la distanță” introduceți /tmp și încărcați acolo scriptul, # apoi prin SSH (install setează imediat proprietarul și drepturile, chown/chmod nu sunt necesare): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # verificare: fișierul e la locul lui, drepturile rwxr-xr-x, sintaxa e intactă bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
Nu confundați directoarele: aveți nevoie de /tmp în rădăcina serverului — nu de /var/tmp și nici de tmp/ din interiorul panoului însuși (ultimul aparține lui www-data și e închis pentru utilizatorul dumneavoastră). În arborele FileZilla /tmp este o ramură de nivel superior, lângă var, nu în interiorul ei.
Ați instalat serverul cu autoconfigurare? Aceste wrappere și sarcinile lor cron sunt deja instalate de script (în /usr/local/bin/, jurnalul — /var/log/arciveo-cron.log) — nu trebuie făcut nimic manual.
Unde caută scripturile panoul. Wrapperele sunt neutre față de domeniu: găsesc instalările panoului parcurgând /home/*/web/*/public_html și /var/www/*, și pun rapoartele în data/ al acestora. Dacă panoul se află la altă cale — adăugați-o în linia for app in … din interiorul scripturilor, altfel rapoartele Lynis/SMART/debsums/Logwatch nu vor ajunge în panou.
cron.log și drepturile de acces. Fișierul logs/cron.log este creat prima dată de cron-ul root — va aparține lui root, iar fila „Jurnal cron” din panou nu îl va putea nici citi, nici goli. Creați fișierul din timp în numele utilizatorului web (proprietarul directorului site-ului; pe HestiaCP este contul, de ex. admin) — atunci cron-ul root doar va adăuga, fără a schimba proprietarul:
# creați din timp în numele utilizatorului web (înainte de a adăuga liniile cron): sudo -u OWNER touch /path/to/monitor/logs/cron.log # dacă cron.log a fost deja creat de cron-ul root — atribuiți-l utilizatorului web: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
Aflați proprietarul directorului: stat -c %U /path/to/monitor.
Gestionare din panou. În secțiunea „Sistem” există pagina „Crontab” — puteți vedea și adăuga sarcini fără SSH. Panoul editează doar sarcinile adăugate prin el însuși (un bloc separat în root-crontab, marcat cu comentarii de serviciu); tot ce se află deja în crontab (lista de mai sus) este afișat acolo read-only într-o listă „Alte sarcini ale serverului” cu butonul „Copiază în editor” — acesta doar transferă programarea/comanda în formularul de adăugare, fără a atinge linia originală. Ca să „treceți” o sarcină existentă sub gestiunea panoului — copiați-o în editor, salvați, apoi ștergeți linia veche manual (sudo crontab -e), altfel se va executa de două ori.
Configurare unică pe server. Pagina are nevoie de un script-wrapper privilegiat — nu de un simplu sudo crontab (asta ar fi o escaladare directă la root pentru oricine obține acces la sesiunea panoului), ci de un script îngust cu două comenzi (list/set), care atinge doar propriul bloc dintre comentariile de serviciu. Instalați o singură dată:
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
Utilizatorul web poate diferi de www-data — verificați sub cine rulează pool-ul PHP-FPM al site-ului (ps -o user= -C php-fpm) și puneți-l în linia sudoers.
Fișierul nou a fost încărcat cu alt proprietar — pagina răspunde „Access denied.”. Dacă fișierul public/crontab_monitor.php a fost încărcat prin FTP/SFTP sub alt utilizator de sistem (de exemplu, root) decât restul fișierelor site-ului, serverul web nu îl va putea citi. Comparați proprietarul și drepturile cu un fișier vecin și aliniați-le:
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

Diagnosticare

36. Instrumentul este instalat, dar afișează „Neinstalat”

Monitorul detectează prezența instrumentelor prin dpkg-query — baza de pachete APT. Dacă instrumentul nu este instalat prin apt (manual, din snap sau din surse), dpkg nu îl vede.

# Verificare prin dpkg: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # Găsește calea către binar: which ufw fail2ban-client auditctl # Test sudo ca www-data: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

37. Rezolvarea problemelor (500, fără date)

Eroare 500 — verificați jurnalele PHP, nginx și ale monitorului:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # Jurnalele monitorului: tail -50 logs/monitor_$(date +%Y-%m-%d).log # Permisiunile pe foldere: ls -la data/ tmp/ logs/
Panoul rulează pe un panou de hosting (HestiaCP, ISPmanager, cPanel)? Acolo PHP nu rulează sub www-data, ci sub contul utilizatorului (de exemplu admin — proprietarul directorului site-ului). Toate regulile sudo și apartenența la grupuri (adm, systemd-journal) trebuie configurate pentru acest utilizator, altfel modulele vor afișa „Inactiv / 0” deși serviciile funcționează. Aflați utilizatorul real al PHP: ps -o user= -C php-fpm | sort -u sau proprietarul directorului site-ului stat -c '%U' /path/to/monitor. Apoi, în toate comenzile de mai jos, folosiți-l în locul lui www-data. Instalarea automată detectează singură utilizatorul web și configurează sudoers pentru el.

Datele nu se afișează — aproape întotdeauna sunt drepturi sudo neconfigurate. Verificați comanda concretă în numele utilizatorului web (înlocuiți www-data cu al dumneavoastră). Indicatorul -n = fără parolă, ca la PHP — dacă cere parola, înseamnă că regula nu există în 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
Modulul afișează „Inactiv” / „0”, deși instrumentul funcționează (de exemplu sudo aa-status în terminal arată profilurile, iar pagina „AppArmor” arată „Inactiv”). Cauza: utilizatorul web nu are dreptul sudo pentru comanda acestui modul. Verificați-o din lista de mai sus: dacă cere parola — adăugați linia lipsă în /etc/sudoers.d/monitor („Configurarea sudo”). Comenzi „noi” frecvente: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
Dacă o anumită pagină (Falco, ModSecurity, Auditd, porturi deschise UFW) este goală — comparați cu lista din secțiunea despre sudo: probabil nu este permis apache2ctl, ausearch, aa-status sau ss, ori utilizatorul web nu este în grupurile adm/systemd-journal (de acolo se citesc jurnalele fail2ban/auth/modsec și journalctl — Falco și evenimentele nucleului).

38. Pagina este goală, deși pe server există date

Simptom: pe server există date (vizibile prin shell), dar pagina afișează „nu există date” sau un status incorect — de exemplu AIDE scrie „Neinițializat”, deși baza este creată.

Cauza este open_basedir: multe panouri și găzduiri restricționează pool-ul PHP-FPM la directorul domeniului, așa că funcțiile PHP file_exists(), file_get_contents(), filemtime() pe căi de sistem (/var/lib/aide, /var/log, /proc…) sunt blocate. Monitorul ocolește acest lucru citind astfel de căi prin comenzi de sistem standard (cat, test, stat).

# Este fișierul vizibil prin shell (așa citește monitorul): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # Valoarea curentă open_basedir pentru pool-ul domeniului: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
Dacă shell-ul „vede” fișierul (VISIBLE), dar pagina nu — este open_basedir. Soluția corectă este citirea prin comenzi de sistem (deja realizată pentru AIDE și Monitorul de rețea). Extinderea open_basedir la /var, /proc nu este necesară și este mai puțin sigură.

39. Pagina SSL nu funcționează

Monitorul verifică certificatele conectându-se direct la domenii prin portul 443. Dacă domeniul nu este accesibil de pe serverul însuși sau portul este blocat de firewall, verificarea nu va reuși.

# Verificați certificatul manual: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # Verificați disponibilitatea: curl -I https://monitor.example.com
Monitorul preia domeniile automat din configurațiile nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) și Apache (/etc/apache2/sites-enabled/), plus hostul curent din HTTP_HOST.
Detectarea automată a subdomeniilor. Subdomeniile sunt detectate automat din jurnalele publice Certificate Transparency și sunt verificate prin rețea — chiar dacă sunt găzduite pe alte servere. Nu trebuie să adăugați nimic manual.

40. Este vizibilă o singură bază din mai multe

Monitorul se conectează la MySQL cu utilizatorul din config.php, care are acces doar la propria bază. MySQL afișează în information_schema doar bazele pentru care există privilegii — de aceea celelalte nu sunt vizibile.

Pentru ca monitorul să vadă toate bazele, acordați acestui utilizator doar dreptul de citire (o singură dată, ca root; înlocuiți numele utilizatorului din config.php):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* acordă doar dreptul de citire — nu se poate modifica, șterge sau crea nimic, deci este sigur pentru monitorizare.
Fără acest GRANT, panoul vede doar propria bază — nu este o eroare, ci o limitare a drepturilor. Panoul nu folosește niciun sudo mysql: lista bazelor este preluată prin propria sa conexiune PDO.

41. PostgreSQL nu apare pe pagina „Baza de date”

PostgreSQL necesită acces la nivelul utilizatorului postgres, pe care utilizatorul web al panoului nu îl are. Expunerea unui sudo psql larg din PHP este nesigură — în schimb, panoul apelează un înveliș restrâns, fără parametri, care afișează doar versiunea, numărul de conexiuni și lista bazelor de date cu dimensiunile lor. Creați-l:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Monitor - read-only PostgreSQL version, connections and per-database size sudo -u postgres psql -tAc "SELECT version();" | grep -oE 'PostgreSQL [0-9.]+' echo "---" sudo -u postgres psql -tAc "SELECT count(*) FROM pg_stat_activity;" echo "---" sudo -u postgres psql -tAc "SELECT datname || '|' || pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;" EOF sudo chown root:root /usr/local/bin/monitor-pgstat sudo chmod 755 /usr/local/bin/monitor-pgstat # în /etc/sudoers.d/monitor (utilizatorul = cel sub care rulează PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
Dacă nu folosiți PostgreSQL — eliminați linia monitor-pgstat din sudoers (pasul 13 al instalării manuale) și nu creați scriptul: cardul PostgreSQL va rămâne pur și simplu inactiv.

42. S-a declanșat o alertă — ce faceți

Panoul arată ce se întâmplă; mai jos — ce trebuie făcut în situații tipice. Principiul general: nu vă panicați, comparați cu activitatea legitimă (acțiunile dumneavoastră, actualizări, backupuri) și reacționați în funcție de gravitate.

  • Harta atacurilor / multe banuri fail2ban — este normal pentru orice server din internet (boții încearcă continuu SSH/web). Important e ca banurile să funcționeze. Asigurați-vă că autentificarea prin SSH se face doar cu cheie (parola dezactivată), iar IP-ul dumneavoastră este în ignoreip.
  • ModSecurity a blocat cereri — WAF-ul respinge atacurile asupra site-ului, asta e treaba lui. Dacă vă blochează traficul legitim (fals pozitiv) — găsiți rule id în detalii și adăugați o excepție în configurația CRS.
  • AIDE: fișiere modificate — comparați lista cu ceea ce ați făcut (actualizarea pachetelor, editarea configurațiilor — e normal). Modificările binarelor de sistem pe care nu le-ați atins sunt un motiv de îngrijorare. După modificări legitime, actualizați baza AIDE.
  • debsums: binare/biblioteci modificate (în afara /etc, în afara /usr/share) — posibil o substituire. Verificați pachetul: debsums PACKAGE_NAME, iar la dubii reinstalați-l (apt install --reinstall).
  • ClamAV / maldet: amenințare găsită — verificați fișierul din carantină, nu îl deschideți. Dacă e un web-shell în directorul site-ului — izolați serverul și căutați punctul de intrare (un plugin vulnerabil, o scurgere de accese).
  • Falco: evenimente critice (lansarea unui shell într-un container, accesul la fișiere sensibile) — analizați evenimentul: al cui proces, ce a lansat. Adesea e activitate legitimă de administrare.
  • Expunere externă: SGBD/cache în roșu — închideți imediat: legați serviciul la 127.0.0.1 sau închideți portul în UFW. Este o breșă reală.
  • SSL expiră / a expirat — reînnoiți certificatul (Let's Encrypt se reînnoiește singur; dacă nu — verificați certbot renew sau setările din panou).
  • Actualizări de securitate în așteptare — instalați: sudo apt update && sudo apt upgrade; după actualizarea nucleului, reporniți serverul.
Semnele unei spargeri reale (procese/utilizatori necunoscuți, binare modificate, spam de ieșire, sarcini cron necunoscute): deconectați serverul de la accesul extern, faceți un backup pentru analiză și, dacă datele sunt critice, ridicați un server curat dintr-un backup de încredere — un rootkit este greu de curățat sigur.
Arcivéo - Security Monitor © 2026