FAQ

Ovo je vodič za instalaciju, podešavanje i održavanje Arcivéo Security Monitor. Odeljci su grupisani: opšti pregled, postavljanje kontrolne table, povezivanje bezbednosnih alata, ugrađeni moduli i dijagnostika. Komande možete kopirati dugmetom sa desne strane.

Kako početi

01. Instalacija kontrolne table — izaberite način

Instalacija kontrolne table nalazi se na zasebnim stranicama sa uputstvima korak po korak. Izaberite način:

Ako niste sigurni — izaberite automatsku. Ovaj priručnik ostaje jedinstveni izvor za SSL, alate, cron i dijagnostiku — install-stranice upućuju na njegove odeljke, ništa ne duplirajući.

Pregled

02. Šta je Arcivéo Security Monitor

Arcivéo Security Monitor — kontrolna tabla bezbednosti servera. Prikuplja podatke od instaliranih alata (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco i dr.) i prikazuje ih u jedinstvenom interfejsu sa kontrolnom tablom, mapom napada i detaljnim stranicama za svaki alat.

Monitor nije aktivno sredstvo zaštite — sam po sebi ne blokira napade. Njegov zadatak je da agregira informacije od već aktivnih alata i prikaže ih na pregledan način.

03. Kako monitor radi na serveru

Monitor radi samo lokalno — mora biti instaliran na istom serveru koji nadzire. Nema nikakvog SSH-a ni udaljenog API-ja.

Sve komande (fail2ban-client, ufw status, ipset list itd.) kontrolna tabla izvršava u ime korisnika veb-servera (obično www-data, na hosting-panelima — nalog sajta) sa uskim skupom prava sudo — samo za konkretne alate, bez opšteg root-pristupa. Rezultati se parsiraju i prikazuju u pregledaču.

Dva ritma rada. Stranice kontrolne table pitaju alate u trenutku otvaranja — uvek vidite trenutno stanje. Pored toga, po rasporedu (cron) rade pozadinski poslovi:

  • na svakih 5 minuta — snimak opterećenja za stranicu „Performanse“;
  • na svakih 5 minuta — senzor bezbednosnih događaja: nove blokade, IDS uzbune, zaustavljena zaštita, otvoren port (odeljak „Bezbednosni događaji“);
  • jednom dnevno — bezbednosni izveštaj na Telegram i e-poštu, kao i teške provere (Lynis, AIDE, ClamAV, debsums, Logwatch);
  • na svakih 15 minuta — pregled servera u korisnički nalog, ako je uključen.

Potpun spisak poslova nalazi se u odeljku „Svi cron poslovi na jednom mestu“.

Za više servera instalirajte monitor na svaki posebno, sa sopstvenim domenom. Da biste ih videli u jednom spisku, uključite pregled servera (odeljak „Pregled servera u korisničkom nalogu“).

04. Kako se računa Ocena bezbednosti

Ocena kreće od maksimuma i smanjuje se za svaki otkriveni problem:

  • UFW nije aktivan — −30
  • Fail2ban nije pokrenut (nema aktivnih jail) — −25
  • Nema WebAuthn ključeva — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum nije učitan — −10
  • ClamAV pronašao pretnje — −20
  • AIDE promene fajlova — −15
  • SSL istekao — −30, ističe za <14 dana — −15, <30 dana — −5
  • CrowdSec instaliran, ali nije pokrenut — −5
  • Suricata instalirana, ali nije pokrenuta — −5
  • Baze/keš (MySQL, PostgreSQL, Redis…) dostupni spolja — −10
  • Dozvoljena prijava root preko SSH (PermitRootLogin yes) — −20
  • Dozvoljena prijava lozinkom preko SSH (PasswordAuthentication yes) — −10
  • Sitna podešavanja SSH-a: uključen X11Forwarding, MaxAuthTries veći od 3 ili sshd_config čitljiv za sve naloge — −5
  • Zaštita veb servera: odgovori otkrivaju verziju veb servera ili PHP-a, uključen je metod TRACE ili nedostaje zaglavlje Strict-Transport-Security ili X-Frame-Options — −5
  • Čekaju instalaciju security-ažuriranja — −5

Rezultat: 80+ = Zaštićen, 60–79 = Pažnja, <60 = Ugrožen.

Odbici za ClamAV, AIDE, CrowdSec i Suricata primenjuju se samo ako je alat instaliran. Lynis i AIDE bez inicijalizovane baze prikazuju se kao „nema podataka“ i ne smanjuju ocenu. Broj napada za danas prikazuje se na kontrolnoj tabli, ali ne utiče na Ocenu bezbednosti. Zaštita veb servera se ne računa ako nijedan sajt nije odgovorio na proveru.

Podešavanja i licenca

05. WebAuthn — dvofaktorska autentifikacija

WebAuthn — standard za autentifikaciju bez lozinke pomoću hardverskog ključa. Podržava YubiKey, Touch ID, Face ID, Windows Hello, Passkey.

Nakon prijave lozinkom sistem traži potvrdu putem registrovanog ključa. Čak i ako lozinka procuri — bez fizičkog ključa ili biometrije prijava nije moguća.

Za podešavanje otvorite WebAuthn ključevi u bočnom meniju i kliknite na „Registruj ključ“. Registrujte odmah dva ključa: ako se jedini ključ izgubi ili pokvari, prijava na kontrolnu tablu njime neće biti moguća.

WebAuthn radi samo preko HTTPS. Na HTTP vezi registracija i prijava ključem nisu dostupne.

06. Obaveštenja: Telegram, Email, webhook i push

Kanala ima četiri: Telegram, Email, webhook i push u pregledaču. Nezavisni su — uključite koje god želite, i sva četiri. Istim kanalima idu dnevni bezbednosni izveštaj, obaveštenja o opterećenju i nalazi senzora događaja; podešavaju se jednom, ovde, u odeljku „Podešavanja“.

Telegram. Potrebni su token bota i chat id:

  1. U Telegramu napišite @BotFather → /newbot → dobićete token oblika 123456:ABC....
  2. Pošaljite svom novom botu bilo kakvu poruku (da bi mogao da vam odgovara).
  3. Saznajte svoj chat id: napišite botu @userinfobot, ili otvorite https://api.telegram.org/bot<TOKEN>/getUpdates i pronađite "chat":{"id":...}.
  4. Unesite token i chat id u „Podešavanja“ → Telegram, kliknite „Sačuvaj i pošalji test“.

Email. Dva načina na izbor u „Podešavanja“ → Email:

  • SMTP — host, port (465/SSL ili 587/TLS), login i lozinka vašeg poštanskog sandučeta;
  • Resend — savremeni API: navedite API ključ (re_...) i potvrđeni domen pošiljaoca.

Webhook. Jedna adresa koja prima POST pokriva Slack, Discord, Mattermost, n8n i sopstveni obrađivač. „Podešavanja“ → Webhook: nalepite adresu i uključite prekidač.

  • ka Slack-u i Mattermost-u šalje se {"text": …}, ka Discord-u {"content": …} (Discord odbija poruke duže od 2000 znakova, pa se tekst skraćuje);
  • svaka druga adresa dobija strukturirani JSON: text, event, severity, source, count, host, ts — tekst poruke ne treba ponovo rastavljati.

Push obaveštenja. Poruka stiže pravo u pregledač, a ako je kontrolna tabla dodata na početni ekran telefona — kao obično obaveštenje aplikacije, bez bota i bez poštanskog servera između. „Podešavanja“ → Push obaveštenja: uključite prekidač i pritisnite „Poveži ovaj uređaj“ na svakom uređaju koji treba da prima obaveštenja. Brojač „Povezani uređaji“ pokazuje koliko ih ima.

Push radi samo preko HTTPS-a (kao i WebAuthn), a dozvola je potrebna dva puta: najpre u pregledaču — upit se pojavljuje posle dugmeta „Poveži ovaj uređaj“ — a zatim i u samom operativnom sistemu. Ako je u Windows-u isključen glavni prekidač Podešavanja → Sistem → Obaveštenja, pregledač će dati dozvolu, kontrolna tabla će prijaviti slanje, a na ekranu se ipak ništa neće pojaviti. Isto čine režim „Ne uznemiravaj“ i isključena obaveštenja pregledača u macOS-u (Sistemska podešavanja → Obaveštenja).
Svaki kanal ima sopstveno dugme „Pošalji test“, koje ga odmah proverava. Raspored automatskog izveštaja ide preko cron-a (odeljak „Svi cron poslovi“): cron pokreće slanje, a kanali se uzimaju iz podešavanja.

Status izveštaja: „PAŽNJA“ ili „OK“. Naslov postaje „PAŽNJA“ samo kod stvarnog problema ili radnje na čekanju: pronađena pretnja u ClamAV, izmene fajlova u AIDE, kritični događaji u Falco (Emergency/Alert/Critical u poslednja 24 h), pao servis u Monit, potreban restart, ističe SSL (≤14 dana) ili čekaju bezbednosna ažuriranja. Pozadinski šum — SSH pokušaji botova, IP adrese banovane preko fail2ban, upozorenja Suricata, upozorenja Lynis i već odbijeni zahtevi ModSecurity — ne podiže status, pa takve cifre u izveštaju same po sebi ne znače „PAŽNJA“.

07. Licenca — unos i aktivacija

Detaljni moduli za nadzor (Lynis, UFW, ModSecurity, mapa napada, AIDE, ClamAV i dr.) otključavaju se uz važeću licencu. Bez nje kontrolna tabla, podešavanja i nalog rade, a moduli prikazuju karticu „Potrebna je licenca“.

Nakon kupovine u korisničkom nalogu imate kod za aktivaciju u obliku ARCIVEO-XXXX-XXXX-XXXX-XXXX. Njega treba „aktivirati“ za domen vaše kontrolne table — time se kod pretvara u potpisanu datoteku licence (blok [license]) koju ubacujete u kontrolnu tablu.

Kako aktivirati (3 koraka):

  1. Uzmite kod za aktivaciju. Korisnički nalog my.arciveo.com → odeljak „Licence“ / „Aktivacija licence“ — kopirajte kod ARCIVEO-….
  2. Aktivirajte kod za svoj domen. Tu u nalogu otvorite „Aktivacija licence“, unesite: kod za aktivaciju, svoj email i domen kontrolne table (adresu na kojoj se otvara monitor, npr. monitor.example.com). Kliknite na aktivaciju — sistem će generisati datoteku licence vezanu za taj domen i prikazati je u polju sa dugmetom „Kopiraj“.
  3. Ubacite ključ u kontrolnu tablu. Kopirajte ceo tekst licence → u kontrolnoj tabli otvorite „Podešavanja“ → blok „Licenca“, nalepite i kliknite na „Sačuvaj“. Moduli se odmah otključavaju.

Kontrolna tabla proverava ključ kriptografski: potpis, vezu za domen i rok važenja.

Domen pri aktivaciji mora tačno da se poklapa sa adresom kontrolne table. Uzmite ga iz konstante APP_URL u config.php i unesite samo ime hosta — bez https:// i bez prefiksa www. Aktivacija je jednokratna: kod se pretvara u licencu za uneti domen i ne aktivira se ponovo — ako pogrešite domen, ključ neće odgovarati vašoj kontrolnoj tabli, a kod će biti potrošen. Zato pažljivo unesite domen.
Ako je rok istekao ili se domen promenio — u zaglavlju kontrolne table pojaviće se upozorenje. Licenca je zauvek vezana za domen i ne prenosi se na drugi domen: za novi rok ili novi domen potreban je novi ključ (kupuje se u nalogu i aktivira jednokratno).

08. Datoteka config.php — sva podešavanja kontrolne table

Svi osnovni parametri kontrolne table zadati su u jednoj datoteci config.php u korenu (pored fascikle public/) običnim konstantama define(). Datoteka se kreira pri instalaciji; ručno je menjati potrebno je retko — uglavnom pri promeni domena, prenosu ili povezivanju na drugu bazu. Nakon svake izmene ponovo pokrenite PHP-FPM (u suprotnom se zbog OPcache izmene neće primeniti).

