Vai al contenuto principale

#tutorial

Podman: l’alternativa a Docker che ogni sysadmin Linux dovrebbe conoscere

Per anni Docker è stato il default indiscusso quando si parlava di container su Linux. Ma l’architettura basata su un daemon centrale che gira come ro

Altro...

Per anni Docker è stato il default indiscusso quando si parlava di container su Linux. Ma l’architettura basata su un daemon centrale che gira come root ha sempre lasciato sul tavolo un problema di superficie d’attacco: se qualcuno compromette dockerd, ha di fatto accesso root all’intero host. Podman nasce proprio per chiudere questo gap, offrendo un motore container daemonless, compatibile con le immagini OCI e con la CLI Docker, che si integra in modo molto più nativo con systemd e con il modello di permessi di Linux.

Vediamo come installarlo, come si differenzia realmente da Docker oltre gli slogan, e come portarlo in produzione con systemd e le Quadlet, che sono probabilmente la ragione migliore per prenderlo sul serio.

Cos’è Podman, in praticaPodman (da Pod Manager) è un motore container open source senza demone centrale. Ogni container gira come processo figlio dell’utente che lo ha avviato, non come figlio di un servizio di sistema con privilegi elevati. Questo significa che è possibile eseguire container completamente rootless, senza mai invocare sudo, riducendo drasticamente cosa un container compromesso può effettivamente toccare sull’host.

Sotto il cofano Podman usa gli stessi runtime OCI di Docker e parla lo stesso formato immagine, quindi la stragrande maggioranza dei comandi Docker funziona invariata sostituendo semplicemente il nome del binario (o creando un alias docker=podman, oppure installando il pacchetto podman-docker che fa da shim trasparente).

Un concetto che Docker non ha nativamente è quello di pod: gruppi di uno o più container che condividono rete e storage, concettualmente vicini ai pod di Kubernetes. Comodo quando si vogliono far girare insieme più container che devono comunicare come se fossero sulla stessa macchina.

Installazione# Debian/Ubuntu (Debian 11+, Ubuntu 20.10+)
sudo apt-get update
sudo apt-get -y install podman

Fedora/CentOS/RHEL 8+

sudo dnf -y install podman

openSUSE

sudo zypper install podman

Arch/Manjaro

sudo pacman -S podmanVerifica dell’installazione:

podman --version
podman info
podman run hello-worldSe l’ultimo comando restituisce il messaggio di benvenuto di Podman, l’installazione è a posto.

Uso quotidiano: i comandi non cambiano quasi nullaShell interattiva dentro un container Ubuntu:

podman run -it ubuntu bashServizio in background, con Nginx esposto sulla porta 8080 dell’host:

podman run -d --name web -p 8080:80 nginx
podman psIl resto della CLI ricalca Docker praticamente 1:1: podman pull, podman images, podman stop/start, podman rm/rmi. Dietro le quinte, podman build è in realtà un wrapper attorno a Buildah, mentre lo spostamento di immagini tra registry passa per Skopeo: strumenti separati che Podman orchestra per te, senza che serva conoscerli nel dettaglio per l’uso base.

Dove Docker e Podman divergono davveroLa compatibilità è alta ma non totale, e i problemi emergono quasi sempre dal modello rootless. Il caso più comune sono i bind mount: poiché i container rootless usano user namespace e mapping subuid/subgid, una directory montata dall’host non sempre ha la proprietà che il container si aspetta. Su sistemi con SELinux attivo serve anche il suffisso :z o :Z per far ri-etichettare correttamente i file:

podman run -v /host/path:/container/path:Z myimage:z minuscolo condivide il volume tra più container, :Z maiuscolo lo rende privato per un singolo container. Se serve far coincidere esattamente la proprietà con quella dell’host, l’opzione --uidmap permette un controllo fine, oppure si può far girare il container in modalità rootful per replicare il comportamento di Docker.

Altri attriti da conoscere prima di migrare: l’accesso GPU da container rootless è limitato (NVIDIA richiede nvidia-container-toolkit e setup CDI, con i container da ricreare a ogni aggiornamento driver), e i Docker secrets insieme ad alcune configurazioni di rete non hanno una corrispondenza 1:1. Niente di bloccante, ma va testato prima di assumere che la migrazione sia un semplice “find and replace”.

Container come servizi systemd: le QuadletQuesto è probabilmente il motivo migliore per scegliere Podman in un contesto server. Invece di lasciare un demone in background a gestire lo stato dei container, si delega tutto a systemd, che diventa responsabile di avvio, riavvio e supervisione, esattamente come per qualsiasi altro servizio di sistema.

Il meccanismo si chiama Quadlet: un file dichiarativo con estensione .container che Podman traduce automaticamente in una unit systemd. Per un servizio utente rootless, il file va in ~/.config/containers/systemd/. Esempio minimo per Nginx:

[Container]
ContainerName=web
Image=docker.io/library/nginx:latest
PublishPort=8080:80

[Install]
WantedBy=default.targetAttivazione:

systemctl --user daemon-reload
systemctl --user start webDa questo momento il container è gestito da systemd come un servizio qualsiasi: si riavvia in caso di crash, si integra con i log di journald, si può abilitare al boot. Aggiungendo l’etichetta AutoUpdate=registry a un container, inoltre, podman auto-update può controllare periodicamente nuove versioni dell’immagine e riavviare il servizio in automatico, senza bisogno di Watchtower o strumenti equivalenti.

Migrare da Docker ComposeChi ha un’infrastruttura basata su Compose ha due strade percorribili. La prima è continuare a usare Compose così com’è: il binario standalone docker compose può puntare al socket di Podman senza toccare i file docker-compose.yml esistenti:

systemctl --user enable --now podman.socketLa seconda è convertire i file Compose in Quadlet, così che sia systemd a gestire tutto nativamente. Scrivere le unit a mano è tedioso, quindi conviene usare podlet, un tool che legge un docker-compose.yml e genera i file Quadlet corrispondenti. C’è una curva di apprendimento, ma è comunque più veloce che partire da zero.

Docker resta rilevanteNonostante i vantaggi di Podman, Docker non sta scomparendo. L’ecosistema attorno a Docker (Compose, Swarm, e tutta la tooling che si integra con esso, inclusi molti sistemi CI/CD già configurati per il socket Docker) resta enorme, e non tutte le piattaforme gestiscono bene le peculiarità rootless di Podman. Se un team è già standardizzato su Docker, spesso ha più senso restare sull’esistente piuttosto che affrontare una migrazione per un guadagno marginale.

