EQVPS
DashboardInizia

Come controllare le porte aperte di un VPS: cosa è in ascolto, cosa vede Internet e la sorpresa di Docker

Guarda ogni porta su cui il server è in ascolto, trova il processo che c'è dietro, scansiona il server dall'esterno come farebbe un attaccante e chiudi ciò che non serve. Con la porta Docker che resta aperta anche con il firewall attivo. Ogni numero misurato su un server Ubuntu 24.04 appena creato.

Una porta aperta e dimenticata è il modo classico per entrare in un server: un database su un indirizzo pubblico, una dashboard di debug, un container che ha pubblicato una porta che nessuno voleva pubblicare. Il controllo richiede un minuto se conosci due comandi e una trappola. Abbiamo eseguito tutto quanto segue su un server Ubuntu 24.04 nuovo dalla nostra immagine e lo abbiamo scansionato da una seconda macchina, quindi gli output sono quelli che vedrai sul tuo server.

1. Cosa è in ascolto

Il comando è ss. Le lettere significano TCP, UDP, socket in ascolto, porte numeriche e nome del processo:

sudo ss -tulpn

Su un server nuovo stampa sei righe:

Netid State  Local Address:Port  Process
udp   UNCONN    127.0.0.54:53    systemd-resolve
udp   UNCONN 127.0.0.53%lo:53    systemd-resolve
tcp   LISTEN    127.0.0.54:53    systemd-resolve
tcp   LISTEN 127.0.0.53%lo:53    systemd-resolve
tcp   LISTEN       0.0.0.0:22    sshd
tcp   LISTEN          [::]:22    sshd

La colonna che conta è Local Address. Ti dice chi può connettersi:

IndirizzoChi lo raggiunge
127.0.0.1:… o 127.0.0.53Solo i programmi su questo server
0.0.0.0:…Chiunque via IPv4, salvo blocco del firewall
[::]:…Chiunque via IPv6 (di solito anche IPv4)
10.0.0.5:… (un indirizzo specifico)Chiunque raggiunga quell'indirizzo

Il server nuovo espone quindi esattamente una cosa: SSH sulla porta 22, in IPv4 e IPv6. Il resolver DNS su 127.0.0.53 è privato.

Per elencare solo ciò che Internet potrebbe vedere, filtra gli indirizzi di loopback:

sudo ss -tlnp | awk 'NR>1 && $4 !~ /^(127\.|\[::1\])/ {print $4, $6}'

Eseguilo dopo ogni installazione. Abbiamo installato nginx, Docker e una piccola app Python, e la lista è passata da 2 a 10 righe, tra cui un docker-proxy su 0.0.0.0:8081 e un socket di containerd su una porta localhost casuale.

2. Quale processo occupa una porta

Quando una porta è occupata e vuoi sapere da chi:

sudo lsof -i :80 -P -n
sudo fuser 80/tcp
sudo ss -tlnp 'sport = :80'

lsof è il più leggibile. Per nginx ha mostrato un processo master come root e un worker come www-data, entrambi su *:80, per IPv4 e IPv6. fuser stampa solo i PID, comodo negli script. Se devi liberare la porta, ferma il servizio invece di uccidere il PID, altrimenti systemd lo riavvia: sudo systemctl stop nginx.

3. Cosa vede Internet

