EQVPS
PanouÎncepe

Cum verifici porturile deschise pe un VPS: ce ascultă, ce vede internetul și surpriza Docker

Vezi fiecare port pe care ascultă serverul, găsește procesul din spatele lui, scanează serverul din exterior cum ar face un atacator și închide ce nu-ți trebuie. Inclusiv portul Docker care rămâne deschis chiar cu firewall-ul pornit. Fiecare cifră măsurată pe un server Ubuntu 24.04 nou.

Un port deschis și uitat este calea clasică de intrare într-un server: o bază de date pe o adresă publică, un panou de depanare, un container care a publicat un port pe care nu-l voia nimeni publicat. Verificarea durează un minut dacă știi două comenzi și o capcană. Am făcut totul mai jos pe un server Ubuntu 24.04 nou din imaginea noastră și l-am scanat de pe o a doua mașină, așa că rezultatele sunt cele pe care le vei vedea pe propriul server.

1. Ce ascultă

Comanda este ss. Literele înseamnă TCP, UDP, socket-uri care ascultă, porturi numerice și numele procesului:

sudo ss -tulpn

Pe un server nou afișează șase rânduri:

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

Coloana care contează este Local Address. Îți spune cine se poate conecta:

AdresăCine ajunge la ea
127.0.0.1:… sau 127.0.0.53Doar programele de pe acest server
0.0.0.0:…Oricine prin IPv4, dacă firewall-ul nu blochează
[::]:…Oricine prin IPv6 (de obicei și IPv4)
10.0.0.5:… (o adresă anume)Oricine poate ajunge la acea adresă

Serverul nou expune deci un singur lucru: SSH pe portul 22, prin IPv4 și IPv6. Resolverul DNS de pe 127.0.0.53 este privat.

Ca să listezi doar ce ar putea vedea internetul, filtrează adresele de loopback:

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

Rulează asta după fiecare instalare. Am instalat nginx, Docker și o mică aplicație Python, iar lista a crescut de la 2 rânduri la 10, printre care un docker-proxy pe 0.0.0.0:8081 și un socket containerd pe un port localhost aleatoriu.

2. Ce proces ocupă un port

Când un port e ocupat și vrei să afli de cine:

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

lsof e cel mai ușor de citit. Pentru nginx a arătat un proces master ca root și un worker ca www-data, ambele pe *:80, pentru IPv4 și IPv6. fuser afișează doar PID-urile, util în scripturi. Dacă trebuie să eliberezi portul, oprește serviciul în loc să omori PID-ul, altfel systemd îl repornește: sudo systemctl stop nginx.

3. Ce vede internetul

ss arată perspectiva serverului. Perspectiva internetului poate fi alta, pentru că între ele stă un firewall sau un serviciu e legat de 127.0.0.1. Pentru imaginea reală, scanează serverul de pe altă mașină, laptopul tău sau un al doilea server. Unealta este nmap (apt install nmap, sau installerul de pe nmap.org pentru Windows și macOS).

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

Prima formă verifică cele mai comune 1.000 de porturi, a doua toate cele 65.535, a treia o listă. Pe serverul nostru nou, înainte de orice 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

Scanarea completă a celor 65.535 de porturi a durat 8,9 secunde și a găsit același port unic. Porturile închise răspund imediat cu un reset, de aceea scanarea lor e rapidă.

Contează trei stări:

  • open: un program a acceptat conexiunea. Asta e suprafața ta de atac.
  • closed: serverul a răspuns că acolo nu ascultă nimic. Sigur, dar confirmă că serverul există și ce nu rulează.
  • filtered: niciun răspuns. Un firewall a aruncat pachetul. Scannerul nu poate ști dacă în spate e un serviciu.

Pentru un singur port fără să instalezi nimic, nc -zv ip-server 443 răspunde succeeded sau refused, iar pe un port filtrat așteaptă până la expirare. Pentru UDP adaugă -sU la nmap și pregătește-te de așteptare; pe serverul nostru cele trei porturi UDP comune, 53, 123 și 161, erau closed.

O notă pentru planurile NAT: de pe internet ajunge doar portul SSH pe care ți l-am redirecționat. O scanare a adresei comune arată marginea rețelei noastre, nu serverul tău, iar celelalte porturi sunt inaccesibile indiferent ce ascultă pe ele. Pe un plan cu adresă IPv4 proprie, fiecare port deschis îl gestionezi tu.

4. Închide ce nu-ți trebuie

Trei metode, de la cea mai bună la cea mai largă.

Leagă de localhost. Dacă doar programele de pe server folosesc un serviciu, fă-l să asculte pe 127.0.0.1. Am pornit o mică aplicație web cu --bind 127.0.0.1 8080: ss a arătat-o pe 127.0.0.1:8080, iar nmap din exterior a raportat 8080/tcp closed. Pentru baze de date asta e setarea implicită corectă: Redis, MySQL și PostgreSQL ascultă pe localhost din start pe Ubuntu, iar ghidurile noastre pentru Redis și MySQL le lasă așa.