Dove Podman convince davvero è quando si parte da zero: setup più sicuro per default, nessun demone da tenere sotto controllo, integrazione diretta con systemd per la gestione del ciclo di vita dei servizi.

ConclusionePodman è un motore container completo, compatibile con Docker, che funziona senza demone e senza bisogno di privilegi root. Per l’uso quotidiano è quasi un drop-in replacement: si installa dal repository della distribuzione, si usano gli stessi comandi (o si crea l’alias docker=podman), e si ottengono benefici di sicurezza concreti senza dover reimparare nulla. I limiti di compatibilità, soprattutto su bind mount, GPU e secrets, vanno conosciuti e testati prima di una migrazione in produzione, ma per chi sta impostando nuovi ambienti containerizzati su Linux, specialmente se pensa di gestirli con systemd e Quadlet, vale decisamente la pena valutarlo.

Fonte originale: Hayden James, “Docker Alternative: Podman on Linux”, LinuxBlog.io.

#linux #container #devops #docker #guide #howto #podman #tutorial

0 0 0

C# 15 introduce le union: basta OneOf e Results per modellare i tipi (.NET 11 Preview 6)

Da anni gli sviluppatori C# aspettano un modo nativo per dire “questo valore è esattamente uno tra questi tipi, e nient’altro”, con il compilatore in

Altro...

Da anni gli sviluppatori C# aspettano un modo nativo per dire “questo valore è esattamente uno tra questi tipi, e nient’altro”, con il compilatore in grado di garantirlo. In assenza di un supporto di linguaggio, la community si è arrangiata con pattern come Results<T> di ASP.NET Core Minimal API o con librerie come OneOf. Funzionano, ma con un limite strutturale: se aggiungi un quarto caso possibile a una funzione che prima ne restituiva tre, nessuno ti avvisa che uno switch a valle non gestisce il nuovo tipo. Manca l’esaustività, che è poi il punto centrale delle discriminated union.

Con .NET 11 Preview 6 (rilasciata il 14 luglio 2026) e C# 15, questa lacuna si chiude: arriva la parola chiave union, insieme a un intero pacchetto di funzionalità correlate (conversioni implicite, pattern matching esaustivo, gestione della nullabilità) che rendono i union type un cittadino di prima classe del linguaggio.

La sintassi: dichiarare un union typeLa forma più semplice è la union declaration, una sintassi compatta che genera automaticamente uno struct:

public union Pet(Cat, Dog, Bird);Questa singola riga dice al compilatore che un Pet è esattamente un Cat, un Dog o un Bird, e nient’altro. Sotto il cofano, il compilatore genera uno struct che implementa l’interfaccia System.Runtime.CompilerServices.IUnion e conserva il valore effettivo in una proprietà Value di tipo object?.

I union generici sono immediatamente utili per modellare risultati di operazioni che possono fallire, un caso d’uso ricorrentissimo in codice di produzione:

public union Result<TSuccess, TError>(TSuccess, TError);

Result<User, Error> Register(string username)
{
if (string.IsNullOrEmpty(username))
return new Error("Username cannot be empty");

return new User(username);

}Da notare l’ultima riga: nessun wrapping esplicito, nessuna chiamata a un factory method. Il valore User o Error viene convertito implicitamente in Result<User, Error> grazie alle union conversion generate automaticamente per ogni case type.

Pattern matching esaustivo, finalmenteIl vero salto di qualità è nel matching. Se dimentichi un caso in uno switch su un union type, il compilatore te lo dice:

string Describe(Pet pet) => pet switch
{
Dog d => d.Name,
Cat c => c.Name,
// CS8509: switch expression does not handle all
// possible values of its input type (Bird)
};Aggiungendo il caso mancante, l’avviso scompare, e non serve più il classico _ => throw new InvalidOperationException("unreachable") per zittire il compilatore:

string Describe(Pet pet) => pet switch
{
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};Il punto interessante è che questa esaustività è dinamica: se in futuro aggiungi un nuovo case type al union (per esempio un quarto animale), ogni switch esistente che non lo gestisce si illumina di un warning. Per chi ha inseguito bug di produzione causati da un case dimenticato in un evento di dominio, è un cambiamento non da poco.

I pattern si applicano direttamente al union, senza bisogno di accedere manualmente a .Value: il compilatore effettua l’unwrapping in automatico, anche negli if pattern classici:

if (pet is Dog d)
{
Console.WriteLine(d.Name);
}Gestione del nullIl valore di default di un union type ha Value == null, ed è possibile intercettarlo esplicitamente con il pattern null:

string Describe(Pet pet) => pet switch
{
null => "nessun animale",
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};La necessità o meno del ramo null dipende dal fatto che il parametro o il campo union-typed sia nullable: l’analisi di nullabilità del compilatore guida correttamente questi casi, in coerenza con le annotazioni #nullable enable già in uso nella maggior parte delle codebase moderne.

Un caso pratico: modellare eventi di dominioI union type diventano davvero interessanti quando li si combina con i record per il domain modeling, per esempio in un sistema di elaborazione ordini con eventi distinti:

public record OrderPlaced(Guid OrderId, decimal Total);
public record OrderShipped(Guid OrderId, string TrackingNumber);
public record OrderCancelled(Guid OrderId, string Reason);
public union OrderEvent(OrderPlaced, OrderShipped, OrderCancelled);

string Summarize(OrderEvent evt) => evt switch
{
OrderPlaced p => $"Ordine {p.OrderId} piazzato per {p.Total:C}",
OrderShipped s => $"Ordine {s.OrderId} spedito, tracking: {s.TrackingNumber}",
OrderCancelled c => $"Ordine {c.OrderId} annullato: {c.Reason}",
};Quando tra tre mesi qualcuno aggiungerà OrderRefunded al union, ogni handler che non lo gestisce lancerà un warning in fase di compilazione, invece di fallire silenziosamente in produzione. È il compilatore che fa da revisore di esaustività al posto tuo.

I union possono anche esporre metodi e proprietà calcolate (ma non campi d’istanza), utile per incapsulare logica di conversione:

public union Length(Meters, Feet)
{
public double TotalMeters => this switch
{
Meters m => m.Value,
Feet f => f.Value * 0.3048,
_ => throw new InvalidOperationException(),
};
}Union personalizzati con l’attributo [Union]La parola chiave union genera sempre uno struct. Se per motivi di identità, ereditarietà o layout di memoria serve un tipo reference, è possibile costruire un union personalizzato applicando direttamente l’attributo System.Runtime.CompilerServices.UnionAttribute e implementando l’interfaccia IUnion:

[System.Runtime.CompilerServices.Union]
public class Shape : System.Runtime.CompilerServices.IUnion
{
private readonly object? _value;
public Shape(Circle value) { _value = value; }
public Shape(Rectangle value) { _value = value; }
public object? Value => _value;
}Nella grande maggioranza dei casi, però, la sintassi union compatta copre già ogni esigenza pratica: l’approccio con attributo è pensato per scenari con requisiti specifici che lo struct generato non può soddisfare.

Come provarlo oggiI union type sono attualmente in preview. Per sperimentarli serve l’SDK .NET 11 Preview e questa configurazione nel file di progetto:

ConclusioniF# ha le discriminated union fin dalle origini, e la richiesta di un equivalente in C# (csharplang issue #113) è aperta da anni. Con l’arrivo dei union type, non ogni problema di modellazione richiede più una gerarchia di classi: per rappresentare “uno tra un insieme chiuso di tipi”, ora esiste un costrutto di linguaggio dedicato, con conversioni implicite, pattern matching esaustivo e un’ottima integrazione con i record esistenti. Per chi lavora ogni giorno con API che possono restituire risultati eterogenei, o con event sourcing e domain modeling, è una delle novità più concrete della prossima versione di C#.

Fonte: .NET Blog, C# language reference proposal: Unions e Maarten Balliauw.

#c #guide #tutorial #net

0 0 0

Nmap su Linux: la guida pratica a scanning e discovery di rete per sistemisti

Chi amministra server Linux prima o poi si trova a dover rispondere a una domanda apparentemente semplice: “cosa è realmente esposto su questa macchin

Altro...

Chi amministra server Linux prima o poi si trova a dover rispondere a una domanda apparentemente semplice: “cosa è realmente esposto su questa macchina, e su questa rete?” La risposta corretta non arriva mai da un elenco di regole firewall letto a memoria, ma da una verifica attiva. Nmap (Network Mapper) resta lo strumento di riferimento per questo tipo di verifica: open source, nato nel 1997, ancora oggi il punto di partenza per audit di sicurezza, mappatura di reti e troubleshooting di connettività.

In questo articolo vediamo un percorso pratico per usare nmap in scenari reali di amministrazione sistemi: dalla discovery degli host alla scansione delle porte, fino agli script NSE per individuare vulnerabilità e configurazioni deboli.

Nota importante: esegui scansioni solo su reti e host di tua proprietà o per cui hai autorizzazione esplicita. La scansione non autorizzata può costituire reato in molte giurisdizioni, Italia compresa (accesso abusivo a sistema informatico, art. 615-ter c.p.).

InstallazioneNmap è disponibile nei repository di tutte le distribuzioni principali:

Debian/Ubuntu

sudo apt install nmap

Fedora/RHEL/CentOS

sudo dnf install nmap

Arch/Manjaro

sudo pacman -S nmap

Verifica

nmap --versionHost discovery: chi è vivo sulla reteIl primo passo in qualsiasi audit è capire quali host rispondono. Per questo si usa la scansione “ping”, che salta completamente il controllo delle porte:

nmap -sn 192.168.1.0/24Su una rete locale nmap non si limita all’ICMP: usa il protocollo ARP, molto più veloce e capace di scovare anche dispositivi che ignorano i normali ping. Su reti instradate, invece, combina richieste ICMP echo, TCP SYN sulla porta 443, TCP ACK sulla porta 80 e timestamp ICMP. Il risultato è un inventario rapido e silenzioso di ciò che è realmente connesso, utile ad esempio quando serve scoprire quale indirizzo IP il DHCP ha assegnato a un nuovo dispositivo.

Scansione delle porteUna volta identificati gli host attivi, il passo successivo è capire quali servizi espongono. Senza opzioni, nmap scansiona le 1.000 porte TCP più comuni e non richiede privilegi root:

nmap 192.168.1.10Da root, il tipo di scansione predefinito diventa la SYN scan (o “stealth scan”), più veloce perché non completa mai l’handshake TCP a tre vie e lascia meno tracce nei log applicativi:

sudo nmap -sS 192.168.1.10Le 1.000 porte di default lasciano fuori parecchio. Un’istanza MySQL su una porta non standard, o un demone SSH spostato sulla 2222, restano invisibili. Per una copertura completa:

sudo nmap -sS -p- 192.168.1.10 # tutte le 65.535 porte
sudo nmap -p 22,80,443,3306 192.168.1.10 # porte specifiche
sudo nmap -p 1-1024 192.168.1.10 # un intervalloVa tenuto d’occhio anche l’UDP, spesso trascurato ma sede di servizi critici come DNS (53), SNMP (161) e NTP (123):

sudo nmap -sU -p 53,161,123 192.168.1.1Le scansioni UDP sono più lente perché una porta chiusa non sempre genera una risposta esplicita: conviene limitare l’intervallo di porte o armarsi di pazienza.

Version detection e OS fingerprintingSapere che la porta 22 è aperta è utile. Sapere che dietro c’è OpenSSH 8.9p1 lo è molto di più, soprattutto per intercettare versioni obsolete durante un audit di sicurezza:

sudo nmap -sV 192.168.1.10

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
80/tcp open http nginx 1.24.0
3306/tcp open mysql MySQL 8.0.35Con --version-intensity (da 0 a 9, default 7) si regola quanto nmap insiste nel probing: abbassarlo a 2-3 velocizza la scansione senza perdere molta precisione sui servizi comuni.

Per un’ipotesi sul sistema operativo, tramite fingerprinting dello stack TCP/IP, serve almeno una porta aperta e una chiusa:

sudo nmap -O 192.168.1.10Su macchine virtuali o stack TCP personalizzati la stima può essere imprecisa, ma resta un segnale utile per separare rapidamente server Linux, macchine Windows e dispositivi embedded su uno stesso segmento di rete.