Umetnite svoje vrednosti na istaknuta mesta; ostalo ostavite kako jeste:

// --- Baza podataka --- define('DB_HOST', 'localhost'); // ostaviti define('DB_NAME', 'db_name'); // što ste zadali pri kreiranju baze define('DB_USER', 'user'); // što ste zadali pri kreiranju baze define('DB_PASS', 'db_password'); // što ste zadali pri kreiranju baze define('DB_CHARSET', 'utf8mb4'); // ostaviti // --- Aplikacija --- define('APP_URL', 'https://monitor.example.com'); // adresa kontrolne table, bez kose crte na kraju define('TIMEZONE', 'Europe/Belgrade'); // vaša vremenska zona // --- Trajanje sesije --- define('SESSION_LIFETIME', 28800); // neaktivnost do ponovne prijave, sek (28800 = 8 č)

Baza podataka. Podaci za povezivanje sa MySQL/MariaDB:

  • DB_HOST — host baze, gotovo uvek localhost;
  • DB_NAME — ime baze podataka kontrolne table;
  • DB_USER — korisnik baze (pristup samo svojoj bazi);
  • DB_PASS — lozinka tog korisnika;
  • DB_CHARSET — kodiranje veze, ostavite utf8mb4.

Aplikacija.

  • APP_URL — puna adresa kontrolne table (npr. https://monitor.example.com). Mora se poklapati sa domenom za koji je aktivirana licenca — u suprotnom će ključ biti odbijen (vidi odeljak „Licenca“);
  • TIMEZONE — vremenska zona PHP-a: utiče samo na to kako kontrolna tabla prikazuje datume i vreme. Na vreme pokretanja cron-zadataka ne utiče — tamo važi zona sistema (vidi „Svi cron-zadaci“).

Trajanje sesije. SESSION_LIFETIME — vreme neaktivnosti sesije u sekundama (klizeće: obnavlja se pri aktivnosti). Podrazumevano 28800 = 8 sati; nakon tog vremena neaktivnosti kontrolna tabla će zatražiti ponovnu prijavu. Na primer, 3600 = 1 sat, 86400 = dan.

Beleženje grešaka. Greške se nikada ne prikazuju posetiocima, već se upisuju u logs/php_errors.log — vide se na stranici „Logovi aplikacije“. Te linije (display_errors=0, log_errors=1, putanju error_log) obično nije potrebno menjati — podešavanja su zadata direktno u datoteci i ne zavise od php.ini.

config.php — tajna datoteka. U njoj je lozinka baze. Nalazi se u korenu kontrolne table (pored public/), a kod ove kontrolne table veb-koren (DocumentRoot) — upravo je koren kontrolne table, ne public/. Sama datoteka ne „curi“: u korenskom .htaccess za nju postoji izričita zabrana (Require all denied) — server vraća 403. Čak i bez tog pravila izvorni kôd ne bi iscureo: ovo je PHP — server ga izvršava, a ne isporučuje kao tekst. Za svaki slučaj: ne postavljajte je u javne repozitorijume i ne šaljite podršci sa stvarnom lozinkom. Dozvole na datoteci — 640.
Pri prenosu ili obnavljanju pristupa ova datoteka je glavni izvor podataka: ime baze, korisnik i lozinka uzimaju se upravo odavde (vidi odeljke „Ažuriranje i prenos kontrolne table“ i „Obnavljanje pristupa“).

09. API samo za čitanje (JSON i Prometheus)

Kontrolna tabla je zatvorena prijavom lozinkom i, ako je uključen, IP filterom. Programu ni jedno ni drugo ne odgovara, pa spoljni sistemi imaju sopstveni ulaz — dve adrese samo za čitanje, zaštićene tokenom. Token ništa ne menja na serveru: njime se mogu samo dobiti pokazatelji.

Uključivanje — „Podešavanja“ → „API samo za čitanje“: prekidač „Uključi API“; token se stvara automatski pri prvom čuvanju. Dugme „Novi token“ izdaje drugi i u istom trenutku isključuje sve koji su koristili prethodni.

  • /api/status.php — JSON: bezbednosna ocena, stanje modula, poslednje merenje opterećenja sa najtežim procesima i bezbednosni događaji za 24 sata;
  • /api/metrics.php — isti brojevi u tekstualnom formatu Prometheus-a (metrike arciveo_*: arciveo_security_score, arciveo_fail2ban_banned, arciveo_cpu_busy_pct i tako dalje).
curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/status.php curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/metrics.php

Ako vaš klijent ne ume da postavi zaglavlje, token se prima i kao parametar — ?token=…. Imajte u vidu da u tom obliku završava u dnevniku pristupa veb servera, pa je zaglavlje bolje.

Prometheus. Gotov blok za scrape_configs:

scrape_configs: - job_name: arciveo metrics_path: /api/metrics.php scheme: https authorization: credentials: <TOKEN> static_configs: - targets: ['monitor.example.com']
Odgovor se kešira na 5 minuta: iza ovih brojeva stoji isto teško ispitivanje alata koje stoji i iza kontrolne table. Često ispitivanje zato serveru ništa ne košta — vrednosti se prosto ponavljaju do sledećeg osvežavanja — ali ni interval kraći od minuta nema smisla.
401 — token je pogrešan ili nije poslat. 404 sa tekstom api disabled — API je isključen u podešavanjima. Odbijeni zahtevi upisuju se u log aplikacije zajedno sa IP adresom pošiljaoca, pa se pogađanje tokena vidi na stranici „Logovi aplikacije“.

10. Pregled servera u korisničkom nalogu

Kontrolna tabla se instalira na svaki server posebno i dobro odgovara na pitanje „kako je ova mašina“. Na pitanje „kako su sve moje mašine“ ne odgovara — zato svaka kontrolna tabla može da šalje kratak pregled u korisnički nalog, gde se serveri vide u jednom spisku.

Šta uzeti u korisničkom nalogu my.arciveo.com → odeljak „Moji serveri“: tamo se izdaje token (oblika fk_…) i navedena je adresa primaoca https://my.arciveo.com/api/fleet.php. Token je jedan po nalogu — isti za sve vaše servere.

Šta podesiti u kontrolnoj tabli — „Podešavanja“ → „Pregled servera“: adresa primaoca, token, naziv servera (kako će biti potpisan u spisku; ostavite li prazno, uzima se domen kontrolne table) i prekidač „Šalji pregled“. Dugme „Pošalji odmah“ proverava vezu istog časa, bez čekanja na raspored.

Dalje pregled odlazi preko cron-a, na svakih 15 minuta:

# na svakih 15 minuta — pregled servera u korisnički nalog 3,18,33,48 * * * * /usr/local/bin/fleet-push-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Šta se tačno šalje: naziv i domen servera, operativni sistem, vreme rada, verzija PHP-a; bezbednosna ocena; stanje modula (UFW, broj Fail2ban jail-ova, blokade za danas, da li rade CrowdSec, Suricata i Falco, pretnje ClamAV-a, izmene AIDE-a, Lynis indeks, ažuriranja na čekanju, da li je potrebno ponovno pokretanje, dani do isteka sertifikata, broj opasno otvorenih portova); poslednje merenje opterećenja (load, CPU, RAM, disk, inode); brojači događaja za 24 sata i poslednji kritični događaj. Dnevnika, lozinki ni sadržaja datoteka u pregledu nema.

Šalje server, a korisnički nalog ne pita. Zato u vašu mrežu ne treba otvarati ulaz spolja, a kontrolna tabla zatvorena IP filterom se svejedno javlja. Čvor se prepoznaje po domenu kontrolne table, pa se spisak ne udvaja posle ponovnog pokretanja ni promene IP adrese.
Server označen u nalogu kao nem znači da pregled odavno nije stigao. Proverite redom: prekidač „Šalji pregled“, red u cron-u (sudo crontab -l) i šta odgovara dugme „Pošalji odmah“. Greške pri slanju upisuju se u log aplikacije sa oznakom FLEET — tu se vidi da li je token odbijen (HTTP 401) ili sama veza nije uspostavljena.

Bezbednosni alati

11. UFW zaštitni zid

UFW (Uncomplicated Firewall) — jednostavan interfejs za nftables/iptables. Zatvara sve dolazne portove osim izričito dozvoljenih. Stranica „UFW zaštitni zid“ prikazuje status i pravila.

sudo apt install ufw # Dozvoli SSH (obavezno PRE uključivanja!) i veb sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Zatvori bazu spolja (pristup samo lokalno) sudo ufw deny 3306 # Uključi i proveri sudo ufw enable sudo ufw status verbose
Pre ufw enable obavezno dozvolite SSH (ufw allow OpenSSH), inače ćete izgubiti pristup serveru.
„Spoljna izloženost“ na kontrolnoj tabli uzima u obzir UFW: port zatvoren pravilom deny ne smatra se dostupnim spolja.
Skipping adding existing rule — nije greška. UFW time javlja da tačno takvo pravilo već postoji i ne dodaje ga ponovo. Pri ponovnom pokretanju automatskog podešavanja (idempotentno je) to je uobičajena poruka — nije potrebno reagovati.

12. Instalacija Fail2ban

Automatski blokira IP adresu nakon prekoračenja broja neuspešnih pokušaja prijave. Analizira logove SSH, nginx, Apache i drugih servisa.

sudo apt install fail2ban sudo systemctl enable --now fail2ban # Provera statusa: sudo fail2ban-client status
Radna konfiguracija (jail.local sa desetinama jail-ova i automatskim banovanjem iz ipsum) — u sledećem odeljku.

13. Radna konfiguracija Fail2ban + ipsum

Osnovna instalacija je gore. Ovde je radna konfiguracija koja daje desetine aktivnih jail-ova i hiljade blokada: opšta podešavanja, ključni jail-ovi i autoban zlonamernih IP adresa sa liste ipsum.

Fajl /etc/fail2ban/jail.local — opšta podešavanja i najvažniji jail-ovi:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # Progresivni ban: svako ponavljanje traje duže bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # trajni ban za brute-force SSH findtime = 3600 # Recidivisti: ko je uhvaćen u više banova — banuje se zauvek [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 # Veb-servisi (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … i ostali jail-ovi po servisima (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
U ignoreip obavezno upišite svoju IP adresu i pouzdane mreže, u suprotnom možete banovati sami sebe. Nakon izmena: sudo fail2ban-client reload.

Automatsko učitavanje blok-liste ipsum — u root cron (sudo crontab -e): level 1 (100+ hiljada IP adresa) učitava se u skup ipsum, koji se odseca na fajervolu (detaljnije — u odeljku „Blok-lista IPset“):

# 04:00 — ažuriranje ipset ipsum (level 1, maksimalni obuhvat): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
Skup mora da se zove ipsum — upravo njega čita kontrolna tabla (kartica „IPset ipsum“). Nivoi: levels/1.txt — maksimalni obuhvat, levels/3.txt — preciznije (3+ izvora).

Zašto je „Monitor bezbednosti“ podeljen na dve zone. Zaštita radi na dva nivoa, i kontrolna tabla ih ne meša:

  • Stvarni napadi (reaktivno) — sve što je uhvatio fail2ban: žive pokušaje proboja (jail-ovi sshd, apache-*, nginx-* itd.) i uporne recidiviste (jail recidive — one koji su već banovani više puta). To su IP adrese koje su vam se stvarno obijale — one su na mapi napada i „Vremenskoj osi“.
  • Preventivna blokada (proaktivno) — javna blok-lista poznatih zlonamernih IP adresa ipset ipsum, koja se odseca na fajervolu pravilom DROP. Ove adrese uglavnom nisu ni dodirnule vaš server — one se seku unapred; brojač „IPset ipsum“ pokazuje koliko ih je preventivno odsečeno.

Razlika je jednostavna: reaktivno — „ovi su napali i dobili ban“, preventivno — „ove smo blokirali još pre pokušaja“. Ranije se u recidive veštački ubacivao list-3 ipsum (otuda stara podela „recidivisti sa liste“); sada je recidive samo pravi recidivisti, a preventiva je u celosti na fajervolu.

14. Blok-lista IPset (ipsum)

ipsum — javna lista zlonamernih IP adresa koja se dnevno ažurira. Monitor prikazuje broj učitanih adresa na kontrolnoj tabli i mapi napada i uračunava ga u Ocenu bezbednosti (−10 ako skup nije učitan).

Minimalna varijanta bez fail2ban-a — poseban skup ipsum sa blokiranjem preko iptables:

# Kreiraj skup (jednom): sudo ipset create ipsum hash:ip # Skripta za ažuriranje /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, dnevno u 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
Proširena varijanta sa fail2ban-recidive — u odeljku „Radna konfiguracija Fail2ban + ipsum“.
ipset živi u memoriji i gubi se pri ponovnom pokretanju. Samo dnevni cron ostaviće skup prazan od trenutka reboot-a do sledećeg pokretanja (kontrolna tabla će prikazati 0). Učitavajte skup i pri startu — izdvojite učitavanje u skriptu i zakačite ga na @reboot. Uz to, komanda create … -exist zadaje limit maxelem 300000 (podrazumevano 65536 — level 1 ne staje, dobićete „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 — dnevno u 04:00 I pri svakom startu: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
Kako radi pri automatskoj instalaciji. Skripta učitava punu listu level 1 (100+ hiljada IP adresa) u skup ipsum i, ako firewall-om upravlja instaler (svež VPS — profili „Puna“/„Olakšana“), povezuje skup sa UFW pravilom DROP — saobraćaj sa tih IP adresa se stvarno blokira. Pravilo stoji posle ESTABLISHED,RELATED, pa se tekuće veze (uključujući vaš SSH) ne prekidaju — seku se samo nove veze sa liste. Skup se obnavlja pri pokretanju servisa ipsum-load.service pre firewall-a (inače se UFW ne bi podigao) i ažurira cron-om u 04:00. Na već podešenom serveru (kontrolna tabla, sopstveni firewall) instaler ne dira firewall — tamo ipsum ostaje lista za kontrolnu tablu i mapu napada, a pravilo DROP se po želji dodaje ručno (minimalna varijanta sa iptables … --match-set ipsum … -j DROP — gore). Pri automatskoj instalaciji ne treba ništa raditi ručno.

15. Instalacija CrowdSec

Savremena zamena za Fail2ban sa kolektivnim threat intelligence: blokade od zajednice plus sopstvena pravila. Zahteva poseban bouncer za primenu blokada na 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 za iptables/nftables: sudo apt install crowdsec-firewall-bouncer-iptables # Provera statusa: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
Status „Nije pokrenut“ na kontrolnoj tabli = servis je instaliran, ali usluga nije aktivna (monitor je proverava preko systemctl is-active crowdsec). Pokretanje: sudo systemctl enable --now crowdsec; kod pada pogledajte sudo journalctl -u crowdsec -n 30. Isto pravilo važi za svaki servis sa statusom „Nije pokrenut“ (Suricata, Falco, Monit, MySQL).
„0 scenarija“ ili „0 bouncer-a“ na kontrolnoj tabli. CrowdSec iz kutije dolazi skoro prazan — bez kolekcija ništa ne detektuje, a bez registrovanog bouncer-a blokade se ne primenjuju na firewall. Instalirajte osnovne kolekcije i uverite se da je bouncer na listi:
# Osnovne kolekcije (Linux + SSH + veb-server): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer mora biti na listi i sa statusom aktivne veze: sudo cscli bouncers list
U logu bouncer-a stream halted / blokade se ne primenjuju. To je osiroteli api-ključ: bouncer je uklonjen iz cscli bouncers list, ali je njegov stari ključ ostao u /etc/crowdsec/bouncers/*.yaml. Ponovo registrujte bouncer i upišite svež ključ:
sudo cscli bouncers add fw-bouncer # izbaciće novi api_key # upišite ovaj ključ u api_key: u /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml sudo systemctl restart crowdsec-firewall-bouncer
Automatska instalacija (profil „Potpuna zaštita“) sama instalira kolekcije i registruje firewall-bouncer — ručno je to potrebno samo kod ručne instalacije ili nakon ručne intervencije u CrowdSec.

16. Instalacija AIDE

AIDE (Advanced Intrusion Detection Environment) pravi snimak sistema datoteka i pri svakoj proveri prijavljuje izmene u /etc, /bin, /usr. Nakon instalacije obavezna je inicijalizacija baze (aideinit).

sudo apt install aide # Inicijalizacija baze (5–15 minuta): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: direktorijum /var/lib/aide kreira se u režimu 700 (vlasnik _aide), # i kontrolna tabla (www-data) ne vidi bazu → prikazuje „Nije inicijalizovana“. # Otvorite direktorijum za prolaz (datoteke baze ostaju 600): sudo chmod 755 /var/lib/aide # Prva provera SA UPISOM u log koji čita monitor. # Na Ubuntu/Debian aide zahteva eksplicitan --config (inače „missing configuration“; # binarni aide.wrapper se u novijim verzijama ne isporučuje): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Tokom aideinit terminal 5–15 minuta stoji na liniji Running aide --init... — to je normalno (heširanje celog sistema datoteka, opterećenje diska). Nemojte prekidati sa Ctrl+C. Ako proces „visi“, ali ništa ne ispisuje — možda čeka odgovor na skriveni upit Overwrite existing aide.db.new [Yn]? (pritisnite Y). Proverite aktivnost iz druge sesije: pgrep -af aide.
Greška aideinit: „21_aide_spamassassin … printf: invalid number“ (return code 20) — poznata greška AIDE konfiguracionog snippet-a u Ubuntu 22.04. Baza se ne kreira. Uklonite neispravan snippet i ponovite:
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
Statusi na kontrolnoj tabli. „Nije inicijalizovana“ = kontrolna tabla ne vidi datoteku baze: ili aideinit nije pokretan, ili je (Ubuntu 24.04) direktorijum /var/lib/aide kreiran u režimu 700 i nedostupan za www-data — rešava se sa sudo chmod 755 /var/lib/aide (vidi blok iznad). „Provera nije obavljena“ = baza postoji, ali provera još nije izvršena — to nije greška. Rezultate monitor čita iz /var/log/aide/aide.log.
Redovna provera → log za kontrolnu tablu. Standardni /etc/cron.daily/aide na novijim Ubuntu/Debian možda neće upisivati /var/log/aide/aide.log u potrebnom obliku (a aide.wrapper u njima više ne postoji). Pouzdanije je dodati sopstveni cron sa eksplicitnim --config — on upisuje log kao root u režimu 644, i monitor ga čita bez dodatnih grupa:
# sudo crontab -e — dnevna provera u 02:00: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # Pokrenite odmah, bez čekanja rasporeda: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Automatska instalacija već radi sve ovo: chmod 755 /var/lib/aide i cron provere u 02:00 — ručno ništa nije potrebno.
Prvu inicijalizaciju obavite na čistom serveru — pre instalacije veb-aplikacija. Nakon legitimnih izmena ponovo kreirajte bazu: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.

17. Instalacija ClamAV

Antivirusni skener za Linux. Naročito koristan za proveru /var/www na PHP šelove i zlonamerni kod.

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # Ažuriranje baze potpisa: sudo freshclam # Ručno skeniranje foldera: sudo clamscan -r /var/www --infected
Demon clamd prikazuje „Neaktivan“ posle enable --now? Tri tipična uzroka:

1. U konfiguraciji je ostao red Example — clamd odbija da se pokrene dok on postoji:

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

2. Nije preuzeta baza potpisa — clamd se ne pokreće bez nje:

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

3. Jednostavno se učitava — clamd učitava ~8 mil. potpisa u memoriju 30–60 s. Sačekajte i proverite: systemctl is-active clamav-daemon (status activating → još učitava).

Dijagnostika: sudo journalctl -u clamav-daemon -n 30 --no-pager.
Na kontrolnoj tabli „Proverenih fajlova: 0“ / „Poslednje skeniranje: —“? Demon clamd samo drži potpise u memoriji, on sam ništa ne skenira po rasporedu. Kontrolna tabla prikazuje rezultate planiranog skeniranja, pa je potreban cron koji skenira i piše log. Automatska instalacija postavlja omotač /usr/local/bin/clamav-scan.sh i cron u 01:30 — posle prvog pokretanja popuniće se „Proverenih fajlova“ i „Poslednje skeniranje“. Pokrenite odmah, ne čekajući raspored: sudo /usr/local/bin/clamav-scan.sh.

18. Instalacija Linux Malware Detect (maldet)

Linux Malware Detect (LMD) — skener zlonamernog softvera za veb-pretnje: PHP shell-ovi, veb-backdoor-i, download-eri. Koristi ClamAV mehanizam i dopunjuje ga sopstvenim potpisima.

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 # Ažuriraj potpise: sudo maldet -u # Skeniraj /var/www: sudo maldet -a /var/www
LMD i ClamAV dobro rade u paru. Poslednji izveštaj: maldet --report.
Pri instalaciji je moguća linija update-rc.d: error: unable to read /etc/init.d/maldet — ona je bezopasna. maldet ne koristi init.d, ažuriranje potpisa i skeniranja se pokreću preko /etc/cron.daily/maldet. Ako se ispod vidi installation completed — sve je instalirano.
Na stranici LMD piše „Nije instaliran“, iako jeste? maldet se ne instalira preko apt, već u /usr/local/maldetect, a kada je open_basedir uključen, njegovo prisustvo se proverava preko shell-a — vidi odeljak „Stranica je prazna, iako podaci postoje na serveru“.

19. Instalacija Suricata

Mrežni sistem za otkrivanje upada: analizira saobraćaj na nivou paketa i poznaje hiljade potpisa napada. Dopunjuje ModSecurity (koji radi na HTTP nivou, dok Suricata radi na TCP/IP nivou).

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # Preuzmi aktuelna pravila: sudo suricata-update sudo systemctl enable --now suricata
Suricata je „Aktivna“, ali kontrolna tabla ne prikazuje upozorenja / broj događaja je 0? Suricata upisuje /var/log/suricata/eve.json pod root u režimu 750 na direktorijum, pa veb-server (www-data) ne može da ga pročita. Otvorite direktorijum za prolaz — datoteke unutra ostaju zaštićene:
sudo chmod o+rx /var/log/suricata
Automatska instalacija to radi sama — ručno nije potrebno.

20. Instalacija Falco

Presreće sistemske pozive kroz eBPF/kernel module i otkriva anomalije u realnom vremenu: shell iz nginx-a, čitanje /etc/passwd veb-procesom, upis u /bin itd.

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
Monitor čita Falco događaje kroz journalctl -u falco (bez sudo — preko grupe systemd-journal). Uverite se da je www-data u toj grupi — vidite „Podešavanje sudo“ (tačka 2) na stranici ručne instalacije.
„0 događaja za 24 sata“ — to je normalno, a ne greška. Falco je event-driven: ćuti dok je sve u redu, a događaj beleži samo pri anomaliji (shell iz veb-procesa, čitanje /etc/passwd, upis u sistemske direktorijume). Nula kritičnih za dan na mirnom serveru je zdravo stanje.
Za kontrolnu tablu je pouzdaniji izlaz u fajl. Čitanje kroz journalctl zahteva prava na dnevnik; da bi kontrolna tabla stabilno videla događaje, automatska instalacija uključuje kod Falco file_output → /var/log/falco/falco.log i servisu postavlja UMask=0022 (dnevnik čita veb-server). Na novoj instalaciji ovo nije potrebno podešavati ručno.

21. Instalacija ModSecurity (WAF)

ModSecurity — veb-firewall (WAF) za Apache ili Nginx. Blokira napade na nivou aplikacije: SQL injekcije, XSS, prolaz kroz putanje, skenere.

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # Skup pravila OWASP Core Rule Set: sudo apt install modsecurity-crs # OBAVEZNO: bez ovog fajla engine pravila je isključen 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 # Provera: treba da vrati 403 curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
Instalacija paketa sama po sebi ništa ne štiti. Apache uključuje konfiguracije linijom IncludeOptional /etc/modsecurity/*.conf, a paket postavlja samo modsecurity.conf-recommended — pod masku *.conf on ne potpada. Ako ga ne kopirate u modsecurity.conf, SecRuleEngine ostaje Off: modul je učitan, CRS pravila su učitana, ali se saobraćaj ne proverava i audit-log se ne kreira. Prelazni režim DetectionOnly samo upisuje događaje u log, ne blokirajući zahteve — kontrolna tabla ga prikazuje žuto.

Pristup kontrolne table audit-logu. Log /var/log/apache2/modsec_audit.log pripada root-u (prava 640), veb-korisnik ga neće pročitati. Kontrolna tabla uzima podatke preko omotača — kreirajte ga:

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 # u /etc/sudoers.d/monitor (korisnik = onaj pod kojim radi PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
Omotač uzima poslednju direktivu SecRuleEngine bez uvlačenja: uvučene linije se nalaze unutar blokova <LocationMatch>/<Directory> (na primer, isključivanje WAF-a za phpMyAdmin) i ne određuju globalni režim.
Korisnik u sudoers-u mora da se poklapa sa korisnikom FPM-pula: na običnom Apache/Debian to je www-data, u HestiaCP pul sajta radi od vlasnika sajta (na primer, admin) — proverite grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
Ako sajt stoji iza Nginx-proksija (HestiaCP), Apache vidi kao klijenta sam proksi — kontrolna tabla uzima realnu IP adresu napadača iz zaglavlja X-Forwarded-For. U statistiku ulaze samo transakcije sa aktiviranim pravilom: direktiva SecAuditLogRelevantStatus upisuje u audit-log bilo koje odgovore 4xx/5xx, pa tamo ulaze i obični 403/500 — kontrolna tabla ih ne smatra WAF događajima.
Blok ---RULES--- potreban je odeljku „Sva aktivna pravila“ — kontrolna tabla prikazuje ne samo aktivirana, već uopšte sva učitana CRS pravila + prilagođena. Tri putanje u petlji for f in … — tipična mesta za CRS pravila i lokalne dopune; ako imate drugačiji raspored (paket postavlja fajlove u svoj direktorijum, ili se prilagođena pravila ne nalaze u /etc/modsecurity/custom-rules.conf), pronađite realne putanje komandom sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null i ubacite ih u listu. Ako je omotač star (bez ovog odeljka) — odeljak će samo prikazati upozorenje „nedostupno“, ostatak stranice radi kao ranije.

22. Instalacija Auditd

Auditd (Linux Audit Daemon) beleži sistemske pozive na nivou jezgra: prijave i odjave, sudo-komande, neuspele pokušaje autentifikacije, izmene fajlova. Monitor prikazuje prijave, neuspele pokušaje i sudo-komande za danas.

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # Proveriti status i događaje: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
Monitor čita događaje preko ausearch (/usr/sbin/ausearch) i po potrebi iz /var/log/audit/audit.log komandom tail. Oba moraju biti u sudoers.

23. Instalacija alata Monit

Prati servise (nginx, php-fpm, mysql itd.) i ponovo ih pokreće kada padnu. Može slati upozorenja na email.

sudo apt install monit sudo systemctl enable --now monit # Konfiguracije: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
Monitor dobija listu servisa preko monit status. U /etc/monit/monitrc mora biti uključen HTTP interfejs (blok set httpd sa allow localhost), inače će monit status vratiti grešku.
Na kontrolnoj tabli piše „0 servisa pod nadzorom“? Dva razloga. (1) HTTP interfejs je isključen — u monitrc je linija set httpd zakomentarisana (podrazumevano ide kao # set httpd port 2812 …). Otkomentarišite blok i dozvolite localhost. (2) Sam uključen httpd ništa ne prati — Monit uzima u obzir samo ono što je opisano check-stancama; bez njih je lista prazna čak i uz aktivan interfejs. Minimalna radna konfiguracija:
# /etc/monit/conf.d/00-httpd — HTTP interfejs za localhost: set httpd port 2812 use address localhost allow localhost # primeri check-stanci (šta pratiti): 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 # provera sintakse (Control file syntax OK) sudo systemctl reload monit sudo monit status
Automatska instalacija postavlja gotov conf.d sa httpd na 2812 i skupom provera — na novoj instalaciji nije potrebno ručno podešavanje.
Servis je u statusu „S greškama“? Monitor samo prikazuje stanje i namerno ne pokreće ponovo servise iz veb-panela (to bi bilo daljinsko izvršavanje root komandi u bezbednosnoj tabli). Dijagnostika i ponovno pokretanje — preko SSH kroz Monit:
sudo monit status <service> # razlog greške sudo monit restart <service> # ponovno pokretanje kroz Monit # ako Monit ne podigne servis — pogledajte njegov sopstveni junit: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

24. Instalacija PSAD (detekcija skeniranja portova)

PSAD analizira dnevnik iptables i otkriva skeniranje portova i mrežne napade, dodeljujući svakom izvoru nivo pretnje (1–5). Dopunjuje fail2ban i Suricata.

sudo apt install psad # PSAD čita iptables log — potrebno je uključiti logovanje (UFW to radi sam). # Za čist iptables dodajte LOG pravila u lance INPUT/FORWARD. sudo psad --sig-update sudo systemctl enable --now psad
Monitor čita podatke preko psad --Status (potreban je u sudoers). Bez logovanja iptables stranica će biti prazna — to je normalno dok nije bilo skeniranja.

25. AppArmor / SELinux (kontrola pristupa)

Mandatory Access Control ograničava kojim datotekama i resursima program može da pristupi, čak i ako je provaljen. Na Ubuntu/Debian se podrazumevano koristi AppArmor (obično je već instaliran i aktivan).

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # provera profila
Monitor čita status preko aa-status (potreban u sudoers). Prikazuje broj profila u režimu enforce/complain i procese bez profila.

„Učitanih profila“ ima više nego enforce + complain — to je normalno. U AppArmor 4.x (Ubuntu 24.04 i noviji) pojavio se režim unconfined: profil je učitan u jezgro, ali ništa ne ograničava. Ubuntu tako označava desetine profila za programe koji koriste user namespaces (pregledači, torent-klijenti i slično). Kada takvi profili postoje, kartica „Učitanih profila“ postaje jantarna i prikazuje njihov broj — na primer unconfined: 90 uz 120 učitanih i 26 u enforce. Stvarnu zaštitu pružaju samo profili u enforce; na Ubuntu 22.04 (AppArmor 3.x) ovog režima nema i brojevi se uvek slažu.

sudo aa-status | grep -E "profiles are" # raščlanjivanje po režimima sudo aa-enforce /etc/apparmor.d/profile-name # prebaci profil u enforce
Profile koje je Ubuntu namerno ostavila u unconfined vredi prebacivati u enforce samo osveštano: nisu isključeni greškom, već zato što bi se inače narušio rad samih programa. Profili u complain su druga priča: tamo su pravila već napisana i samo se ne primenjuju.

26. Instalacija debsums (integritet paketa)

debsums proverava da li se datoteke instaliranih paketa poklapaju sa kontrolnim sumama iz repozitorijuma — otkriva zamenjene sistemske binarne datoteke (dopunjuje AIDE). Potpuna provera traje 1–2 minuta, pa se pokreće preko cron-a, a kontrolna tabla čita rezultat iz data/debsums/debsums.log i sama ga razvrstava po kategorijama (bitne su samo binarne datoteke i biblioteke).

Zadatak ide u root-cron (sudo crontab -e). Gotov omotač debsums-scan.sh stavlja se u /usr/local/bin/ (chmod +x; vidi pregled cron-zadataka) i sam upisuje izveštaj u data/debsums/ kontrolne table.

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

Omotač debsums-scan.sh sam pronalazi data/ kontrolne table — putanju nije potrebno navoditi.

Izmene u /etc/ (konfiguracije) i /usr/share/ (resursi) na serveru su obično normalne — kontrolna tabla ih označava posebnom bojom. Zabrinjavajuće su izmene binarnih datoteka i biblioteka (/bin, /sbin, /usr/lib itd.) — kartica „Binarne datoteke / biblioteke“ prikazuje upravo njih.

27. Podešavanje Lynis izveštaja

Lynis se pokreće ručno ili preko cron-a. Izveštaj se mora čuvati u folderu data/lynis/ projekta — Monitor čita datoteku lynis-report.dat.

# Jednokratno pokretanje (unesite svoju putanju do korena kontrolne table): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # Dnevni audit — cron-linija (gotov omotač lynis-scan.sh u /usr/local/bin/, vidi pregled): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
Posle prvog pokretanja stranica „Lynis audit“ odmah prikazuje hardening index, upozorenja i preporuke.
Dugme „Pokreni audit“ na stranici Lynis. Ono pokreće lynis-scan.sh u pozadini direktno iz kontrolne table (bez čekanja na cron): prikazuje „Skeniranje…“ i po završetku samo osvežava izveštaj. Za to je veb-korisniku potrebna sudoers linija za pokretanje skripte — instalater je dodaje automatski u /etc/sudoers.d/monitor. Ako je kontrolna tabla postavljena ručno/ranije, dopišite je istim korisnikom koji je već naveden u datoteci:
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. Podešavanje Logwatch izveštaja

Logwatch treba da čuva dnevne izveštaje u fascikli data/logwatch/ projekta u formatu .txt. Monitor prikazuje poslednji izveštaj i arhivu.

# Dnevno (6:00) — cron-linija (gotov omotač logwatch_daily.sh u /usr/local/bin/, vidi pregled): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

Moduli kontrolne table

29. Mrežni monitor (ugrađeni)

Mrežni monitor ne zahteva instalaciju — to je ugrađena stranica kontrolne table. Prikazuje mrežno stanje servera iz lokalnih izvora:

  • interfejsi i saobraćaj — iz /proc/net/dev;
  • stanje linkova (UP/DOWN) i IP — preko ip;
  • veze i portovi koji slušaju — preko ss;
  • mrežni događaji jezgra za 24 h — preko journalctl -k.

Prva tri izvora rade bez sudo, pa su interfejsi, saobraćaj, veze i portovi vidljivi odmah. Blok „Događaji jezgra“ koristi journalctl -k — čita se preko grupe systemd-journal („Podešavanje sudo“, t.2), sudo nije potreban. Provera da li je sve dostupno veb-korisniku:

# Provera u ime www-data (pod njim radi 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
Blok „Mrežni događaji jezgra“ prikazuje događaje mrežnog steka jezgra (promena linka up/down, greške nosioca, „network unreachable“). Zapisi zaštitnog zida UFW BLOCK ovde se ne prikazuju — oni su na stranicama „Zaštitni zid UFW“ i „Mapa napada“. Prazan blok sa zelenom kvačicom = tokom dana nije bilo mrežnih otkaza.

30. Disk i SMART

Ugrađena stranica prikazuje tri stvari:

  • Sistemi datoteka — popunjenost particija (df); skala postaje crvena pri ≥90%;
  • Uređaji za skladištenje — spisak diskova (lsblk), samo stvarni (loop/snap su skriveni);
  • Zdravlje (SMART) — status diska i atributi (smartctl).

Prostor i spisak uređaja rade odmah, bez podešavanja. Za SMART je potreban paket smartmontools. Veb-proces nema direktan pristup disk uređajima, pa se SMART očitava preko crona u datoteku data/disk/smart.txt, a kontrolna tabla je čita.

Zadatak ide u root-cron (sudo crontab -e). Gotov omotač smart-scan.sh stavlja se u /usr/local/bin/ (chmod +x; vidi pregled cron-zadataka) i sam upisuje u data/disk/ kontrolne table.

sudo apt install smartmontools # Cron-linija (na svakih 30 minuta): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Omotač smart-scan.sh sam pronalazi data/ kontrolne table — putanju nije potrebno navoditi. Unutar toga lsblk -e7,11 isključuje loop/cdrom.

Na virtuelnim diskovima (QEMU/KVM i sličnim) obično je dostupan samo opšti status „zdravlje: OK“, dok temperatura, sati rada i preraspoređeni sektori mogu biti prazni — to je normalno. Na fizičkom serveru prikazuju se svi atributi.

31. Performanse (CPU/RAM/Mreža/Disk)

Stranica prikazuje istoriju opterećenja servera za poslednja 24 sata — Load Average, zauzeće CPU-a i I/O čekanje, RAM/Swap, mrežni saobraćaj (prijem/slanje), disk I/O (čitanje/pisanje), popunjenost diska i inode-ova, otvorene fajl-deskriptore i MySQL veze, plus trenutni broj TCP veza i procesa. Prozor od 24 sata je podrazumevani: dugmad na vrhu prebacuju ga na 7 dana ili 30 dana.

Podatke prikuplja cron/collect_metrics.php — jednom u 5 minuta upisuje jedan „sirov“ snimak brojača (/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') u tabelu baze system_metrics; procente i brzine stranica računa sama iz razlike između susednih snimaka (popunjenost diska/inode-ova/deskriptora/MySQL veze — trenutne vrednosti, bez preračunavanja). Sudo nije potreban — izvori se čitaju bez root prava.

Dve dubine čuvanja. „Sirovi“ petominutni snimci žive jedan dan (plus sat rezerve, da najstarija tačka na grafikonu ima prethodnika za proračun). Svaki završeni sat se sažima u jedan red; taj časovni niz čuva se 30 dana i upravo njega čitaju prikazi „7 dana“ i „30 dana“. Mesec istorije tako košta oko 720 redova umesto približno 8600.

Na periodima od 7 i 30 dana prikazani su časovni proseci, a ne pojedinačna merenja — kratak skok od pet minuta se na toj razmeri izgladi, a stranica na to upozorava. Za Load Average časovni red čuva i prosek i vrhunac sata, pa grafikon prikazuje obe linije. Odmah posle ažuriranja dugi periodi su prazni („za ovaj period još nema istorije“) — časovni niz počinje da se skuplja od tog trenutka.
# Cron-linija (svakih 5 minuta): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Omotač collect-metrics-all.sh (vidi pregled cron-zadataka) sam pronalazi sve instalirane instance kontrolne table na serveru i pokreće cron/collect_metrics.php svake od njih u ime vlasnika sajta.

Dok kolektor ne odradi bar dvaput (prvih ~10 minuta nakon instalacije), stranica prikazuje „podaci se prikupljaju“ — grafikonima je potreban najmanje jedan par susednih tačaka da bi izračunali brzine i procente.

Najteži procesi. Ispod grafikona su dve tabele sa pet procesa koji najviše troše CPU:

  • „Procesi u poslednjem merenju“ — šta je opterećivalo server u trenutku poslednjeg snimka (vreme je u zaglavlju kartice);
  • „Procesi u vrhuncu dana“ — istih pet, ali uzeti u merenju sa najvišim Load Average u poslednja 24 sata. To je odgovor na pitanje „šta je ono bilo noćas“, kada je vrhunac na grafikonu odavno prošao.

Obe tabele uvek opisuju poslednja 24 sata, čak i kada grafikoni pokazuju mesec: snimak procesa nose samo petominutni redovi, a oni se ne čuvaju duže od jednog dana.

Sopstveni procesi merenja (ps, PHP skript prikupljanja i lanac cron/sudo iznad njega) izuzimaju se sa spiska — inače bi zauzimali prve redove u svakom snimku: ps u trenutku pokretanja pokazuje skoro 100 % CPU. Ostali cron poslovi pokrenuti u istom minutu se pojavljuju — upravo zbog njih tabela i postoji.

Obaveštenja o opterećenju (odeljak „Podešavanja“ → „Obaveštenja o opterećenju“) — pri prekoračenju praga za CPU/RAM/disk/inode kontrolna tabla šalje obaveštenje svim uključenim kanalima (Telegram, Email, webhook, push — istim onim kojima ide dnevni izveštaj; za obaveštenja se ništa ne uključuje posebno), a zatim još jedno kada se metrika vrati u normalu. Dok se prag zadržava, ne spamuje: sledeće obaveštenje stiže tek posle ciklusa „vratilo se u normalu → ponovo prekoračeno“.

Pragove proverava isti collect_metrics.php pri svakom pokretanju (jednom u 5 minuta) — poseban cron nije potreban. Stanje „već obavešteno / još nije“ čuva se u data/alerts_state.json, a pragovi — u podešavanjima kontrolne table.

32. Bezbednosni događaji (senzor na svakih 5 minuta)

Dnevni izveštaj odgovara na pitanje „kako je server“. Senzor odgovara na drugo — „šta se upravo dogodilo“. Na svakih 5 minuta ispituje brze izvore i beleži samo ono što se promenilo od prethodne provere; stranica „Bezbednosni događaji“ u meniju prikazuje spisak nalaza.

Spore provere — Lynis, debsums, ažuriranja paketa, rok SSL sertifikata — senzor ne dira: njihovi brojevi se ionako menjaju jednom dnevno i ostaju posao dnevnog izveštaja.

Šta primećuje — devet izvora:

  • Fail2ban — nove blokade (poredi se spisak blokiranih adresa, pa deblokada nije događaj, a važeća blokada se prijavljuje tačno jednom);
  • CrowdSec — nove odluke;
  • Falco — događaji nivoa Emergency, Alert i Critical;
  • Suricata — nove uzbune; oznaka [Priority: 1] podiže nalaz na kritičan;
  • ClamAV — novi redovi FOUND u dnevniku skeniranja;
  • AIDE — izmene datoteka prema poslednjoj proveri (dakle ne češće nego što se ona izvršava po sopstvenom rasporedu);
  • SSH — uspešna prijava kao root (kritično) i prijava sa adrese koja ranije nije viđena (upozorenje);
  • Servisi zaštite — UFW, Fail2ban, CrowdSec, Suricata, Falco: jedna poruka kada se servis zaustavi i jedna kada ponovo proradi;
  • Portovi — port koji je postao dostupan spolja; ako je iza njega baza podataka ili keš — kritično.

Alat koji nije instaliran ili čiji dnevnik kontrolna tabla ne može da pročita jednostavno ćuti — to nije ni greška ni događaj.

Prva provera ne šalje ništa. Svaki izvor čuva oznaku „dokle je već pročitano“ (datoteka data/secwatch_state.json), a prvi prolaz samo upisuje tu oznaku. U suprotnom bi uključivanje nadzora donelo obaveštenje o svemu što su dnevnici nakupili mesecima.

Podešavanje — „Podešavanja“ → „Nadzor događaja“:

  • Uključi nadzor — dok je isključen, cron posao radi uprazno i spisak se ne puni;
  • Obaveštavati od — „Upozorenje“ ili „Kritično“. Nalazi ispod praga svejedno dospevaju u spisak, ali ne i u obaveštenja;
  • Pauza, min — najmanji razmak između obaveštenja, podrazumevano 15;
  • Tihi sati — prozor u obliku 23-7 tokom kojeg se upozorenja ne šalju.
Kritični nalazi odlaze odmah — ne zadržavaju ih ni pauza ni tihi sati: upravo zbog njih senzor na 5 minuta i postoji. Osigurač ipak postoji: najviše 6 obaveštenja na sat, za slučaj da neki izvor počne da „treperi“.

Obaveštenja idu istim kanalima kao i dnevni izveštaj (Telegram, Email, webhook, push) — ništa se ne uključuje posebno. Svi nalazi se upisuju u spisak nezavisno od toga da li je obaveštenje poslato, i čuvaju se 90 dana.

Spisak događaja. Filteri: period (24 sata, 7, 30 ili 90 dana), važnost i izvor; prikazuje se poslednjih 500 zapisa. Dugme „Proveri odmah“ pokreće tačno isti prolaz kao cron — zgodno odmah posle podešavanja, da se ne čeka pet minuta; ono navodi i razlog kada obaveštenje nije poslato („ispod praga važnosti“, „tihi sati“, „nije podešen nijedan kanal obaveštenja“). Crveni brojač pored stavke menija je broj kritičnih događaja u poslednja 24 sata.

Kartica adrese. Klik na red u listi događaja ili u bloku Povezane adrese otvara sve što se o jednoj adresi zna: hronologiju njenih događaja, državu i u prvom redu zaključak. Red liste otvara karticu kada se događaj odnosi na tačno jednu adresu; ako ih navodi više, veze su same adrese unutar reda. Zaključaka ima četiri:

  • Pristup moguć — sa adrese je bila uspešna prijava, a istu adresu su uhvatile i druge zaštite, ili su odmah potom reagovali AIDE, ClamAV ili se otvorio novi port. Jedini slučaj koji vredi proveriti odmah;
  • Prijava sa ove adrese — prijava postoji i ništa više. Obično je to vlasnik sa novog mesta, zato se kartica ne boji u crveno;
  • Blokirana — adresa je uhvaćena i blokirana: zaštita je odradila svoje, nema šta da se radi;
  • Zahteva proveru — detekcije postoje, blokade nije bilo. Ako se adresa vraća, zatvorite je ručno.

Ispod hronologije stoji blok Šta se u isto vreme dešavalo na serveru: događaji koji uopšte nemaju adresu. AIDE ne zna ko je izmenio datoteku, ClamAV ne zna ko je doneo zaraženu. Prikazani su oni koji padaju u aktivnost adrese i šest sati posle nje. Upravo prijava zajedno sa onim što je usledilo razdvaja pokušaj od stvarnog pristupa.

Veza se gradi po adresi. Napadač koji menja adresu je prekida. Kartica pokazuje ono što su zaštite videle i ne uzima na sebe da razlikuje proboj od vaše sopstvene prijave sa novog mesta.

Raspored. Posao ide u root crontab (sudo crontab -e), pomeren za 2 minuta u odnosu na prikupljanje metrika, da oba ne krenu istovremeno:

# na svakih 5 minuta — provera bezbednosnih događaja 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Pokrećite proveru samo preko omotača, nikada direktno sa php cron/security_watch.php. Omotač pronalazi sve instalacije kontrolne table na serveru i pokreće proveru u ime vlasnika sajta — sa istim sudo pravima koja kontrolna tabla koristi sa veba. Direktan poziv iz root crontab-a napravio bi datoteku stanja data/secwatch_state.json u vlasništvu korisnika root, i dugme „Proveri odmah“ prestalo bi da radi.
Ako je server pripremljen automatskom instalacijom, posao je već dodat — ostaje samo da se nadzor uključi u podešavanjima.

33. Veb server: zahtevi i kodovi odgovora

Stranica „Veb server“ rastavlja dnevnik pristupa i pokazuje koliko je bilo zahteva, koji se deo završio greškom i ko ih je slao. ModSecurity odgovara na pitanje „šta je blokirano“, ova stranica na pitanje „šta je uopšte stizalo na sajt“.

Šta se vidi: broj zahteva, RPS, udeo grešaka, poseban brojač 5xx i količina poslatog saobraćaja; grafikon zahteva po satima; raspodela kodova 2xx/3xx/4xx/5xx; česte adrese, česte IP adrese, česte greške (kod plus putanja) i klijenti (User-Agent). Period: 24 sata ili 7 dana.

Izvor je dnevnik pristupa u formatu combined, pa odgovaraju i Nginx i Apache, a dodatni modul nije potreban. Kontrolna tabla traži dnevnik među standardnim datotekama:

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

Pored njih, kontrolna tabla proverava datoteke *access*.log i *requests*.log u direktorijumima /var/log/nginx/, /var/log/apache2/ i /var/log/httpd/. Tako se pronalazi i dnevnik koji sajt upisuje u sopstvenu datoteku direktivom CustomLog — na primer arciveo-monitor_requests.log, koji pravi Arcivéo instalater.

Čita se samo jedan dnevnik: kada Nginx stoji ispred Apache-a, sabiranje dva dnevnika brojalo bi svaki zahtev dva puta. Uzima se prvi dnevnik sa spiska iznad u koji je upisivano tokom poslednjeg dana (datoteke pronađene po maski proveravaju se posle njega, od najsvežijih); ako ni u jedan nije upisivano tokom dana, uzima se najsvežiji neprazan. Zato dnevnik koji je ispraznio logrotate ili koji je ostao od isključenog veb servera ne zaklanja onaj živi. Čita se poslednji deo dnevnika (3 MB), a rezultat se kešira na 5 minuta — zato na opterećenom sajtu izabrani period možda neće biti pokriven u celosti; stvarni obuhvat je ispisan iznad grafikona.

„Panel ne može da čita dnevnik veb servera“. Uzrok su gotovo uvek dozvole: dnevnici i njihov direktorijum pripadaju grupi adm, a veb korisnik nije u njoj. Arcivéo instalater ga dodaje u tu grupu; posle ručne instalacije pomaže mali omotač od root-a kome je dozvoljena tačno jedna stvar — da ispiše dnevnik (stranica ModSecurity radi na isti način). Omotač bira dnevnik po istim pravilima kao kontrolna tabla. Komanda se ispisuje na samoj stranici; evo je i ovde. Nalepite je celu — to je jedna komanda:
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

Veb korisnik može da se razlikuje od www-data — proverite pod kojim korisnikom radi PHP-FPM pool sajta (ps -o user= -C php-fpm) i upišite ga u red za sudoers. Ako ime dnevnika ne sadrži ni access ni requests, dopišite njegovu putanju na početak reda L=… unutar omotača.

„Za izabrani period nema zapisa“ — dnevnik je pročitan, ali odgovarajući redovi u njemu nisu nađeni: ili sajt zaista nije otvaran, ili se dnevnik upravo obrnuo (logrotate) i počeo iznova.

Pokušaji poznatih ranjivosti. Panel poredi zahteve iz dnevnika sa potpisima dvadesetak raširenih eksploita: PHP-CGI, obilazak direktorijuma u Apache-u, PHPUnit, Log4Shell, ranjivosti rutera, kamera i VPN mrežnih prolaza. Za svaki pokušaj odgovara da li može da proradi na ovom serveru i oslanja se na činjenice: instalirane verzije Apache-a i PHP-a, prisustvo Jave i kod kojim je server odgovorio na zahtev za fajl. Crvenom je označeno samo ono što zaista može da proradi.

Zaštita veb servera. Panel šalje zahtev svakom sajtu na serveru preko 127.0.0.1 i proverava šta dobija posetilac: da li se vide verzije veb servera i PHP-a, da li je uključen metod TRACE i da li postoje zaštitna zaglavlja Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy i Content-Security-Policy. Sajtovi se uzimaju iz adrese na kojoj je panel otvoren i iz fajlova virtuelnih hostova, ako panel može da ih pročita. Rezultat se osvežava na svakih 10 minuta.

Ako nešto nedostaje, ispod tabele se pojavljuje jedna komanda. Ona pravi zaseban fajl zz-arciveo-hardening.conf i ponovo učitava veb server tek posle uspešne provere konfiguracije; zaglavlja koja sajt već šalje sam ne dupliraju se. CSP se ne nudi kao jedan red: politika se pravi za konkretan sajt, inače on prestaje da učitava sopstvene skripte, stilove i fontove. Poništavanje izmene na Apache-u:

sudo a2disconf zz-arciveo-hardening && sudo systemctl reload apache2
Potpis na stranicama grešaka (ServerSignature) ne označava se ako je verzija veb servera već skrivena: bez verzije prikazuje samo naziv servera i ime hosta.

34. Mapa napada (GeoIP)

Stranica „Mapa napada“ određuje državu na osnovu IP adrese pomoću komande geoiplookup. Bez GeoIP paketa države se neće odrediti i tačke se neće pojaviti na mapi:

sudo apt install geoip-bin geoip-database # Provera: geoiplookup 8.8.8.8
Sudo nije potreban — bazu /usr/share/GeoIP/GeoIP.dat mogu čitati svi, a rezultati se keširaju u tmp/geoip_cache.json. Sama mapa (Leaflet + OpenStreetMap pločice) učitava se u pregledaču — potreban je internet na računaru na kojem je otvorena kontrolna tabla.

35. Spoljna izloženost, ažuriranja i automatska ažuriranja

Dve ugrađene kartice kontrolne table koje ne prikazuju „uklj./isklj.“ alata, već stvarnu zaštićenost servera. Ne zahtevaju instalaciju, čitaju se lokalno bez sudo.

Spoljna izloženost — koliko servisa sluša sve interfejse (0.0.0.0/[::]) i dostupno je spolja. Osvetljava crvenim ako su spolja izloženi baza podataka ili keš (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — to je direktna rupa (−10 na Ocenu bezbednosti). Izvor: ss -tuln.

Ako je kartica crvena — zatvorite bazu podataka za spoljni svet: vežite je za 127.0.0.1 (bind-address u konfiguraciji MySQL/PostgreSQL, bind 127.0.0.1 u Redis) ili zatvorite port u UFW.
„Otvoren port“ ≠ „dostupan spolja“. Servis koji sluša 127.0.0.1 (loopback) vidljiv je samo samom serveru — spolja mu se ne može pristupiti, čak i ako je port „otvoren“. Zato je Postfix na portu 25, vezan za loopback, bezbedan: automatsko podešavanje postavlja inet_interfaces = loopback-only (plus neutralni smtpd_banner — zatvara napomenu Lynis MAIL-8818 o otkrivanju verzije). Kartica „Spoljna izloženost“ računa kao spoljno samo ono što sluša 0.0.0.0/[::]; loopback servisi tu ne spadaju.
Lynis MAIL-8818 ručno (ako ste sami postavljali poštu): u /etc/postfix/main.cf zadajte smtpd_banner = $myhostname ESMTP (bez verzije i OS-a) i inet_interfaces = loopback-only, zatim sudo systemctl restart postfix.

Bezbednosna ažuriranja — koliko bezbednosnih zakrpa čeka instalaciju i da li je potrebno ponovno pokretanje nakon ažuriranja kernela (−5 na Ocenu bezbednosti ako postoje zakrpe). Izvor: /usr/lib/update-notifier/apt-check, fajl /var/run/reboot-required. Detaljan spisak — na stranici „Bezbednosna ažuriranja“.

# Instalirati ažuriranja: sudo apt update && sudo apt upgrade # Proveriti šta sluša spolja: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
Kartica ažuriranja radi na Ubuntu/Debian (update-notifier-common). Ako apt-check nedostaje — Monitor računa zakrpe preko apt-get -s upgrade.

Automatska bezbednosna ažuriranja (unattended-upgrades) — na stranici „Bezbednosna ažuriranja“ posebna kartica prikazuje da li je uključena automatska instalacija bezbednosnih zakrpa i kada je poslednji put pokrenuta. Sudo nije potreban — status se čita preko apt-config dump.

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # uključiti # Proveriti šta je uključeno: apt-config dump | grep Unattended-Upgrade

Održavanje

36. Rezervne kopije

Rezervna kopija je glavno osiguranje: gubitak podataka je gori od bilo kakvog upada. Potrebne su dve stvari — rezervna kopija servera/sajtova i posebno rezervna kopija baze kontrolne table (tu su korisnici, WebAuthn ključevi, podešavanja, licenca).

Opcija A — HestiaCP: kartica Backup kod korisnika → dugme za kreiranje rezervne kopije (ili po rasporedu u podešavanjima servera). Rezervna kopija obuhvata sajtove i njihove baze.

Opcija B — ručno (cron): dump baze + arhiva direktorijuma data/ kontrolne table:

# root-cron (sudo crontab -e) — dnevna rezervna kopija u 2:30 (unesite svoja imena/putanje): 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 # Brisanje arhiva starijih od 14 dana: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
Rezervna kopija na istom serveru spasava od grešaka, ali ne i od gubitka servera. Kopirajte arhive na spoljno skladište (drugi server, S3, rclone u oblak). Proveravajte da vraćanje zaista funkcioniše.

37. Ažuriranje i migracija kontrolne table

Ažuriranje na novu verziju. Prvo napravite rezervnu kopiju. Zatim ponovo otpremite datoteke koda, zadržavši svoje podatke:

  • prepisati (kod): public/, includes/, assets/, cron/, database/, kao i korenske .htaccess (front-kontroler — rutiranje se ne sme ostaviti iz stare verzije), manifest.json, sw.js;
  • ne dirati: config.php (podaci BP), data/ (izveštaji), logs/, tmp/ (sesije i keš).
# Nakon otpremanja — resetovati keš PHP (ako je opcache uključen): sudo systemctl reload php*-fpm
FileZilla javlja SSH_FX_PERMISSION_DENIED — Permission denied. Fajlovi kontrolne table pripadaju korisniku www-data (tako su podešeni pri instalaciji), dok se SFTP klijent povezuje pod vašim sopstvenim korisnikom, koji nema pravo upisa. Predati www-data celu kontrolnu tablu „da bi radilo“ — upravo je to ono što dovodi do ove greške; ispod su tri načina, svaki rešava problem.
# Varijanta A (preporučeno) — razdvojiti vlasnike: kôd je vaš, radne fascikle veb-servera. # Veb-server uopšte ne dobija pravo upisa u KÔD kontrolne table: 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 # Varijanta B — ACL preko trenutnih vlasnika (ništa ne premeštamo): 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 # Varijanta C — preko grupe www-data. Jednostavnija, ali pravo upisa u fajlove # kontrolne table dobija i veb-server (uz ranjivost u PHP-u kôd se može podmeniti): 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
Zašto je varijanta A bezbedna. Kontrolna tabla upisuje samo u tri direktorijuma — data/ (izveštaji), tmp/ (sesije i keš), logs/; oni ostaju u vlasništvu www-data. Ostalo je kôd, a veb-serveru je on potreban samo za čitanje, koje omogućava grupa www-data s pravima 644. Uzgredna korist: uz ranjivost u PHP-u fajlovi kontrolne table se više ne mogu prepisati. Na hosting-kontrolnim tablama (HestiaCP i slične) varijanta A nije potrebna: tamo fajlovi sajta ionako pripadaju nalogu pod kojim se prijavljujete preko SFTP, a veb-server ih čita po grupi.
Zamka varijante B: svaki naredni chmod nad fajlovima resetuje ACL-masku i pristup neprimetno nestaje. Ako se posle „sređivanja prava“ otpremanje ponovo zaustavi na Permission denied — ponovite obe komande setfacl.
Bit 2 u varijanti C je setgid: fajlovi otpremljeni preko SFTP ostaju u grupi www-data, inače kontrolna tabla ne može da ih prepiše. Posle varijante C povežite se ponovo u FileZilli — nova grupa važi tek pri novoj prijavi. Provera: id deploy (mora da se pojavi grupa www-data) i ls -ld /path/to/monitor (drwxrwsr-x — slovo s znači da je setgid postavljen).

Migracija na drugi server:

  1. Na novom serveru podignite sajt + HTTPS (vidi stranicu ručne instalacije).
  2. Kopirajte sve datoteke kontrolne table zajedno sa config.php, data/.
  3. Prenesite BP: mysqldump na starom → uvoz na novom; ispravite podatke BP u config.php.
  4. Ponovite na novom serveru: sudoers, članstvo u grupi adm, cron zadatke.
  5. Licenca je vezana za domen — ako je domen isti, ključ će nastaviti da radi.

38. Drugi sajt na ovom serveru (još jedan domen)

Kontrolna tabla već radi, a na istom serveru je potreban još jedan sajt — sa sopstvenim domenom pored monitora. Posle automatskog podešavanja server je običan Apache + PHP-FPM, pa su sajtu potrebne tri stvari: sopstveni direktorijum, sopstveni vhost i sopstveni sertifikat. Kontrolnu tablu pritom ne diramo: ona nadgleda ceo server, drugi primerak za drugi domen nije potreban.

Ovaj odeljak je za server bez hosting panela. Ako je instaliran HestiaCP ili sličan panel, dodajte domen u njemu, a ne ručno. A ako planirate mnogo sajtova (uz to i poštu), panel se instalira pre automatskog podešavanja: skripta ga prepoznaje i prelazi u aditivni režim, dok panel instaliran kasnije iznova gradi konfiguraciju Apache-a, zaštitnog zida i pošte.
Šta zameniti u komandama. site2.example.com je adresa novog sajta. To može biti i zaseban domen (mycompany.com) i poddomen (shop.mycompany.com) — za Apache nema razlike, razlikuju se samo DNS zapis (korak 1) i izdavanje sertifikata (korak 5). site2 je samo kratko ime sajta: tako se zovu direktorijum /var/www/site2 i konfiguraciona datoteka site2.conf. Sa domenom nema nikakve veze, Apache uzima adresu isključivo iz ServerName; ime može biti bilo koje — za shop.mycompany.com je, na primer, zgodno shop: direktorijum /var/www/shop, konfiguracija shop.conf.

1. DNS. U DNS panelu kod registratora domena napravite A zapis ka IP adresi ovog servera:

# Poddomen (shop.mycompany.com): Tip: A Ime: shop Vrednost: 203.0.113.10 TTL: 3600 # Zaseban domen (mycompany.com) — dva zapisa, da radi i adresa sa www: Tip: A Ime: @ Vrednost: 203.0.113.10 TTL: 3600 Tip: A Ime: www Vrednost: 203.0.113.10 TTL: 3600

Posle nekoliko minuta proverite: dig +short site2.example.com treba da vrati IP servera.

2. Direktorijum sajta.

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

3. vhost. Blok se u terminal nalepi u celini — putanja do PHP-FPM soketa određuje se sama:

PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # automatsko prepoznavanje PHP-FPM soketa sudo tee /etc/apache2/sites-available/site2.conf > /dev/null <<'EOF' <VirtualHost *:80> ServerName site2.example.com # Zaseban domen: uklonite # iz reda ispod da bi se sajt otvarao i sa www. # Za poddomen taj red nije potreban. #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. Uključite sajt i proverite konfiguraciju pre ponovnog učitavanja:

sudo a2ensite site2.conf sudo apache2ctl configtest # očekuje se: Syntax OK sudo systemctl reload apache2

5. SSL. certbot je već instaliran automatskim podešavanjem; DNS u ovom trenutku mora da pokazuje na server:

# Poddomen — jedna adresa: sudo certbot --apache -d site2.example.com # Zaseban domen — odmah i sa www (oba A zapisa iz koraka 1 moraju da pokazuju na server, # a www mora da bude u ServerAlias, inače certbot ne može da proveri drugu adresu): sudo certbot --apache -d site2.example.com -d www.site2.example.com

Treći i naredni domeni dodaju se na isti način — ponovite korake 1–5 uz drugi domen i drugi direktorijum.

Ko odgovara na „tuđe“ zahteve. Ako se Host ne poklapa ni sa jednim ServerName (pristup preko IP adrese ili tuđi domen usmeren na vaš server), Apache isporučuje prvi po abecedi uključen sajt iz /etc/apache2/sites-enabled/. Standardni 000-default automatsko podešavanje isključuje, pa ta „dežurna“ uloga ostaje vhostu kontrolne table (arciveo-monitor.conf) — na sajtove koji se otvaraju sopstvenim imenom to ne utiče. Ako preko IP adrese treba da se otvara drugi sajt, nazovite njegovu datoteku tako da bude prva po abecedi (na primer 000-site2.conf).
Zaštita važi za ceo server: UFW, Fail2ban, CrowdSec, ModSecurity i Suricata već rade i novi sajt pokrivaju automatski, ne treba ih posebno podešavati. Portovi 80/443 su takođe već otvoreni. Sajt ima sopstvene logove: site2_error.log i site2_access.log u /var/log/apache2/.
Direktorijum novog sajta nemojte stavljati unutar direktorijuma kontrolne table — veb koren kontrolne table uređuje sopstveni .htaccess (front kontroler), pa bi ugnežđeni sajt isporučivao nešto drugo nego što očekujete. Držite sajtove jedan pored drugog: /var/www/monitor, /var/www/site2.

39. Oporavak pristupa (izgubljen ključ, lozinka, IP-blok)

Ako ne možete da se prijavite — sve se popravlja direktno u bazi sa servera. Otvorite bazu (ime — iz config.php):

sudo mysql MY_DB

Izgubljen WebAuthn ključ (ne prolazi drugi faktor) — isključite 2FA, prijavite se lozinkom, registrujte novi ključ:

UPDATE users SET webauthn_enabled = 0;

Zaboravili ste lozinku — postavite novi heš (generišite ga na serveru i unesite):

# Generisati heš nove lozinke: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # U bazi (unesite dobijeni heš): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

Zaključali ste sebe IP-filterom — isključite ograničenje:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
Pristup bazi postoji uvek: sudo mysql na serveru, ili phpMyAdmin / odeljak baze u kontrolnoj tabli hostinga. Nakon oporavka ponovo uključite WebAuthn i IP-filter.

40. Svi cron poslovi na jednom mestu

Pregled poslova nalazi se u root cron-u servera (dodaju se preko sudo crontab -e). Ostavite samo redove za alate koje koristite; prilagodite putanje svom serveru.

# Serverski cron monitora (root) — upišite preko: sudo crontab -e # 01:30 — ClamAV skeniranje po rizičnim putanjama (web, home, temp) → kartice „Provereno fajlova“ i „Poslednje skeniranje“ 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — provera integriteta fajlova AIDE (potreban izričit --config) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # pri pokretanju — vratiti prava /var/lib/aide (paketni tmpfiles fajl # aide-common.conf ih vraća na 0700, pa kontrolna tabla više ne vidi bazu) @reboot chmod 755 /var/lib/aide # 03:00 — bezbednosni audit Lynis 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — ažuriranje blok-liste ipsum (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # ipsum skup pri pokretanju podiže servis ipsum-load.service (PRE firewall-a, inače # UFW neće videti skup u before.rules) — nije cron. Ovde je samo dnevni refresh iznad. # 06:00 — Logwatch izveštaj 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # svakih 30 min — provera diskova SMART */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — integritet paketa debsums 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — izveštaj po rasporedu na Email i Telegram 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # svakog sata — osvežavanje liste paketa (za karticu „Bezbednosna ažuriranja“) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # svakih 5 min — snimak resursa (CPU/RAM/mreža/disk) za stranicu „Performanse“ */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # na svakih 5 min, pomereno u odnosu na snimak iznad — senzor bezbednosnih događaja: # nove blokade, IDS uzbune, zaustavljena zaštita, otvoren port. # Dok je nadzor isključen u podešavanjima, posao ne radi ništa. 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # na svakih 15 min — pregled servera u korisnički nalog, da bi se više servera # videlo u jednom spisku. Dok je pregled isključen, posao ne radi ništa. 3,18,33,48 * * * * /usr/local/bin/fleet-push-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Detalji o svakom nalaze se u odgovarajućim odeljcima. Poslovi rezervnih kopija (prethodni odeljak) dodaju se u isti cron. Nakon izmena proverite: sudo crontab -l i da je cron servis aktivan.
Vreme cron-a = vremenska zona servera, a ne TIMEZONE iz config.php. Konstanta TIMEZONE utiče samo na PHP (kako kontrolna tabla prikazuje datume), ali cron demon pokreće poslove po sistemskom vremenu OS-a. Ako se zona servera ne poklapa sa vašom, izveštaj „08:00“ stiže u pogrešno vreme. Primer: server je u drugoj zoni (Europe/London, UTC+1), a vi u Beogradu (UTC+2) → izveštaj „08:00“ stiže u 09:00 po vašem vremenu. Proverite i po potrebi uskladite sistemsku zonu sa svojom:
# Proveriti trenutnu zonu servera: timedatectl # Postaviti svoju zonu (primer) i restartovati cron: sudo timedatectl set-timezone Europe/Belgrade sudo systemctl restart cron
Nakon toga red 0 8 * * * odradiće u 08:00 po lokalnom vremenu. U suprotnom biste morali da pomerate sam cron, ali pri prelasku na zimsko/letnje vreme pomak bi se opet razišao — zato je ispravnije podesiti sistemsku zonu.
Gotove skripte-omotači. Njihove radne kopije i primer crontab-a (crontab.txt) nalaze se u folderu system/ pored projekta, izvan public_html. To nije deo sajta — ne treba ih otpremati u web-koren; smestite ih na server po sistemskim putanjama (kao u crontab-u iznad):
  • lynis-scan.sh → /usr/local/bin/ (chmod +x) — pokreće lynis audit system, tokom skeniranja postavlja fleg /tmp/lynis-running i kopira lynis-report.dat u data/lynis/ kontrolne table;
  • logwatch_daily.sh → /usr/local/bin/ (chmod +x) — formira dnevni Logwatch izveštaj (sshd, fail2ban, sudo, postfix) u data/logwatch/;
  • smart-scan.sh → /usr/local/bin/ (chmod +x) — snima stanje diskova (smartctl) u data/disk/;
  • debsums-scan.sh → /usr/local/bin/ (chmod +x) — proverava integritet paketa (debsums) u data/debsums/;
  • clamav-scan.sh → /usr/local/bin/ (chmod +x) — ClamAV antivirusno skeniranje po rizičnim putanjama (web, home, temp); upisuje pregled u /var/log/clamav/scan.log, odakle ga čita stranica ClamAV (red 01:30 u crontab-u iznad);
  • load-ipsum.sh → /usr/local/bin/ (chmod +x) — ažurira ipset skup ipsum (level 1) na licu mesta, bez kidanja aktivnih pravila fajervola (red 04:00 u crontab-u iznad);
  • daily-report-all.sh → /usr/local/bin/ (chmod +x) — pokreće izveštaj cron/daily_report.php kontrolne table (red 08:00 u crontab-u iznad);
  • daily_report.php — već je deo kontrolne table (cron/daily_report.php), pokreće se preko daily-report-all.sh, ne treba ga posebno postavljati;
  • collect-metrics-all.sh → /usr/local/bin/ (chmod +x) — pokreće cron/collect_metrics.php kontrolne table (stranica „Performanse“, red */5 u crontab-u iznad); collect_metrics.php je već deo kontrolne table, ne treba ga posebno postavljati;
  • security-watch-all.sh → /usr/local/bin/ (chmod +x) — pokreće cron/security_watch.php kontrolne table u ime vlasnika sajta (stranica „Bezbednosni događaji“, red 2-57/5 u crontab-u iznad); security_watch.php već ulazi u sastav kontrolne table i ne instalira se posebno;
  • fleet-push-all.sh → /usr/local/bin/ (chmod +x) — šalje pregled servera u korisnički nalog preko cron/fleet_push.php kontrolne table (red 3,18,33,48 iznad);
  • crontab.txt (system/cron/) — primer poslova; potrebne redove upišite preko sudo crontab -e.
Putanja do skripte u crontab-u mora se poklapati sa mestom gde ste je postavili.
Kako smestiti skriptu u /usr/local/bin/. Direktno iz FileZilla tamo ne možete upisati — direktorijum pripada root-u, i SFTP-klijent će dobiti SSH_FX_PERMISSION_DENIED. Redosled je ovakav: prvo otpremiti fajl u /tmp (tamo svi mogu da pišu), zatim ga jednom komandom premestiti na mesto:
# u FileZilla: u polje „Udaljeni sajt“ uneti /tmp i tamo otpremiti skriptu, # zatim preko SSH (install odmah postavlja vlasnika i prava, chown/chmod nisu potrebni): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # provera: fajl je na mestu, prava rwxr-xr-x, sintaksa je ispravna bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
Ne pomešajte direktorijume: potreban je /tmp u korenu servera — ne /var/tmp i ne tmp/ unutar same kontrolne table (poslednji pripada www-data-u i zatvoren je za vašeg korisnika). U stablu FileZilla /tmp je grana najvišeg nivoa, pored var, a ne unutar njega.
Postavljali ste server automatskim podešavanjem? Ovi omotači i njihovi cron poslovi već su instalirani skriptom (u /usr/local/bin/, log — /var/log/arciveo-cron.log) — ručno ne treba ništa raditi.
Gde skripte traže kontrolnu tablu. Omotači su domenski neutralni: pronalaze instalacije kontrolne table prolazeći kroz /home/*/web/*/public_html i /var/www/*, i stavljaju izveštaje u njihov data/. Ako je kontrolna tabla na drugoj putanji — dodajte je u red for app in … unutar skripti, inače izveštaji Lynis/SMART/debsums/Logwatch neće stići u kontrolnu tablu.
cron.log i prava pristupa. Fajl logs/cron.log prvi kreira root cron — pripadaće root-u, i kartica „Cron dnevnik“ u kontrolnoj tabli neće moći ni da ga pročita ni da ga očisti. Kreirajte fajl unapred u ime web-korisnika (vlasnik direktorijuma sajta; na HestiaCP to je nalog, npr. admin) — tada će root cron samo dopisivati, ne menjajući vlasnika:
# kreirati unapred kao web-korisnik (pre dodavanja cron redova): sudo -u OWNER touch /path/to/monitor/logs/cron.log # ako je cron.log već kreirao root cron — dodeliti web-korisniku: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
Saznati vlasnika direktorijuma: stat -c %U /path/to/monitor.
Upravljanje iz kontrolne table. U odeljku „Sistem“ postoji stranica „Crontab“ — poslove možete pregledati i dodavati bez SSH. Kontrolna tabla uređuje samo poslove dodate preko nje same (poseban blok u root-crontab-u, označen servisnim komentarima); sve što je već u crontab-u (spisak iznad) prikazano je tamo kao read-only spisak „Ostali poslovi servera“ sa dugmetom „Kopiraj u editor“ — ono samo prenosi raspored/komandu u formu za dodavanje, izvorni red ne dira. Da biste postojeći posao „preveli“ pod upravljanje kontrolne table — kopirajte ga u editor, sačuvajte, zatim ručno obrišite stari red (sudo crontab -e), inače će se izvršavati dvaput.
Jednokratno podešavanje na serveru. Stranici je potrebna privilegovana skripta-omotač — ne goli sudo crontab (to bi bila direktna eskalacija do root-a za svakoga ko dobije pristup sesiji kontrolne table), već uska skripta sa dve komande (list/set), koja dira samo svoj blok između servisnih komentara. Instalirajte jednom:
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
Web-korisnik može da se razlikuje od www-data — proverite pod kim radi PHP-FPM pul sajta (ps -o user= -C php-fpm) i unesite ga u sudoers red.
Novi fajl otpremljen sa pogrešnim vlasnikom — stranica odgovara „Access denied.“. Ako je fajl public/crontab_monitor.php otpremljen preko FTP/SFTP pod drugim sistemskim korisnikom (na primer, root) nego ostali fajlovi sajta, web-server neće moći da ga pročita. Uporedite vlasnika i prava sa susednim fajlom i uskladite:
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

Dijagnostika

41. Alat je instaliran, ali prikazuje „Nije instaliran“

Monitor otkriva prisustvo alata putem dpkg-query — APT baze paketa. Ako alat nije instaliran putem apt (ručno, iz snap ili iz izvornog koda), dpkg ga ne vidi.

# Provera putem dpkg: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # Pronaći putanju do binarnog fajla: which ufw fail2ban-client auditctl # Test sudo od www-data: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

42. Rešavanje problema (500, nema podataka)

Greška 500 — proverite logove PHP, nginx i samog monitora:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # Logovi monitora: tail -50 logs/monitor_$(date +%Y-%m-%d).log # Dozvole na fascikle: ls -la data/ tmp/ logs/
Kontrolna tabla na hosting-panelu (HestiaCP, ISPmanager, cPanel)? Tamo PHP ne radi pod www-data, već pod korisničkim nalogom (na primer admin — vlasnik direktorijuma sajta). Sva sudo-pravila i članstvo u grupama (adm, systemd-journal) treba dodeliti tom korisniku, inače će moduli prikazati „Nije aktivan / 0“ iako servisi rade. Da saznate stvarnog PHP korisnika: ps -o user= -C php-fpm | sort -u ili vlasnik direktorijuma sajta stat -c '%U' /path/to/monitor. Dalje u svim komandama ispod umesto www-data upišite njega. Automatska instalacija sama određuje veb-korisnika i za njega upisuje sudoers.

Podaci se ne prikazuju — gotovo uvek su u pitanju nepodešena sudo-prava. Proverite konkretnu komandu kao veb-korisnik (zamenite www-data svojim). Flag -n = bez lozinke, kao kod PHP — ako traži lozinku, znači da u sudoers nema pravila:

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
Modul prikazuje „Nije aktivan“ / „0“, iako alat radi (na primer sudo aa-status u terminalu prikazuje profile, a stranica „AppArmor“ — „Neaktivan“). Uzrok: veb-korisnik nema sudo-pravo na komandu tog modula. Proverite je iz spiska iznad: ako traži lozinku — dodajte nedostajući red u /etc/sudoers.d/monitor („Podešavanje sudo“). Česte „nove“ komande: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
Ako je konkretna stranica (Falco, ModSecurity, Auditd, otvoreni portovi UFW) prazna — uporedite sa spiskom u odeljku o sudo: verovatno nije dozvoljen apache2ctl, ausearch, aa-status ili ss, ili veb-korisnik nije u grupama adm/systemd-journal (odatle se čitaju logovi fail2ban/auth/modsec i journalctl — Falco i događaji kernela).

43. Stranica je prazna, iako podaci na serveru postoje

Simptom: na serveru podaci postoje (vidljivi kroz shell), a stranica prikazuje „nema podataka“ ili pogrešan status — na primer AIDE prijavljuje „Nije inicijalizovana“, iako je baza kreirana.

Uzrok je open_basedir: mnoge kontrolne table i hostinzi ograničavaju PHP-FPM pul na direktorijum domena, pa se PHP funkcije file_exists(), file_get_contents(), filemtime() po sistemskim putanjama (/var/lib/aide, /var/log, /proc…) blokiraju. Monitor to zaobilazi tako što takve putanje čita standardnim sistemskim komandama (cat, test, stat).

# Da li je fajl vidljiv kroz shell (tako ga monitor čita): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # Trenutna vrednost open_basedir za pul domena: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
Ako shell „vidi“ fajl (VISIBLE), a stranica ne — to je open_basedir. Ispravno rešenje je čitanje sistemskim komandama (već urađeno za AIDE i Mrežni monitor). Nije potrebno proširivati open_basedir na /var, /proc, a i manje je bezbedno.

44. SSL stranica ne radi

Monitor proverava sertifikate povezujući se sa domenima direktno preko porta 443. Ako domen nije dostupan sa samog servera ili je port zatvoren fajervolom — provera neće uspeti.

# Ručna provera sertifikata: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # Provera dostupnosti: curl -I https://monitor.example.com
Domene Monitor automatski preuzima iz konfiguracija nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) i Apache (/etc/apache2/sites-enabled/) plus trenutni host iz HTTP_HOST.
Automatsko otkrivanje poddomena. Poddomeni se automatski otkrivaju iz javnih Certificate Transparency logova i proveravaju preko mreže — čak i ako se nalaze na drugim serverima. Ništa ne treba dodavati ručno.

45. Vidljiva je samo jedna baza od više njih

Monitor se povezuje na MySQL kao korisnik iz config.php koji ima pristup samo svojoj bazi. MySQL u information_schema prikazuje samo baze na kojima ima privilegije — zato ostale nisu vidljive.

Da bi monitor video sve baze, dajte ovom korisniku pravo samo za čitanje (jednom, kao root; unesite korisničko ime iz config.php):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* daje samo pravo čitanja — ništa se ne može izmeniti, obrisati ni kreirati, što je bezbedno za nadzor.
Bez ovog GRANT-a kontrolna tabla vidi samo svoju bazu — to nije greška, već ograničenje prava. Nikakav sudo mysql kontrolna tabla ne koristi: spisak baza uzima preko sopstvene PDO veze.

46. PostgreSQL se ne prikazuje na stranici „Baza podataka“

PostgreSQL zahteva pristup na nivou korisnika postgres, koji veb-korisnik kontrolne table nema. Otvaranje širokog sudo psql iz PHP-a nije bezbedno — umesto toga kontrolna tabla poziva usku omotač-skriptu bez parametara, koja samo ispisuje verziju, broj konekcija i listu baza sa veličinama. Kreirajte je:

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 # u /etc/sudoers.d/monitor (korisnik = onaj pod kojim radi PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
Ako ne koristite PostgreSQL — uklonite red monitor-pgstat iz sudoers (korak 13 ručne instalacije) i sam skript nemojte kreirati: kartica PostgreSQL će ostati jednostavno neaktivna.

47. Aktivirao se alert — šta dalje

Kontrolna tabla prikazuje šta se dešava; u nastavku — šta činiti u tipičnim situacijama. Opšte pravilo: bez panike, uporedite sa legitimnom aktivnošću (vaše radnje, ažuriranja, rezervne kopije) i reagujte prema ozbiljnosti.

  • Mapa napada / mnogo fail2ban banova — to je normalno za svaki server na internetu (botovi stalno probaju SSH/veb). Bitno je da banovi rade. Uverite se da je prijava preko SSH — samo ključem (lozinka isključena) i da je vaša IP adresa u ignoreip.
  • ModSecurity je blokirao zahteve — WAF odbija napade na sajt, to mu je posao. Ako se blokira vaš legitiman saobraćaj (lažno okidanje) — nađite rule id u detaljima i dodajte izuzetak u CRS konfiguraciju.
  • AIDE: izmenjeni fajlovi — uporedite listu sa onim što ste radili (ažuriranje paketa, izmena konfiguracija — normalno). Izmene sistemskih binarnih fajlova koje niste dirali — razlog za oprez. Nakon legitimnih izmena ažurirajte AIDE bazu.
  • debsums: izmenjeni binarni fajlovi/biblioteke (van /etc, van /usr/share) — potencijalna podmena. Proverite paket: debsums PACKAGE_NAME, ako sumnjate — ponovo ga instalirajte (apt install --reinstall).
  • ClamAV / maldet: pronađena pretnja — proverite fajl u karantinu, ne otvarajte ga. Ako je to veb-šel u direktorijumu sajta — izolujte server i tražite tačku ulaska (ranjiv dodatak, curenje pristupnih podataka).
  • Falco: kritični događaji (pokretanje shell-a u kontejneru, pristup osetljivim fajlovima) — analizirajte događaj: čiji proces, šta ga je pokrenulo. Često je to legitimna administratorska aktivnost.
  • Spoljna izloženost: crveno za baze/keš — odmah zatvorite: vežite servis za 127.0.0.1 ili zatvorite port u UFW. To je stvarna rupa.
  • SSL ističe / istekao — obnovite sertifikat (Let's Encrypt se obnavlja sam; ako ne — proverite certbot renew ili podešavanja u kontrolnoj tabli).
  • Bezbednosna ažuriranja čekaju — instalirajte: sudo apt update && sudo apt upgrade; nakon ažuriranja kernela ponovo pokrenite server.
Znaci stvarnog upada (nepoznati procesi/korisnici, izmenjeni binarni fajlovi, odlazni spam, nepoznati cron zadaci): isključite server sa spoljnog pristupa, napravite rezervnu kopiju za analizu i, ako su podaci kritični, podignite čist server iz pouzdane rezervne kopije — pouzdano ukloniti rootkit je teško.