Oprește serviciul. sudo systemctl disable --now nume elimină definitiv ascultătorul. Verifică cu ss că a dispărut.

Pornește firewall-ul. Permite întâi SSH, apoi ce servești, apoi activează:

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

Scanarea din exterior s-a schimbat complet:

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

Fiecare port nepermis a trecut din closed în filtered, iar scanarea completă a celor 65.535 de porturi a durat acum 110 secunde în loc de 8,9. Mai mult timp pe port pentru scanner, mai puține informații despre serverul tău. Ghidul nostru UFW acoperă limitarea ratei, permiterea unui singur IP și IPv6.

Dar uită-te la al treilea rând.

5. Surpriza Docker

Portul 8081 a rămas deschis cu firewall-ul pornit și fără nicio regulă care să-l permită. Portul aparține unui container pornit cu docker run -p 8081:80 nginx:alpine. Docker adaugă propriile reguli în firewall-ul kernelului, iar acestea sunt evaluate înaintea celor ufw. Regula pe care a scris-o pe serverul nostru:

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

Orice pachet către portul 8081 este redirecționat în container înainte ca ufw să aibă un cuvânt de spus. Așa face orice container cu -p sau o intrare ports:, iar ss îl arată cinstit ca docker-proxy pe 0.0.0.0:8081.

Soluția e să publici doar pe localhost:

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

În Compose scrie "127.0.0.1:8081:80" sub ports:. După schimbare, ss a arătat 127.0.0.1:8081, regula Docker a primit -d 127.0.0.1/32, iar scanarea din exterior a raportat 8081/tcp filtered. Pune nginx ca reverse proxy în față pentru partea publică, cu HTTPS, ca singurele porturi deschise pe server să fie 22, 80 și 443.

Listă de verificare după fiecare schimbare

  1. sudo ss -tulpn: fiecare rând cu 0.0.0.0 sau [::] e ceva ce ai vrut să expui?
  2. nmap ip-server de pe laptop: porturile deschise se potrivesc?
  3. O bază de date, un cache sau un panou de administrare pe o adresă publică: mută-l azi pe 127.0.0.1 sau în spatele firewall-ului.
  4. Fiecare intrare ports: din Docker: începe cu 127.0.0.1: dacă nu e portul web public?
  5. SSH deschis tuturor: adaugă fail2ban sau autentificare doar cu cheie.

Pe Windows Server aceeași verificare este Get-NetTCPConnection -State Listen, iar regulile stau în Windows Firewall. Fiecare plan Linux, de la Nano la $3 în sus, are o variantă cu adresă IPv4 proprie, iar acolo ce vezi în ss vede și restul lumii, minus ce oprește firewall-ul tău.

Întrebări frecvente

Ce porturi sunt deschise pe un VPS nou?

Pe imaginea noastră Ubuntu 24.04, unul singur: SSH pe portul 22. În rest ascultă doar resolverul DNS local pe 127.0.0.53 și 127.0.0.54, la care internetul nu ajunge. O scanare a tuturor celor 65.535 de porturi TCP de pe altă mașină a găsit exact un port deschis.

Care e diferența dintre un port closed și unul filtered?

Closed înseamnă că serverul a răspuns că acolo nu ascultă nimic, deci scannerul află imediat. Filtered înseamnă niciun răspuns, adică ce face un firewall când aruncă pachetele. Ambele țin intrușii afară, dar filtered ascunde și ce servicii există și face o scanare completă de circa douăsprezece ori mai lentă pe serverul nostru.

De ce ss arată un port pe care nmap îl raportează closed?

Serviciul ascultă doar pe 127.0.0.1, adresa de loopback. Programele de pe server se pot conecta, din exterior nimeni. În ss uită-te la coloana Local Address: 127.0.0.1:8080 e privat, 0.0.0.0:8080 sau [::]:8080 e accesibil de pe internet dacă firewall-ul permite.

Am pornit ufw, de ce portul Docker e încă deschis?

Docker își scrie propriile reguli de firewall, evaluate înaintea celor ufw. Un container pornit cu -p 8081:80 era accesibil din exterior pe serverul nostru cu ufw activ și fără regulă pentru 8081. Publică pe localhost, -p 127.0.0.1:8081:80, și pune nginx sau Caddy în față pentru partea publică.

Cum verific un port de pe propriul calculator?

Rulează nc -zv ip-server 443 pentru un port, sau instalează nmap și rulează nmap ip-server pentru cele mai comune o mie de porturi. Pe un plan NAT de pe internet răspunde doar portul tău SSH redirecționat; restul este inaccesibil prin design.

Comentarii

Încă nu există comentarii. Fii primul.

Lasă un comentariu

Comentariile sunt moderate înainte să apară.