Per un quadro completo in un colpo solo (OS detection, version detection, script scanning e traceroute) c’è la scansione aggressiva:

sudo nmap -A 192.168.1.10Genera molto traffico: da evitare su reti di produzione senza una finestra di manutenzione concordata.

Nmap Scripting Engine (NSE): oltre il semplice port scanLa vera potenza di nmap emerge con NSE, il motore di scripting che esegue controlli automatizzati sugli host scoperti: dalla ricerca di vulnerabilità note alla verifica di configurazioni deboli. Gli script risiedono in /usr/share/nmap/scripts/ e sono organizzati in categorie (default, auth, vuln, discovery, intrusive, safe).

Vulnerabilità note (categoria più invasiva, usarla con criterio)

sudo nmap --script=vuln 192.168.1.10

Accesso FTP anonimo

sudo nmap --script=ftp-anon -p 21 192.168.1.10

Header HTTP (spesso rivelano versioni software o debug info)

sudo nmap --script=http-headers -p 80,443 192.168.1.10

Open relay SMTP

sudo nmap --script=smtp-open-relay -p 25 192.168.1.20Un controllo rapido su porta 80/443 con http-headers capita spesso di far emergere header con versioni software esposte inutilmente: una correzione da cinque minuti che chiude una falla di information disclosure.

Output e automazionePer qualsiasi verifica che vada oltre il controllo estemporaneo, conviene salvare i risultati:

sudo nmap -sV 192.168.1.0/24 -oA scan_resultsIl flag -oA genera contemporaneamente output normale (.nmap), XML (.xml, utile per l’integrazione con altri strumenti e dashboard) e formato “grepable” (.gnmap), comodo per il parsing rapido da shell.

Combinazioni utili nel lavoro quotidiano# Solo porte effettivamente aperte, timing aggressivo su rete affidabile
sudo nmap -sS -T4 --open 192.168.1.10

Tutti i server SSH su una subnet

sudo nmap -p 22 --open -sV 192.168.1.0/24

Verifica che MySQL non sia esposto inutilmente

sudo nmap -p 3306 --open 192.168.1.0/24

Discovery + version scan solo sugli host realmente attivi

sudo nmap -sn 192.168.1.0/24 -oG - | grep "Up" | awk '{print $2}' | sudo nmap -sV -iL -MySQL esposto senza motivo è uno degli errori di configurazione più comuni e più pericolosi: una scansione mirata come quella sopra richiede due secondi e può intercettare il problema prima che lo trovi qualcun altro.

Nmap ha inoltre sei template di timing, da T0 (paranoico, lentissimo) a T5 (aggressivo): T3 è il default bilanciato, T4 va bene su reti locali affidabili, mentre su VPN o collegamenti lenti conviene scendere a T2 per evitare falsi negativi dovuti a pacchetti persi.

Porte filtrate: un segnale, non un fastidioNmap distingue tre stati: open, closed e filtered. Quest’ultimo indica che un firewall o un packet filter sta bloccando silenziosamente la sonda. Se compaiono molte porte filtrate su un server che non ti aspetti sia protetto da firewall, vale la pena indagare: potrebbe essere ufw, firewalld, un ruleset nftables o un security group del provider cloud. In ogni caso, è un’indicazione da non ignorare, e lo stesso principio vale per i probe di version detection e OS fingerprinting, che un firewall può alterare o azzerare.

ConclusioneNmap non si impara in un pomeriggio, ma i comandi visti coprono la maggior parte del lavoro quotidiano di un sistemista: discovery degli host, scansione delle porte, identificazione di servizi e versioni, script NSE per approfondire, e output strutturato per automazione o revisione successiva. La sequenza tipica è semplice: si parte con -sn per la discovery, si aggiunge -sV quando servono i dettagli sui servizi, e si porta NSE in campo quando serve scavare più a fondo. Timing prudente in produzione, aggressivo nel proprio lab: è una distinzione che vale la pena interiorizzare prima di lanciare la prima scansione su un ambiente che non si controlla del tutto.

Fonte originale: Hayden James, “nmap on Linux: Guide to Network Scanning and Discovery”, LinuxBlog.io.

#sicurezza #linux #guide #howto #tutorial #networking #nmap

0 0 0

Fail2ban su Linux: come configurarlo per bloccare davvero gli attacchi brute-force

Perché ogni server esposto a Internet ha bisogno di Fail2banBasta controllare i log di autenticazione di un qualunque server Linux raggiungibile da In

Altro...

Perché ogni server esposto a Internet ha bisogno di Fail2banBasta controllare i log di autenticazione di un qualunque server Linux raggiungibile da Internet per rendersi conto di un fatto scomodo: nel giro di poche ore compaiono centinaia di tentativi di accesso falliti su SSH, pannelli web o form di login. Non è un attacco mirato: sono scanner automatici che perlustrano di continuo intere sottoreti, alla ricerca di credenziali deboli o servizi mal configurati. Ignorare questo rumore di fondo non è un’opzione, ma bloccare manualmente ogni IP sospetto è impraticabile.

Fail2ban risolve il problema analizzando i log in tempo reale e bannando automaticamente, tramite il firewall, gli indirizzi IP che superano una soglia di tentativi falliti in una finestra temporale configurabile. È uno strumento maturo, leggero, presente nei repository di tutte le principali distribuzioni, ma la configurazione di default lascia molto sul tavolo: un bantime di 10 minuti, tanto per fare un esempio, è quasi inutile contro un attaccante automatizzato che può semplicemente aspettare e riprovare.

In questa guida vediamo come installare, configurare e soprattutto tunare Fail2ban per ottenere una protezione reale, con particolare attenzione agli scenari più comuni su un server di produzione: SSH, Nginx, firewall moderni basati su nftables e persistenza dei ban tra un reboot e l’altro.

I tre concetti chiave: filter, jail, actionPrima di mettere mano alla configurazione conviene avere chiaro il modello concettuale di Fail2ban, perché tutta la configurazione ruota attorno a tre elementi:

Filter: un insieme di espressioni regolari che individuano le righe di log corrispondenti a un tentativo di accesso fallito.

Jail: combina un filtro con il percorso del log da monitorare, le soglie di attivazione e l’azione da eseguire al superamento della soglia.

