Sicurezza VPS per hosting siti: guida Ubuntu 24.04 passo passo
Un VPS appena acceso è esposto a Internet con impostazioni pensate per funzionare, non per resistere agli attacchi. Per mettere in sicurezza un VPS Ubuntu 24.04 che ospita siti bastano pochi interventi mirati: accesso SSH solo con chiavi, firewall con le sole porte necessarie, fail2ban, aggiornamenti di sicurezza automatici, un utente Linux e un pool PHP-FPM separati per ogni sito, scansioni antimalware e backup fuori dal server. In questa guida trovi i comandi per farlo a mano; in fondo vediamo cosa fa già Koapanel appena installato.
Da dove arrivano davvero gli attacchi
Su un server di hosting i problemi nascono quasi sempre da tre cause:
- password deboli su SSH, sul pannello o su wp-admin, provate a raffica da bot automatici;
- plugin e temi vulnerabili (soprattutto WordPress) che permettono di caricare una web shell;
- siti non isolati: se tutti i siti girano con lo stesso utente, un sito compromesso legge e modifica tutti gli altri.
Ogni passo che segue chiude una di queste porte. L'ordine conta: prima l'accesso, poi la rete, poi i siti.
1. SSH: chiavi, niente password, niente root con password
Sul tuo computer genera una chiave (se non ne hai già una) e copiala sul server:
ssh-keygen -t ed25519 -C "tuo-nome@portatile"
ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@IP-DEL-SERVER
Crea un utente amministrativo se lavori ancora come root:
sudo adduser deploy
sudo usermod -aG sudo deploy
Poi scrivi le impostazioni in un file separato. Su Ubuntu 24.04 /etc/ssh/sshd_config include per prima cosa /etc/ssh/sshd_config.d/*.conf, e in SSH vince il primo valore letto: un file che inizia con 00- ha la precedenza anche su 50-cloud-init.conf, che su molti VPS riattiva le password.
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
Controlla la sintassi e riavvia il servizio (su Ubuntu si chiama ssh, non sshd):
sudo sshd -t && sudo systemctl restart ssh
Tieni aperta la sessione attuale e prova ad entrare da un secondo terminale prima di chiudere la prima. Se vuoi cambiare anche la porta, ricorda che Ubuntu 24.04 usa l'attivazione tramite socket: dopo la modifica servono sudo systemctl daemon-reload e sudo systemctl restart ssh.socket.
2. Firewall con ufw
ufw è già presente su Ubuntu. Apri solo quello che serve: SSH, web e, se c'è, il pannello.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status verbose
limit blocca temporaneamente un indirizzo che apre 6 o più connessioni in 30 secondi: un primo filtro contro i tentativi a raffica. MariaDB non va mai aperto verso Internet: su Ubuntu ascolta già solo su 127.0.0.1 (bind-address in /etc/mysql/mariadb.conf.d/50-server.cnf). Verifica cosa è in ascolto con:
sudo ss -tulpn
Attenzione se usi Docker: le porte pubblicate dai container scavalcano le regole di ufw, quindi vanno controllate a parte.
3. fail2ban contro i tentativi ripetuti
sudo apt update && sudo apt upgrade
sudo apt install fail2ban
Aggiorna i pacchetti prima: la versione di fail2ban uscita con Ubuntu 24.04 aveva un problema con Python 3.12, corretto negli aggiornamenti. Non modificare jail.conf: crea /etc/fail2ban/jail.local.
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
bantime.increment = true
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
[sshd]
enabled = true
Sostituisci 203.0.113.10 con l'IP del tuo ufficio. Poi:
sudo systemctl enable --now fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Per sbloccare un indirizzo: sudo fail2ban-client set sshd unbanip 198.51.100.7.
4. Aggiornamenti di sicurezza automatici
Su Ubuntu Server unattended-upgrades è di solito già installato. Verifica che sia attivo:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
sudo unattended-upgrade --dry-run --debug
Il comportamento si regola in /etc/apt/apt.conf.d/50unattended-upgrades. La scelta più prudente per un server di hosting è installare da soli i soli aggiornamenti di sicurezza e riavviare a mano in un momento tranquillo (Unattended-Upgrade::Automatic-Reboot "false";). Per sapere se serve un riavvio:
cat /var/run/reboot-required 2>/dev/null || echo "Nessun riavvio richiesto"
5. Un utente Linux e un pool PHP-FPM per ogni sito
È il punto che fa la differenza tra "un sito bucato" e "tutto il server bucato". Crea un utente di sistema senza shell per il sito:
sudo useradd --system --user-group --home-dir /var/www/esempio.it --shell /usr/sbin/nologin sito_esempio
sudo mkdir -p /var/www/esempio.it/{public_html,tmp,logs}
Poi un pool dedicato in /etc/php/8.3/fpm/pool.d/esempio.it.conf (8.3 è la versione PHP di Ubuntu 24.04):
[esempio.it]
user = sito_esempio
group = sito_esempio
listen = /run/php/php8.3-fpm-esempio.it.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 30s
php_admin_value[open_basedir] = /var/www/esempio.it/:/tmp/
php_admin_value[upload_tmp_dir] = /var/www/esempio.it/tmp
php_admin_value[session.save_path] = /var/www/esempio.it/tmp
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen
php_admin_flag[expose_php] = off
disable_functions può rompere qualche plugin che lancia comandi: provalo sito per sito. Verifica e ricarica:
sudo php-fpm8.3 -t && sudo systemctl reload php8.3-fpm
Nel blocco server di nginx, fastcgi_pass punta al socket del sito (unix:/run/php/php8.3-fpm-esempio.it.sock), e ogni sito ha il suo.
6. Permessi dei file
PHP gira con l'utente del sito, nginx (www-data) deve solo leggere. Uno schema semplice: proprietario il sito, gruppo www-data, cartelle con il bit setgid così i file nuovi ereditano il gruppo.
sudo chown -R sito_esempio:www-data /var/www/esempio.it
sudo find /var/www/esempio.it -type d -exec chmod 2750 {} +
sudo find /var/www/esempio.it -type f -exec chmod 640 {} +
sudo chmod 600 /var/www/esempio.it/public_html/wp-config.php
Niente 777, mai: se un plugin lo chiede, il problema è l'utente con cui gira PHP, non i permessi.
7. WordPress: le protezioni che contano
WordPress è il bersaglio più frequente perché è il più diffuso. Le misure più utili:
- niente PHP nella cartella uploads e XML-RPC chiuso, direttamente in nginx:
location ~* ^/wp-content/uploads/.*\.php$ { deny all; }
location = /xmlrpc.php { deny all; }
- login limitato: nel blocco
httpdi nginxlimit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m;e nellalocation = /wp-login.phplimit_req zone=wplogin burst=5 nodelay;(insieme alle solite direttive FastCGI); - editor dei file disattivato in
wp-config.php:define('DISALLOW_FILE_EDIT', true); - controllo dell'integrità con WP-CLI, eseguito come utente del sito:
sudo -u sito_esempio wp core verify-checksums --path=/var/www/esempio.it/public_html
sudo -u sito_esempio wp plugin verify-checksums --all --path=/var/www/esempio.it/public_html
- aggiornamenti costanti di core, plugin e temi, e rimozione di quelli inutilizzati.
Per l'impostazione completa di un server WordPress vedi anche la guida hosting WordPress su VPS.
8. Scansione antimalware
ClamAV riconosce i malware noti; per le web shell PHP servono anche controlli euristici.
sudo apt install clamav clamav-daemon
sudo systemctl enable --now clamav-freshclam
sudo clamscan -r -i --max-filesize=20M /var/www
Il demone clamd tiene in memoria le firme (oltre un gigabyte di RAM): su un VPS da 2 GB conviene usare solo clamscan di notte. Due controlli rapidi che trovano molte infezioni:
sudo find /var/www -path '*/wp-content/uploads/*' -name '*.php'
sudo find /var/www -type f -name '*.php' -mtime -2
Il primo elenca file PHP negli upload (quasi sempre sospetti), il secondo i PHP modificati negli ultimi due giorni.
9. Backup fuori dal server
Nessuna di queste misure sostituisce un backup. Copia file e database su uno storage esterno, cifrati, con più versioni conservate. Lo spieghiamo passo passo in backup dei siti su S3 con restic.
10. Monitoraggio minimo
Non serve uno stack complesso per accorgersi dei problemi:
systemctl --failed
last -a | head -20
sudo journalctl -u ssh --since today | grep -i accepted
df -h
Aggiungi un controllo esterno di disponibilità (qualsiasi servizio di uptime che ti avvisa via email) e un avviso quando il disco supera il 90%: un disco pieno ferma database e posta.
Cosa fa Koapanel appena installato
Se non vuoi mantenere tutto questo a mano, Koapanel applica gran parte di queste misure da solo su Ubuntu 24.04. Secondo il manuale:
| Misura | In Koapanel |
|---|---|
| Firewall | ufw gestito dalla pagina Sicurezza: regole consenti, rifiuta o limita, anche per singolo IP; le regole di SSH e del pannello non si possono eliminare, così non ti chiudi fuori |
| fail2ban | indirizzi bloccati visibili, sblocco e blocco manuale, tentativi, durata, finestra e IP mai bloccati configurabili |
| Aggiornamenti di Ubuntu | aggiornamenti di sicurezza automatici attivi dopo l'installazione, riavvio automatico facoltativo, elenco dei pacchetti in attesa (aggiornamenti) |
| Isolamento | per ogni sito utente Linux, pool PHP-FPM, open_basedir, tmp e sessioni private |
| Accesso ai file | solo SFTP (niente FTP), chiuso nella cartella del sito e senza comandi; chiavi SSH al posto della password |
| WordPress | login limitato a 10 tentativi al minuto, fail2ban su login e XML-RPC, XML-RPC chiuso, PHP bloccato negli upload, editor disattivato, file sensibili non scaricabili, integrità controllata ogni notte (WordPress) |
| Antimalware | scanner euristico integrato + ClamAV, con modalità scelta in base alla RAM (demone da 4 GB, su richiesta sui server più piccoli), scansioni notturne incrementali a bassa priorità (antimalware) |
| Tempo reale | ogni file PHP, JS, HTML, SVG, .htaccess o .user.ini scritto in un sito viene controllato pochi secondi dopo; solo i rilevamenti certi vanno subito in quarantena (protezione in tempo reale) |
| Quarantena | reversibile: ripristino, falso positivo, riparazione del core WordPress senza toccare wp-content |
| Registro e avvisi | registro di chi ha fatto cosa, email per disco oltre il 90%, backup non riuscito, password cambiata |
| Backup | restic cifrato su S3 o disco (backup e ripristino) |
Anche le chiavi S3 e i token DNS sono salvati cifrati sul server, e gli aggiornamenti del pannello sono firmati: il pannello controlla la firma prima di installarli.
Cosa resta a te
- La configurazione di SSH per il tuo accesso amministrativo (sezione 1). Attenzione: se dai ai clienti l'accesso SFTP con password generata dal pannello, non disattivare le password per tutti. Metti in fondo a
/etc/ssh/sshd_configun bloccoMatch User root,deployconPasswordAuthentication no, oppure usa solo chiavi anche per SFTP. - Un backup esterno configurato davvero, con la password del repository conservata lontano dal server.
- Il monitoraggio esterno della disponibilità dei siti.
Per onestà: Koapanel non include un web application firewall. Se ti serve un WAF con regole commerciali, soluzioni come Imunify360 sull'ecosistema cPanel/CloudLinux coprono di più, a un costo maggiore. Koapanel inoltre gira solo su Ubuntu 24.04 con nginx: niente Apache e niente .htaccess come meccanismo di configurazione.
Domande frequenti
Cambiare la porta SSH serve?
Riduce i tentativi automatici nei log, ma non protegge da chi ti cerca davvero. La protezione vera è l'accesso solo con chiavi più fail2ban.
Basta ClamAV per trovare le web shell?
No. ClamAV riconosce soprattutto malware già noti; molte web shell PHP sono offuscate e cambiano spesso. Servono anche controlli euristici e il confronto con i checksum ufficiali di WordPress.
Devo attivare il riavvio automatico dopo gli aggiornamenti?
Su un server con siti in produzione è meglio di no: installa da solo gli aggiornamenti di sicurezza e scegli tu quando riavviare, controllando /var/run/reboot-required.
Un utente per sito rallenta il server?
No in modo apprezzabile. Con pm = ondemand i processi PHP di un sito partono solo quando arrivano richieste, quindi anche molti pool su un VPS piccolo occupano poca memoria.
Koapanel funziona su Debian o Ubuntu 22.04?
No, solo su Ubuntu 24.04 LTS, installato da zero.
Prova su un server nuovo
Puoi seguire questa guida a mano oppure installare Koapanel su un Ubuntu 24.04 appena creato e trovare firewall, fail2ban, isolamento dei siti e antimalware già attivi. È gratuito fino a 3 siti per uso personale:
curl -fsSL https://get.koapanel.app | sudo bash
Vuoi vederlo prima? Apri la demo pubblica oppure leggi la guida all'installazione e i prezzi.