Porte Linux: cosa sono e come vedere i servizi in ascolto
Scopri come funzionano le porte Linux, perché 443 e 22 identificano servizi diversi e come usare ss per distinguere porte locali e pubbliche.
Che cos'è realmente una porta
Una porta è un numero che consente a un server di eseguire più servizi contemporaneamente senza confondere il relativo traffico. Il tuo VPS ha un solo indirizzo IP, ma può eseguire nello stesso momento un server web, un server SSH e un database. Quando arriva un pacchetto, il sistema operativo deve sapere a quale di questi servizi è destinato. Il numero di porta fornisce questa informazione. Il traffico HTTPS arriva normalmente alla porta 443, mentre SSH usa la porta 22. L'indirizzo IP porta il pacchetto al server; la porta lo consegna al programma corretto su quel server.
Una porta è un numero a 16 bit: 16 bit consentono valori da 0 a 65535 e 0 è riservato, quindi nella pratica le porte vanno da 1 a 65535. Le porte inferiori a 1024 sono le porte "well-known" e, per impostazione predefinita, Linux consente di aprirle solo a root o a un programma a cui è stata assegnata la capability CAP_NET_BIND_SERVICE. Per questo i servizi standard usano queste porte: 22 per SSH, 80 per HTTP, 443 per HTTPS e 53 per DNS. Il parametro sysctl net.ipv4.ip_unprivileged_port_start può modificare questa soglia, ma il valore predefinito è 1024. Le porte da 1024 in poi sono disponibili per i normali programmi.
Esistono due tipi di porte, TCP e UDP, e il numero di porta in uno dei due protocolli è distinto dallo stesso numero nell'altro. TCP è il protocollo basato sulla connessione usato dalla maggior parte dei servizi, tra cui SSH, HTTP e i database. UDP non usa connessioni ed è impiegato, ad esempio, da DNS e da alcune VPN. Quando apri una porta nel firewall, di solito devi specificare il protocollo, ad esempio 22/tcp.
L’ascolto indica che un programma attende connessioni su una porta
Un programma che deve ricevere connessioni chiede al kernel di mettersi in «ascolto» su una porta. Da quel momento la porta è aperta sulla macchina e il programma risponde alle connessioni in arrivo, secondo le regole del firewall. Una porta su cui non è in ascolto alcun programma rifiuta semplicemente le connessioni. Per questo, il primo controllo di qualsiasi verifica di sicurezza consiste nel chiedersi: che cosa è in ascolto e su quale indirizzo.
Il comando per verificarlo è ss:
sudo ss -tlnpI flag indicano TCP (t), solo i socket in ascolto (l), le porte in formato numerico (n, quindi viene visualizzato 22 invece di ssh) e il processo proprietario (p). Un risultato tipico è:
State Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:80 nginxLa colonna Process indica quale programma possiede ogni porta. Questo consente di individuare un processo che non si intendeva lasciare in esecuzione.
La colonna Local Address è quella importante
Leggi con attenzione l'indirizzo riportato davanti a ogni porta, perché determina chi può raggiungere il servizio. Esistono tre casi che incontrerai continuamente.
0.0.0.0:22 significa "ascolta su ogni indirizzo IPv4 disponibile su questa macchina", compreso quello pubblico. Il servizio è raggiungibile da Internet tramite IPv4, se il firewall lo consente.
[::]:80 ha lo stesso significato per IPv6: ascolta su ogni indirizzo IPv6, compreso quello pubblico. Molti programmi si associano qui per impostazione predefinita e, su Linux, un socket :: spesso accetta anche connessioni IPv4.
127.0.0.1:5432 significa "ascolta solo sul loopback". 127.0.0.1 è l'indirizzo che una macchina usa per comunicare con se stessa e, con le impostazioni predefinite del kernel, non è instradabile da altri sistemi. Un servizio associato a questo indirizzo è raggiungibile solo dallo stesso server, non da Internet, anche se il firewall consentisse la porta. La riga relativa a Postgres riportata sopra è quindi sicura per impostazione predefinita. Esiste un'eccezione: l'impostazione del kernel route_localnet. È disattivata per impostazione predefinita, ma alcuni strumenti la attivano, tra cui kube-proxy di Kubernetes. Se è attiva e sono presenti regole di routing o NAT appropriate, il traffico destinato al loopback può arrivare dall'esterno. sysctl -a | grep route_localnet dovrebbe mostrare = 0 su ogni riga.
La regola pratica deriva direttamente da questo comportamento: un database, una cache o un pannello di amministrazione usato solo dalle tue applicazioni dovrebbe associarsi a 127.0.0.1, non a 0.0.0.0. Se il servizio non ascolta mai su un indirizzo pubblico, un attaccante non ha alcuna porta da raggiungere.
Ascoltare non significa essere raggiungibili
Un'ulteriore distinzione evita molta confusione. Che una porta sia aperta sulla macchina, cioè che un programma sia in ascolto, è diverso dal fatto che la porta sia raggiungibile dall'esterno, cioè che il firewall ne consenta il traffico. Entrambe le condizioni devono essere vere perché un client remoto possa connettersi. I due problemi producono anche effetti diversi sul client: una connessione rifiutata indica generalmente che nessun programma era in ascolto, mentre una connessione che resta in attesa e poi va in timeout indica di solito che il firewall ha scartato il pacchetto. È esattamente ciò che indicano i due errori SSH.
Esistono quindi due livelli di controllo. Decidi quali servizi devono essere in ascolto impostando l'indirizzo di bind di ciascun servizio. Decidi invece quali servizi possono essere raggiunti dall'esterno tramite un firewall. Un server gestito correttamente usa entrambi i livelli: i servizi si associano solo agli indirizzi necessari e il firewall nega tutto ciò che non hai consentito esplicitamente. Leggere i servizi in ascolto con ss è il primo passaggio; verificare ciò che il firewall consente è il secondo, come descritto in guida introduttiva ai firewall con UFW.
Qui esiste una particolarità importante. IPv4 e IPv6 sono separati e un firewall che protegge solo IPv4 lascia esposti su IPv6 i servizi [::]. Questo problema specifico è trattato in un articolo dedicato: il problema del firewall IPv6.
FAQ
Come posso vedere quali porte sono aperte sul mio server Linux?
Esegui sudo ss -tlnp per TCP oppure sudo ss -ulnp per UDP. Il comando elenca ogni socket in ascolto, la porta, l'indirizzo locale a cui è associato e il processo che lo possiede. Leggi la colonna Local Address: 0.0.0.0 o [::] significa che il servizio è esposto alla rete, mentre 127.0.0.1 significa che ascolta solo sulla macchina stessa.
Qual è la differenza tra 0.0.0.0 e 127.0.0.1?
0.0.0.0 significa "ascolta su tutti gli indirizzi IPv4", compreso quello pubblico, quindi il servizio può essere raggiunto dalla rete. 127.0.0.1 è il loopback, cioè l'indirizzo che la macchina usa per comunicare con se stessa. Con le impostazioni predefinite del kernel, questo indirizzo non è instradabile da altri sistemi e un servizio associato a esso è quindi raggiungibile solo localmente. Associa i servizi interni a 127.0.0.1 per mantenerli fuori dalla rete.
Devo aprire una porta nel firewall perché un servizio funzioni?
Solo per i servizi che devono essere raggiunti da altre macchine. Un servizio associato a 127.0.0.1 non richiede una regola di autorizzazione, perché con le impostazioni predefinite del kernel nulla dall'esterno può raggiungerlo. Un servizio su 0.0.0.0 o [::] richiede una regola di autorizzazione quando il firewall nega per impostazione predefinita il traffico in ingresso, come dovrebbe. Se non è attivo alcun firewall o la relativa policy accetta tutto, il servizio è già raggiungibile senza alcuna regola.
Qual è la differenza tra una porta TCP e una porta UDP?
TCP è basato sulla connessione ed è usato dalla maggior parte dei servizi, tra cui SSH, i server web e i database. UDP non usa connessioni ed è impiegato da DNS e da alcune VPN. Lo stesso numero in TCP e UDP identifica porte distinte, quindi 53/tcp e 53/udp sono diverse. Quando scrivi le regole del firewall devi specificare il protocollo, ad esempio 22/tcp.