Action: cosa succede quando la soglia viene superata. Nella maggior parte dei casi è una regola firewall, ma può includere anche l’invio di una notifica via email.

Fail2ban include già filtri e jail pronti per decine di servizi (SSH, Apache, Nginx, Postfix, Dovecot…). Nella pratica quotidiana ci si limita ad abilitare le jail utili e a regolare qualche parametro.

InstallazioneFail2ban è disponibile nei repository ufficiali di tutte le distribuzioni principali.

Debian/Ubuntu:

sudo apt update
sudo apt install fail2banFedora / RHEL 9+ / Rocky / AlmaLinux:

sudo dnf install fail2banArch Linux:

sudo pacman -S fail2banAbilitiamo e avviamo il servizio, poi verifichiamo lo stato:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2banSe lo stato non riporta active (running), i log vanno controllati con sudo journalctl -u fail2ban -n 50.

Configurare Fail2ban nel modo correttoUn errore comune è modificare direttamente /etc/fail2ban/jail.conf: questo file viene sovrascritto a ogni aggiornamento del pacchetto, con conseguente perdita delle personalizzazioni. L’approccio corretto è creare un file dedicato dentro jail.d/:

sudo nano /etc/fail2ban/jail.d/custom.confIn alternativa si può copiare il file di default in jail.local, che ha priorità sui valori in jail.conf:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localLa sezione [DEFAULT]Nella sezione [DEFAULT] si impostano i valori applicati a tutte le jail, salvo override specifico:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1bantime: durata del ban. Il default (spesso 10 minuti) è troppo permissivo: 1 ora è un buon punto di partenza, e per attaccanti persistenti si può salire a 24h o 1w. Il valore -1 produce un ban permanente, da usare con cautela.

findtime: la finestra temporale in cui vengono contati i fallimenti.

maxretry: numero di tentativi falliti prima del ban. 5 è ragionevole per SSH, si può scendere a 3 per una postura più aggressiva.

ignoreip: gli IP che non verranno mai bannati. È fondamentale aggiungere qui il proprio IP prima di abilitare qualsiasi jail: restare fuori dal proprio server per un ban accidentale è un classico errore da evitare.

Se il server ha un indirizzo IPv6 pubblico, va incluso anche quello: alcuni filtri più datati intercettano solo IPv4, quindi conviene verificare che le jail catturino correttamente entrambi i protocolli.

La jail SSHÈ la jail più importante per la maggior parte dei server. In jail.local o in un nuovo file /etc/fail2ban/jail.d/sshd.conf:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 1hSe SSH è stato spostato su una porta non standard (buona pratica consigliata), va aggiornata la riga port. Sui sistemi basati su systemd, %(sshd_log)s punta automaticamente al journal; sui sistemi più datati che usano /var/log/auth.log o /var/log/secure, Fail2ban gestisce la differenza tramite il parametro backend. Dopo ogni modifica alla configurazione:

sudo fail2ban-client reloadJail per NginxI server web attirano un tipo diverso di abuso: scanner di URL 404, bruteforcer su form di login, bot che generano richieste inutili.

[nginx-http-auth]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 3

[nginx-limit-req]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 10La jail nginx-limit-req intercetta i client che superano i limit_req configurati in Nginx: è una combinazione efficace se il server web è già stato ottimizzato per gestire traffico elevato. Se Fail2ban segnala che un percorso di log non esiste, va impostato esplicitamente, ad esempio logpath = /var/log/nginx/error.log.

Verificare jail e ban attiviIl comando fail2ban-client è lo strumento principale per monitorare la situazione. Elenco delle jail attive:

sudo fail2ban-client statusDettaglio di una jail specifica, comprensivo di IP attualmente bannati:

sudo fail2ban-client status sshdPer bannare o sbannare manualmente un IP:

sudo fail2ban-client set sshd banip 203.0.113.99
sudo fail2ban-client set sshd unbanip 203.0.113.99Il comando unbanip è quello da tenere a portata di mano nel caso in cui ci si banni da soli per errore, prima di aver aggiunto il proprio IP a ignoreip.

Ban incrementali con la jail recidiveUna delle funzionalità meno conosciute ma più efficaci di Fail2ban è la jail recidive, che monitora il log interno di Fail2ban stesso e applica ban molto più lunghi agli IP che, dopo la scadenza di un primo ban, tornano a fare bruteforcing.

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
action = %(action_mwl)s
bantime = 1w
findtime = 1d
maxretry = 5Con questa configurazione, un IP bannato 5 volte in un giorno riceve un ban di una settimana: è l’equivalente più vicino a una blocklist persistente senza dover integrare feed di threat intelligence esterni. Su sistemi che scrivono solo sul journal, va impostato backend = systemd nella jail recidive, oppure va verificato che Fail2ban stia scrivendo un log tradizionale.

Testare i filtri prima di attivarliPrima di abilitare una jail, conviene verificare che il regex del filtro corrisponda davvero alle righe di log presenti sul sistema:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.confL’output riporta gli IP individuati e il numero di righe che hanno fatto match. Un filtro che non intercetta nulla non protegge nulla: questo comando è indispensabile soprattutto quando si scrive un filtro personalizzato per un’applicazione custom, dentro /etc/fail2ban/filter.d/:

/etc/fail2ban/filter.d/myapp-auth.conf

[Definition]
failregex = ^<HOST> .* "POST /login" 401
ignoreregex =Il tag <HOST> è obbligatorio: Fail2ban lo sostituisce con un’espressione regolare che cattura l’indirizzo IP da bannare. Un pattern troppo generico rischia di bannare traffico legittimo, quindi va sempre validato con fail2ban-regex prima di collegarlo a una jail attiva.

nftables, firewalld e persistenza dei banSu Debian 12+ e Ubuntu 22.04+, nftables è il backend firewall di default. L’azione di ban predefinita di Fail2ban usa ancora iptables, che nella maggior parte delle installazioni funziona tramite il layer di compatibilità iptables-nft. Se invece si usa nftables puro, l’azione va impostata esplicitamente:

banaction = nftables-multiport
banaction_allports = nftables-allportsSu RHEL, Fedora e Rocky, dove firewalld è lo standard, va usata l’azione corrispondente:

