Porte e servizi in ascolto
Modulo 5: Proteggere la rete · Tempo di lettura: 10 minuti
Obiettivo della lezione: dopo questa lezione Lei saprà vedere quali servizi sono in ascolto sul Suo server e su quale indirizzo, spiegare la differenza tra 0.0.0.0 e 127.0.0.1 e verificare dall'esterno che cosa chiunque su internet vede del Suo server.
Concetti chiave: porta, TCP e UDP, essere in ascolto, ss -tulpn, 0.0.0.0 e [::], 127.0.0.1 e [::1], bind-address, aperta, chiusa e filtrata, superficie di attacco, scanner
Un indirizzo IP con 65.535 porte
Il Suo server ha un indirizzo IP, per esempio 192.0.2.10 e 2001:db8::10. Su quell'indirizzo possono essere raggiungibili contemporaneamente diversi programmi, ciascuno su una propria porta: un numero da 1 a 65.535. Un programma che accetta connessioni è in ascolto su una porta. Alcune porte note:
| Porta | Protocollo | Servizio |
|---|---|---|
| 22 | TCP | SSH |
| 80 | TCP | http (server web) |
| 443 | TCP e UDP | https (UDP per HTTP/3) |
| 25 | TCP | posta tra server di posta (SMTP) |
| 3306 | TCP | MySQL e MariaDB |
| 5432 | TCP | PostgreSQL |
| 6379 | TCP | Redis |
TCP è il protocollo per le connessioni che devono arrivare in modo affidabile (web, SSH, database). UDP serve per pacchetti singoli e veloci (DNS, VPN come WireGuard, HTTP/3). Un servizio è in ascolto su TCP, su UDP o su entrambi.
Ogni porta in ascolto è una porta d'ingresso al Suo server. Dietro ogni porta c'è un software che può contenere errori. L'insieme delle porte raggiungibili dall'esterno si chiama superficie di attacco. Più è piccola, meglio è: un server con un sito web ha bisogno dall'esterno soltanto delle porte 22, 80 e 443.
Vedere che cosa è in ascolto: ss
Il comando ss (socket statistics) mostra che cosa è in ascolto sul Suo server. Con le opzioni -t (TCP), -u (UDP), -l (solo in ascolto), -p (quale programma) e -n (numeri, non nomi):
anna@web1:~$ sudo ss -tulpn
Netid State Local Address:Port Peer Address:Port Process
udp UNCONN 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=402,fd=16))
tcp LISTEN 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=611,fd=3))
tcp LISTEN 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=902,fd=6))
tcp LISTEN 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=902,fd=7))
tcp LISTEN 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=755,fd=21))
tcp LISTEN 0.0.0.0:6379 0.0.0.0:* users:(("redis-server",pid=780,fd=6))
tcp LISTEN [::]:22 [::]:* users:(("sshd",pid=611,fd=4))
tcp LISTEN [::]:80 [::]:* users:(("nginx",pid=902,fd=8))
tcp LISTEN [::]:443 [::]:* users:(("nginx",pid=902,fd=9))La colonna più importante è Local Address: l'indirizzo su cui il programma è in ascolto.
| Indirizzo | Significato |
|---|---|
0.0.0.0 | Tutti gli indirizzi IPv4 del server, quindi anche quello pubblico: raggiungibile dall'esterno (a meno che un firewall non lo blocchi) |
[::] | Tutti gli indirizzi IPv6: lo stesso, per IPv6 |
127.0.0.1 o [::1] | Solo il server stesso (loopback): mai raggiungibile dall'esterno |
127.0.0.53, 127.0.0.54 | Anche questo è loopback; qui è in ascolto il resolver DNS locale di systemd-resolved |
192.0.2.10 | Solo quell'unico indirizzo |
Nell'esempio qui sopra MariaDB è a posto: è in ascolto su 127.0.0.1, quindi solo i programmi sul server stesso (il Suo sito web) possono accedervi. Redis invece è in ascolto su 0.0.0.0:6379. Se il firewall non è configurato correttamente, l'intera internet può accedervi. È proprio il tipo di errore di cui tratta questa lezione.
Ascoltare sull'indirizzo giusto
Un database, una cache o un pannello di amministrazione non dovrebbero quasi mai essere raggiungibili dall'esterno. La prima e migliore difesa è che il servizio sia in ascolto solo su loopback. Un firewall (lezione 5.2) è il secondo livello; può essere disattivato per errore o non essere applicato (per esempio con Docker, lezione 9.3).
Il punto in cui si configura cambia da programma a programma:
| Programma | Impostazione | File (Debian/Ubuntu) |
|---|---|---|
| MariaDB/MySQL | bind-address = 127.0.0.1 | /etc/mysql/mariadb.conf.d/50-server.cnf |
| PostgreSQL | listen_addresses = 'localhost' | /etc/postgresql/<versie>/main/postgresql.conf |
| Redis | bind 127.0.0.1 -::1 e protected-mode yes | /etc/redis/redis.conf |
I pacchetti di Debian e Ubuntu impostano già questi servizi su localhost per impostazione predefinita. Di solito le cose vanno storte quando qualcuno segue una guida che dice "imposti bind-address su 0.0.0.0 per connettersi dall'esterno". Se vuole accedere al database dal Suo portatile, usi un tunnel SSH (lezione 2.3): la porta resta chiusa e solo chi entra tramite SSH può accedervi.
Dopo una modifica, riavvii il servizio e controlli di nuovo con ss -tulpn.
Aperta, chiusa e filtrata
Vista dall'esterno, una porta può trovarsi in tre stati:
- Aperta (open): qualcosa è in ascolto e la connessione riesce.
- Chiusa (closed): non c'è nulla in ascolto, oppure un firewall rifiuta attivamente. Il server risponde subito con un "no" (con TCP un pacchetto RST). La connessione fallisce immediatamente con "Connection refused".
- Filtrata (filtered): un firewall scarta il pacchetto in silenzio. La connessione resta in sospeso fino a un timeout.
Per il Suo database chiusa e filtrata vanno entrambe bene: nessuno può accedervi. La differenza Le dice solo perché: filtrata significa quasi sempre che è il Suo firewall a bloccare.
Guardare dall'esterno
ss mostra che cosa è in ascolto sul server, ma non che cosa è raggiungibile dall'esterno. In mezzo c'è ancora un firewall e, a volte, presso il Suo fornitore anche un firewall di rete. L'unico controllo vero è quindi: guardare dall'esterno, da un altro computer.
Dal Suo computer (non dal server stesso, perché in quel caso passerebbe per il loopback) può farlo con nc (netcat) per una singola porta:
anna@laptop:~$ nc -vz -w 3 192.0.2.10 6379
nc: connect to 192.0.2.10 port 6379 (tcp) failed: Connection refused
anna@laptop:~$ nc -vz -w 3 192.0.2.10 22
Connection to 192.0.2.10 22 port [tcp/ssh] succeeded!Su Windows PowerShell fa la stessa cosa con Test-NetConnection 192.0.2.10 -Port 6379. Uno scanner di porte come nmap può esaminare più porte contemporaneamente; usi uno scanner del genere solo sul Suo server.
Non dimentichi IPv6. Un errore frequente è un firewall con regole solo per IPv4, mentre il servizio è in ascolto anche su [::]. Verifichi quindi anche l'indirizzo IPv6: nc -6 -vz -w 3 2001:db8::10 6379.
Perché è così importante
Il Suo server viene scansionato fin dal primo minuto. Motori di ricerca per dispositivi e servizi su internet, e bot di criminali, provano di continuo tutti gli indirizzi IPv4 sulle porte note. Un Redis aperto senza password, un cluster Elasticsearch o un MongoDB senza controllo degli accessi vengono trovati in breve tempo. Le fughe di dati dovute a database aperti e cluster di ricerca aperti finiscono regolarmente nelle notizie, e si tratta quasi sempre proprio di questo errore: un servizio pensato per l'uso interno era in ascolto su tutti gli indirizzi.
Anche alla porta di SSH si bussa tutto il giorno. È normale e, con le chiavi (lezione 2.2) e fail2ban (lezione 5.3), non è un problema.
Il controllo del corso
Nell'esercizio di questa lezione il programma del corso controlla dall'esterno cinque porte fisse di database del Suo server: 3306 (MySQL/MariaDB), 5432 (PostgreSQL), 6379 (Redis), 9200 (Elasticsearch/OpenSearch) e 27017 (MongoDB). Il programma verifica soltanto se si stabilisce una connessione, non invia dati e non effettua alcun accesso. Non scansiona altre porte. I controlli provengono dall'indirizzo IP indicato nell'esercizio, così può riconoscerli nei Suoi log. Un indirizzo può essere controllato solo poche volte all'ora.
Su AlmaLinux e Rocky Linux
ss funziona allo stesso modo. I file dei servizi si trovano in altre posizioni (per esempio /etc/my.cnf.d/ per MariaDB, /var/lib/pgsql/data/postgresql.conf per PostgreSQL). Inoltre SELinux può bloccare un servizio che vuole mettersi in ascolto su una porta insolita; in quel caso lo vede in journalctl (lezione 6.2) e non in ss.
Riepilogo
- Ogni porta in ascolto è una porta d'ingresso; dall'esterno tenga aperto solo ciò che è davvero necessario (di solito 22, 80 e 443).
sudo ss -tulpnmostra quale programma è in ascolto su quale indirizzo e su quale porta.0.0.0.0e[::]significano "tutti gli indirizzi",127.0.0.1e[::1]significano "solo il server stesso". Database, cache e cluster di ricerca vanno su loopback.- Chiusa e filtrata vanno entrambe bene per un database; aperta è sbagliato.
- Verifichi sempre dall'esterno, sia per IPv4 sia per IPv6, perché
ssnon vede il firewall.
Quiz
Esercizio
Esercizio Z5.1: Porte dei database chiuse dall'esterno. Esegua sudo ss -tulpn sul Suo server e scopra su quali indirizzi sono in ascolto i Suoi servizi. Poi lasci che il programma del corso verifichi dall'esterno che le porte 3306, 5432, 6379, 9200 e 27017 del Suo server non siano raggiungibili, per IPv4 e (se il Suo server ha un record AAAA) per IPv6. Indichi anche quali servizi sono in ascolto, nel Suo caso, su 0.0.0.0 o [::]. Il programma si limita a stabilire una connessione verso quelle cinque porte e non invia nulla.