ss mostra la prospettiva del server. Quella di Internet può essere diversa, perché in mezzo c'è un firewall o perché un servizio è legato a 127.0.0.1. Per vedere la situazione reale, scansiona il server da un'altra macchina, il tuo portatile o un secondo server. Lo strumento è nmap (apt install nmap, oppure l'installer di nmap.org su Windows e macOS).

nmap your-server-ip
nmap -p- your-server-ip
nmap -p 22,80,443,3306 your-server-ip

La prima forma controlla le 1.000 porte più comuni, la seconda tutte le 65.535, la terza un elenco. Sul nostro server nuovo, prima di qualsiasi firewall:

Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
Nmap done: 1 IP address (1 host up) scanned in 6.83 seconds

La scansione completa delle 65.535 porte ha richiesto 8,9 secondi e ha trovato la stessa unica porta. Le porte chiuse rispondono subito con un reset, per questo scansionarle è veloce.

Contano tre stati:

  • open: un programma ha accettato la connessione. È la tua superficie di attacco.
  • closed: il server ha risposto che lì non ascolta nulla. Sicuro, ma conferma che il server esiste e cosa non esegue.
  • filtered: nessuna risposta. Un firewall ha scartato il pacchetto. Lo scanner non può sapere se dietro c'è un servizio.

Per una singola porta senza installare nulla, nc -zv ip-del-server 443 risponde succeeded o refused, e su una porta filtrata resta in attesa fino al timeout. Per l'UDP aggiungi -sU a nmap e aspettati lentezza; sul nostro server le tre porte UDP comuni, 53, 123 e 161, erano closed.

Una nota per i piani NAT: da Internet arriva solo la porta SSH che ti abbiamo inoltrato. Una scansione dell'indirizzo condiviso mostra il nostro bordo, non il tuo server, e le altre porte sono irraggiungibili, qualunque cosa vi ascolti. Su un piano con indirizzo IPv4 proprio, ogni porta aperta la gestisci tu.

4. Chiudi ciò che non serve

Tre modi, dal migliore al più ampio.

Legare a localhost. Se un servizio è usato solo da programmi sul server, fallo ascoltare su 127.0.0.1. Abbiamo avviato una piccola app web con --bind 127.0.0.1 8080: ss la mostrava su 127.0.0.1:8080 e nmap dall'esterno riportava 8080/tcp closed. Per i database è l'impostazione predefinita giusta: Redis, MySQL e PostgreSQL ascoltano su localhost già di serie su Ubuntu, e le nostre guide a Redis e MySQL lo lasciano così.

Fermare il servizio. sudo systemctl disable --now nome elimina l'ascolto per sempre. Verifica con ss che sia sparito.

Attivare il firewall. Consenti prima SSH, poi ciò che servi, poi attiva:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status verbose

La scansione dall'esterno è cambiata del tutto:

Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8081/tcp open  blackice-icecap
Nmap done: 1 IP address (1 host up) scanned in 10.18 seconds

Ogni porta non consentita è passata da closed a filtered, e la scansione completa delle 65.535 porte ora richiedeva 110 secondi invece di 8,9. Più tempo per porta per lo scanner, meno informazioni sul tuo server. La nostra guida a UFW tratta i limiti di frequenza, l'accesso da un solo IP e l'IPv6.

Ma guarda la terza riga.

5. La sorpresa di Docker

La porta 8081 è rimasta aperta con il firewall attivo e senza una regola che la consentisse. Appartiene a un container avviato con docker run -p 8081:80 nginx:alpine. Docker aggiunge regole proprie al firewall del kernel, e vengono valutate prima di quelle di ufw. La regola che ha scritto sul nostro server:

-A DOCKER ! -i docker0 -p tcp --dport 8081 -j DNAT --to-destination 172.17.0.2:80

Qualsiasi pacchetto per la porta 8081 viene inoltrato nel container prima che ufw possa dire la sua. Lo fa ogni container con -p o una voce ports:, e ss lo mostra onestamente come docker-proxy su 0.0.0.0:8081.

La correzione è pubblicare solo su localhost:

docker rm -f web
docker run -d --name web -p 127.0.0.1:8081:80 nginx:alpine

In Compose scrivi "127.0.0.1:8081:80" sotto ports:. Dopo la modifica ss mostrava 127.0.0.1:8081, la regola di Docker ha guadagnato -d 127.0.0.1/32 e la scansione dall'esterno riportava 8081/tcp filtered. Metti nginx come reverse proxy davanti per la parte pubblica, con HTTPS, così le uniche porte aperte sul server sono 22, 80 e 443.

Checklist dopo ogni modifica

  1. sudo ss -tulpn: ogni riga con 0.0.0.0 o [::] è qualcosa che volevi esporre?
  2. nmap ip-del-server dal portatile: le porte aperte corrispondono?
  3. Un database, una cache o un pannello di amministrazione su un indirizzo pubblico: spostalo oggi su 127.0.0.1 o dietro il firewall.
  4. Ogni voce ports: di Docker: inizia con 127.0.0.1: se non è la porta web pubblica?
  5. SSH esposto a tutti: aggiungi fail2ban o l'accesso solo con chiave.

Su Windows Server lo stesso controllo è Get-NetTCPConnection -State Listen, e le regole stanno nel Windows Firewall. Ogni piano Linux, dal Nano a $3 in su, ha una versione con indirizzo IPv4 proprio, e lì ciò che vedi in ss è ciò che vede il mondo, meno il tuo firewall.

FAQ

Quali porte sono aperte su un VPS nuovo?

Sulla nostra immagine Ubuntu 24.04, una: SSH sulla porta 22. Oltre a quella ascolta solo il resolver DNS locale su 127.0.0.53 e 127.0.0.54, che da Internet non si raggiunge. Una scansione di tutte le 65.535 porte TCP da un'altra macchina ha trovato esattamente una porta aperta.

Che differenza c'è tra una porta closed e una filtered?

Closed significa che il server ha risposto che lì non ascolta nulla, quindi lo scanner lo sa subito. Filtered significa nessuna risposta, ed è ciò che fa un firewall quando scarta i pacchetti. Entrambi tengono fuori gli intrusi, ma filtered nasconde anche quali servizi esistono e rende una scansione completa circa dodici volte più lenta sul nostro server.

Perché ss mostra una porta che nmap dice closed?

Il servizio ascolta solo su 127.0.0.1, l'indirizzo di loopback. I programmi sul server stesso possono connettersi, dall'esterno nessuno. In ss guarda la colonna Local Address: 127.0.0.1:8080 è privato, 0.0.0.0:8080 o [::]:8080 è raggiungibile da Internet se il firewall lo consente.

Ho attivato ufw, perché la porta di Docker è ancora aperta?

Docker scrive regole firewall proprie, valutate prima di quelle di ufw. Un container avviato con -p 8081:80 era raggiungibile dall'esterno sul nostro server con ufw attivo e nessuna regola per la 8081. Pubblica invece su localhost, -p 127.0.0.1:8081:80, e metti nginx o Caddy davanti per la parte pubblica.

Come controllo una porta dal mio computer?

Esegui nc -zv ip-del-server 443 per una porta, oppure installa nmap ed esegui nmap ip-del-server per le mille porte più comuni. Su un piano NAT da Internet risponde solo la tua porta SSH inoltrata; tutto il resto è irraggiungibile per scelta.

Commenti

Ancora nessun commento. Sii il primo.

Lascia un commento

I commenti sono moderati prima di comparire.