banaction = firewallcmd-rich-rules
banaction_allports = firewallcmd-allportsPer default, i ban sono mantenuti in memoria e vengono persi a ogni riavvio. Per farli sopravvivere ai reboot va abilitato il database SQLite (su molte distribuzioni recenti è già attivo di default):

dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 7dUna configurazione di partenza completaEcco un file /etc/fail2ban/jail.d/custom.conf che copre i casi d’uso più comuni su un server Linux tipico, da usare come punto di partenza:

[DEFAULT]
bantime = 2h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 7d

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 6h

[nginx-http-auth]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 4

[nginx-limit-req]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 10

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 5sudo fail2ban-client reload
sudo fail2ban-client statusCosa Fail2ban non risolveFail2ban è uno strumento reattivo, non preventivo: banna un IP solo dopo che ha già effettuato diversi tentativi. Non copre, da solo, alcuni scenari:

attacchi bruteforce distribuiti su migliaia di IP diversi, ciascuno con uno o due tentativi soltanto;

exploit zero-day che non generano righe di log riconoscibili;

attacchi a livello applicativo che non producono un fallimento di autenticazione tracciabile.

Per una protezione a più livelli, Fail2ban va affiancato all’autenticazione SSH tramite chiavi (disabilitando del tutto l’autenticazione via password), a un firewall configurato correttamente e a una revisione periodica dei log. Un’attenzione particolare va riservata ai server dietro Cloudflare o un altro reverse proxy: senza ripristinare l’IP originale del visitatore (tramite mod_remoteip su Apache o real_ip_module su Nginx), Fail2ban finirebbe per bannare gli IP del proxy stesso invece degli attaccanti reali.

Comandi da tenere sempre a portata di manosudo fail2ban-client status — elenco di tutte le jail attive

sudo fail2ban-client status sshd — stato dettagliato di una jail

sudo fail2ban-client set sshd banip 1.2.3.4 — ban manuale di un IP

sudo fail2ban-client set sshd unbanip 1.2.3.4 — rimozione manuale di un ban

sudo fail2ban-client reload — ricarica la configurazione dopo una modifica

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf — test di un filtro

sudo tail -f /var/log/fail2ban.log — monitoraggio dei ban in tempo reale

ConclusioneFail2ban resta uno degli strumenti che meritano un posto fisso su ogni server Linux esposto a Internet: l’installazione richiede pochi minuti e già con una configurazione minima riduce in modo drastico il rumore generato da scanner SSH e probe automatizzati sui servizi web. La differenza reale, però, la fanno tre accorgimenti spesso trascurati: impostare un bantime ragionevole (il default di 10 minuti è quasi inutile), aggiungere sempre il proprio IP a ignoreip prima di abilitare le jail, e attivare la jail recidive per penalizzare chi insiste. Da soli, questi tre passaggi fanno la differenza tra un’installazione di default e una protezione che funziona davvero.

Fonte: Fail2ban on Linux: Protect Your Server from Brute-Force Attacks, LinuxBlog.io

#sicurezza #linux #howto #tutorial

0 0 0

Nginx e TLS nel 2026: le tecniche aggiornate per ridurre TTFB e latenza HTTPS

Nel 2026 quasi tutto il traffico web viaggia in HTTPS, ma quanto di quella cifratura sta ancora costando millisecondi inutili al vostro Time To First

Altro...

Nel 2026 quasi tutto il traffico web viaggia in HTTPS, ma quanto di quella cifratura sta ancora costando millisecondi inutili al vostro Time To First Byte? Molte configurazioni Nginx che giravano perfettamente nel 2020 oggi trascinano direttive deprecate, parametri OCSP che non fanno più nulla e cipher suite che TLS 1.3 ignora comunque. Vale la pena rimettere mano al blocco ssl_* del vostro server, non per inseguire un punteggio più alto su SSL Labs, ma perché ogni handshake più corto si moltiplica per il numero di visitatori.

Va detto subito, con onestà: il tuning TLS non salva un backend lento. Se il TTFB del vostro sito è dominato da query al database, cache fredda o un’applicazione PHP/.NET che impiega 800ms a costruire la pagina, ottimizzare l’handshake sposta l’ago di qualche decina di millisecondi. Ma è ottimizzazione a costo quasi zero, che si somma a tutto il resto: cache, CDN, query tuning. Va fatta bene una volta e poi dimenticata.

HTTP/2 e HTTP/3: la sintassi è cambiataSe la vostra configurazione risale a qualche anno fa, probabilmente avete ancora questa riga:

listen 443 ssl http2;Funziona ancora, ma da Nginx 1.25.1 il parametro http2 sulla direttiva listen è deprecato: lanciando nginx -t su una build recente comparirà un warning esplicito. La forma corretta separa i due concetti:

listen 443 ssl;
http2 on;La direttiva http2 attiva il protocollo per l’intero server block, il che è più pulito che ripeterlo su ogni riga listen. Se gestite una flotta di server dietro un load balancer, verificate che tutte le istanze montino Nginx 1.25.1 o superiore prima di effettuare lo switch: una versione più vecchia non riconosce http2 on; e si rifiuta di avviarsi.

Attivare HTTP/3 con QUIC senza compilare nullaFino a poco tempo fa, abilitare HTTP/3 su Nginx significava patchare e ricompilare da sorgente contro una libreria TLS con supporto QUIC: un esercizio che pochi sistemisti volevano affrontare in produzione. Quell’epoca è finita. Il supporto nativo a QUIC e HTTP/3 è arrivato nel mainline Nginx a partire dalla 1.25.0 ed è ormai maturo nel branch stable, quindi sulle distribuzioni recenti o sul repository ufficiale Nginx non serve più compilare nulla a mano.

Va detto che, nonostante l’entusiasmo degli anni scorsi, l’adozione reale di HTTP/3 procede più lentamente del previsto: a metà 2026 HTTP/2 serve poco più della metà delle richieste globali mentre HTTP/3 si attesta intorno al 21%, con un plateau che dura da diversi mesi. Parte del motivo è strutturale: un browser passa a HTTP/3 solo dopo aver scoperto il supporto tramite un header Alt-Svc o un record DNS, quindi molte prime visite non negoziano mai QUIC. Vale comunque la pena abilitarlo: sposta il trasporto su UDP ed elimina l’head-of-line blocking di TCP, un vantaggio concreto su connessioni mobili lente o con perdita di pacchetti.

Su Nginx 1.25.0 o superiore con supporto QUIC integrato, un server block tipico è:

server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;

http2 on;

ssl_certificate     /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/key.pem;

# Annuncia HTTP/3 ai client che arrivano via HTTP/1.1 o HTTP/2
add_header Alt-Svc 'h3=":443"; ma=86400';

# ... resto della configurazione del server

}Attenzione a reuseport: va specificato una sola volta per combinazione IP/porta. Se gestite più server block sullo stesso indirizzo, mettete reuseport solo sul blocco predefinito e usate listen 443 quic; sugli altri, altrimenti Nginx si rifiuta di partire.

L’header Alt-Svc è il dettaglio che quasi tutti dimenticano: senza di esso i browser non hanno modo di sapere che il server parla HTTP/3 e restano su HTTP/2. Dopo la modifica, testate e ricaricate:

nginx -t
nginx -s reloadPer verificare rapidamente da riga di comando quale protocollo state effettivamente servendo:

curl --http2 -I https://vostrodominio.it/
curl --http3 -I https://vostrodominio.it/Session cache e session ticket: il vero risparmio sull’handshakeCon HTTPS, invece di una singola andata e ritorno, la connessione richiede un handshake aggiuntivo. Attivare la cache delle sessioni TLS riduce questo costo per le connessioni ripetute:

ssl_session_cache shared:SSL:10m; # circa 40.000 sessioni
ssl_session_timeout 1d; # tempo di riutilizzo della sessioneSui session ticket la raccomandazione è cambiata rispetto a qualche anno fa. Un tempo si consigliava di disabilitarli perché la rotazione della chiave di cifratura non era gestita correttamente da Nginx. Da Nginx 1.23.2 in poi la gestione delle chiavi per la ripresa stateless delle sessioni è molto migliorata, quindi salvo casi particolari conviene tenerli attivi:

ssl_session_tickets on;Unica eccezione: se gestite più server Nginx dietro un bilanciatore senza sincronizzare le chiavi dei ticket tra le istanze, la ripresa della sessione si rompe silenziosamente e perdete il beneficio. In quel caso, sincronizzate le chiavi o disabilitate i ticket su tutta la flotta in modo coerente.

Quali versioni TLS tenere attiveTLS 1.0 e 1.1 sono obsoleti, bloccati da ogni browser moderno e vietati dallo standard PCI DSS: vanno disattivati ovunque, senza eccezioni. La vera decisione riguarda invece TLS 1.2 e 1.3.

Per la maggior parte dei siti pubblici, la scelta corretta è tenere entrambi attivi:

ssl_protocols TLSv1.2 TLSv1.3;È TLS 1.3 a fare la differenza sul TTFB: riduce l’handshake a un singolo round trip e supporta la ripresa di sessione, quindi i visitatori che tornano si connettono più rapidamente. TLS 1.2 resta come fallback per client più datati e, su un sito pubblico normale, non costa nulla lasciarlo attivo.

Passate a TLS 1.3 soltanto se controllate i client che si connettono: un’API interna, un backend applicativo, un servizio dove sapete con certezza che nessun client datato deve collegarsi:

ssl_protocols TLSv1.3;Disabilitare TLS 1.2 su un sito pubblico è il tipo di modifica che sembra pulita in un file di configurazione e poi silenziosamente taglia fuori una fetta di traffico reale. Senza un motivo specifico, lasciatelo acceso.

OCSP stapling: cosa è cambiato con Let’s EncryptL’OCSP stapling permette a Nginx di allegare all’handshake una prova firmata dalla CA della validità del certificato, evitando che il client debba interrogare direttamente il servizio OCSP. La configurazione classica resta questa:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/full_chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;Ma qui c’è un cambiamento importante da conoscere se usate Let’s Encrypt: il 6 agosto 2025 Let’s Encrypt ha terminato il supporto OCSP e spento i propri responder. I certificati che emette oggi non hanno più un URL OCSP, ma un URL CRL al suo posto. Senza un responder da interrogare, ssl_stapling on; non fa più nulla sui certificati Let’s Encrypt e Nginx registra nei log un warning "ssl_stapling" ignored, no OCSP responder URL.

Il bilancio onesto nel 2026 è questo: se la vostra CA pubblica ancora un URL OCSP, lo stapling resta un piccolo vantaggio innocuo e potete tenerlo attivo. Se siete su Let’s Encrypt, le direttive sopra sono ormai inerti e potete rimuoverle per tenere puliti configurazione e log. È parte di uno spostamento più ampio del settore verso CRL e certificati a vita breve.

Buffer SSL più piccolo per ridurre il TTFBIl parametro ssl_buffer_size imposta la dimensione del buffer usato per inviare dati via HTTPS. Il valore predefinito è 16k, pensato per risposte di grandi dimensioni, ma per minimizzare il TTFB conviene spesso un valore più piccolo:

ssl_buffer_size 4k;Il risparmio tipico è di 30-50 millisecondi sul TTFB, variabile a seconda del carico e delle dimensioni medie delle risposte servite.

Configurazione completa consigliata per il 2026http2 on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_buffer_size 4k;

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options sameorigin;
add_header X-Content-Type-Options nosniff;Da notare: con TLS 1.3 le cipher suite sono fissate dal protocollo stesso, quindi una lunga stringa ssl_ciphers personalizzata e una direttiva ssl_ecdh_curve manuale non portano quasi nessun beneficio. I cipher elencati sopra si applicano soltanto alle connessioni TLS 1.2, e ssl_prefer_server_ciphers va disattivato perché i client moderni scelgono in modo sensato per conto proprio. Piuttosto che ottimizzare a mano all’infinito, generate una configurazione aggiornata con il Mozilla SSL Configuration Generator e incollate solo le parti che vi servono.

Se avete ancora in configurazione una riga X-Xss-Protection "1; mode=block", rimuovetela: l’XSS auditor del browser che controllava è stato eliminato da tutti i browser principali, e in alcuni casi quell’header può addirittura introdurre vulnerabilità invece di prevenirle. Una Content-Security-Policy è il sostituto moderno.

ConclusioneNessuna di queste modifiche, presa singolarmente, trasformerà le prestazioni del vostro sito. Ma insieme costituiscono un livello di ottimizzazione a costo pressoché nullo che qualsiasi sistemista dovrebbe verificare almeno una volta l’anno, specialmente dopo un major upgrade di Nginx o un rinnovo dell’infrastruttura dei certificati. Testate sempre con nginx -t prima di ricaricare, verificate il risultato con SSL Labs e con l’ispezione della colonna Protocol negli strumenti di sviluppo del browser, e ricordate che il vero collo di bottiglia, nella maggior parte dei casi, resta ciò che succede dopo l’handshake: cache, query e tempo di generazione della risposta.

Fonte: Nginx tuning tips: HTTPS/TLS – Turbocharge TTFB/Latency, LinuxBlog.io (Hayden James).

#sicurezza #linux #tutorial #performance #nginx #tlsssl

0 0 0

Swap attivo con RAM libera? Ecco come scoprire il processo colpevole con smem su Linux

Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)Capita spesso: un server ha 32 o 64 GB di RAM, il carico è t

Altro...

Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)Capita spesso: un server ha 32 o 64 GB di RAM, il carico è tutto sommato modesto, eppure free -h mostra qualche centinaio di MB o addirittura qualche GB in swap. Il riflesso istintivo di molti sistemisti è colpevolizzare la RAM insufficiente e chiedere un upgrade. Nella maggior parte dei casi, però, il problema non è la quantità di memoria disponibile, ma quali processi stanno finendo in swap e perché. Per rispondere serve uno strumento che guardi dentro ai singoli processi, non solo ai numeri aggregati: smem.

Perché Linux usa lo swap anche con RAM liberaIl kernel Linux non tratta la RAM come una risorsa da tenere il più vuota possibile: la usa aggressivamente per la page cache, per velocizzare I/O su file e librerie. Quando il kernel individua pagine di memoria che non vengono acquisite/toccate da tempo, può decidere di spostarle in swap per liberare RAM fisica da destinare alla cache, anche se tecnicamente c’è ancora memoria “libera” disponibile. Questo comportamento è regolato dal parametro vm.swappiness (0-100, con default storicamente a 60 su molte distribuzioni), che indica al kernel quanto è propenso a scambiare memoria anonima verso lo swap piuttosto che liberare pagine di cache.

Il punto chiave: prima di toccare vm.swappiness alla cieca, bisogna sapere chi sta effettivamente occupando swap. Un valore aggregato come quello di free non lo dice. Serve la vista per processo.

smem: memoria proporzionale, non solo RSSTool classici come top o ps mostrano RSS (Resident Set Size), che però ha un difetto noto: se due processi condividono le stesse pagine di memoria (librerie condivise, memoria mappata), quella memoria viene contata per intero in ognuno dei due, gonfiando artificialmente i numeri quando si sommano i processi.

smem risolve il problema calcolando anche:

USS (Unique Set Size): memoria usata esclusivamente da quel processo, non condivisa con nessun altro — utile per capire quanto libereresti davvero uccidendo il processo

PSS (Proportional Set Size): memoria condivisa divisa proporzionalmente tra i processi che la usano — la metrica più corretta per sommare l’uso reale di memoria di un sistema senza doppi conteggi

Swap: quanta memoria di quello specifico processo è stata spostata su disco

Installazionesmem non è quasi mai preinstallato, ma è nei repository di tutte le principali distribuzioni:

RHEL / CentOS / AlmaLinux / Fedora

dnf install smem

Debian / Ubuntu

apt install smemUso pratico: trovare chi consuma swapIl comando base per ordinare i processi per swap consumato:

smem -rs swapOutput tipico (troncato):

PID User Command Swap USS PSS RSS
28986 mysql /usr/sbin/mysqld --daemon 476372 10963864 10963932 10965112
29152 root /usr/sbin/rsyslogd -n 371424 3956 17475 43352
31423 root /opt/fluent-bit/bin/fluent 22508 26612 26739 29100Da un output così è immediato capire che mysqld e rsyslogd sono i principali responsabili dell’uso di swap su questo host, e non un generico “poca RAM”. Da qui l’indagine si sposta su quel servizio specifico: per MySQL, ad esempio, tipicamente significa rivedere innodb_buffer_pool_size rispetto alla RAM totale disponibile, o verificare connessioni/thread che allocano memoria inutilmente.

Alcune varianti utili del comando:

Ordina per USS (memoria realmente esclusiva del processo)

smem -rs uss

Filtra per utente

smem -u

Vista grafica a torta per RSS (richiede matplotlib)

smem --pie name -s rssDalla diagnosi al tuningUna volta identificati i servizi che finiscono in swap, ci sono due strade complementari:

Agire sul servizio: ridimensionare i buffer/pool applicativi (buffer pool di MySQL, heap JVM, cache applicative) in base alla RAM effettivamente disponibile, invece di lasciare valori di default pensati per macchine generiche.

Agire sul kernel, solo dopo aver capito il quadro reale: ridurre vm.swappiness per rendere il kernel meno aggressivo nello spostare memoria anonima in swap:

sysctl vm.swappiness=1
echo 'vm.swappiness=1' >> /etc/sysctl.confDa notare che vm.swappiness=0 non disabilita completamente lo swap su kernel recenti (dal 3.5 in poi il comportamento è cambiato rispetto alle versioni più vecchie), mentre valori molto bassi come 1 riducono drasticamente la propensione allo swap mantenendo comunque una valvola di sicurezza in caso di pressione di memoria reale. Su un database server dedicato, dove si preferisce quasi sempre tenere i dati “caldi” in RAM piuttosto che liberare cache, è una delle prime ottimizzazioni da considerare.

ConclusioneVedere swap attivo su un server con RAM apparentemente libera non è di per sé un allarme: è il comportamento normale di un kernel che ottimizza l’uso della cache. Il problema comincia quando lo swap coinvolge processi critici per la latenza, come un database o un servizio applicativo, degradando le performance in modo silenzioso. smem -rs swap è il primo comando da lanciare in questi casi: in pochi secondi isola il processo responsabile, distingue la memoria condivisa da quella esclusiva, e trasforma un sintomo generico (“il server è lento”) in un’azione concreta di tuning, sul servizio o sul kernel.

Fonte: LinuxBlog.io, “Diagnosing Swap Usage with smem on Linux”.

#linux #howto #tutorial #performance #swap

0 0 0