EQVPS
DashboardKom i gang

Sådan tjekker du åbne porte på en VPS: hvad der lytter, hvad internettet ser og Docker-overraskelsen

Se hver port din server lytter på, find processen bag den, scan serveren udefra som en angriber ville og luk det, du ikke har brug for. Med Docker-porten, der forbliver åben, selv når firewallen er slået til. Hvert tal målt på en ny Ubuntu 24.04-server.

En åben og glemt port er den klassiske vej ind i en server: en database på en offentlig adresse, et debug-dashboard, en container, der udgav en port, som ingen ville udgive. Tjekket tager et minut, når du kender to kommandoer og én fælde. Vi kørte alt nedenfor på en ny Ubuntu 24.04-server fra vores image og scannede den fra en anden maskine, så outputtet er det, du vil se på din egen server.

1. Hvad der lytter

Kommandoen er ss. Bogstaverne står for TCP, UDP, lyttende sockets, numeriske porte og procesnavn:

sudo ss -tulpn

På en ny server udskriver den seks linjer:

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

Kolonnen, der betyder noget, er Local Address. Den fortæller, hvem der kan forbinde:

AdresseHvem der kan nå den
127.0.0.1:… eller 127.0.0.53Kun programmer på denne server
0.0.0.0:…Alle over IPv4, medmindre firewallen blokerer
[::]:…Alle over IPv6 (og som regel også IPv4)
10.0.0.5:… (en bestemt adresse)Alle, der kan nå den adresse

Den nye server eksponerer altså præcis én ting: SSH på port 22, over IPv4 og IPv6. DNS-resolveren på 127.0.0.53 er privat.

For kun at liste det, internettet kunne se, filtrerer du loopback-adresserne fra:

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

Kør det efter hver installation. Vi installerede nginx, Docker og en lille Python-app, og listen voksede fra 2 linjer til 10, blandt andet en docker-proxy på 0.0.0.0:8081 og en containerd-socket på en tilfældig localhost-port.

2. Hvilken proces der ejer en port

Når en port er optaget, og du vil vide af hvem:

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

lsof er nemmest at læse. For nginx viste den en masterproces som root og en worker som www-data, begge på *:80, for IPv4 og IPv6. fuser udskriver kun PID'er, praktisk i scripts. Skal du frigøre porten, så stop tjenesten i stedet for at dræbe PID'en, ellers genstarter systemd den: sudo systemctl stop nginx.

3. Hvad internettet ser

ss viser serverens perspektiv. Internettets kan være anderledes, fordi en firewall sidder imellem, eller fordi en tjeneste er bundet til 127.0.0.1. For at se det reelle billede skal du scanne serveren fra en anden maskine, din bærbare eller en anden server. Værktøjet er nmap (apt install nmap, eller installationsprogrammet fra nmap.org på Windows og macOS).

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

Den første form tjekker de 1.000 mest almindelige porte, den anden alle 65.535, den tredje en liste. På vores nye server, før nogen 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

Den fulde scanning af 65.535 porte tog 8,9 sekunder og fandt den samme ene port. Lukkede porte svarer straks med en reset, derfor er de hurtige at scanne.

Tre tilstande tæller:

  • open: et program accepterede forbindelsen. Det er din angrebsflade.
  • closed: serveren svarede, at intet lytter der. Sikkert, men det bekræfter, at serveren findes, og hvad den ikke kører.
  • filtered: intet svar. En firewall smed pakken væk. Scanneren kan ikke vide, om der er en tjeneste bagved.

For en enkelt port uden at installere noget svarer nc -zv server-ip 443 med succeeded eller refused, og den hænger til timeout på en filtreret port. For UDP tilføjer du -sU til nmap og må forvente at vente; på vores server var de tre almindelige UDP-porte, 53, 123 og 161, closed.

En bemærkning om NAT-planer: fra internettet kan kun den SSH-port, vi har videresendt til dig, nås. En scanning af den delte adresse viser vores kant, ikke din server, og de øvrige porte kan ikke nås, uanset hvad der lytter på dem. På en plan med egen IPv4-adresse styrer du selv hver åben port.

4. Luk det, du ikke har brug for

Tre måder, fra bedst til bredest.

Bind til localhost. Hvis kun programmer på serveren bruger en tjeneste, så lad den lytte på 127.0.0.1. Vi startede en lille webapp med --bind 127.0.0.1 8080: ss viste den på 127.0.0.1:8080, og nmap udefra meldte 8080/tcp closed. For databaser er det den rigtige standard: Redis, MySQL og PostgreSQL lytter på localhost fra start på Ubuntu, og vores guides til Redis og MySQL lader det være sådan.

Stop tjenesten. sudo systemctl disable --now navn fjerner lytteren for altid. Tjek med ss, at den er væk.

Slå firewallen til. Tillad først SSH, derefter det, du leverer, og aktivér så:

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

Scanningen udefra ændrede sig fuldstændigt:

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

Hver ikke-tilladt port gik fra closed til filtered, og den fulde scanning af 65.535 porte tog nu 110 sekunder i stedet for 8,9. Mere tid pr. port for scanneren, mindre information om din server. Vores UFW-guide dækker hastighedsbegrænsning, at tillade en enkelt IP og IPv6.

Men se på tredje linje.

5. Docker-overraskelsen

Port 8081 forblev åben med firewallen slået til og uden en regel, der tillod den. Porten tilhører en container, vi startede med docker run -p 8081:80 nginx:alpine. Docker tilføjer sine egne regler til kernens firewall, og de evalueres før ufw's. Reglen, den skrev på vores server:

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

Hver pakke til port 8081 sendes videre ind i containeren, før ufw får noget at skulle have sagt. Det gør hver container med -p eller en ports:-post, og ss viser det ærligt som docker-proxy på 0.0.0.0:8081.

Løsningen er kun at udgive på localhost:

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

I Compose skriver du "127.0.0.1:8081:80" under ports:. Efter ændringen viste ss 127.0.0.1:8081, Docker-reglen fik -d 127.0.0.1/32, og scanningen udefra meldte 8081/tcp filtered. Sæt nginx som reverse proxy foran til den offentlige side, med HTTPS, så de eneste åbne porte på serveren er 22, 80 og 443.

Tjekliste efter hver ændring

  1. sudo ss -tulpn: er hver linje med 0.0.0.0 eller [::] noget, du ville eksponere?
  2. nmap server-ip fra din bærbare: passer de åbne porte?
  3. En database, cache eller et adminpanel på en offentlig adresse: flyt det til 127.0.0.1 eller bag firewallen i dag.
  4. Hver Docker-ports:-post: starter den med 127.0.0.1:, hvis det ikke er den offentlige webport?
  5. SSH åben for alle: tilføj fail2ban eller login kun med nøgle.

På Windows Server er det samme tjek Get-NetTCPConnection -State Listen, og reglerne findes i Windows Firewall. Hver Linux-plan, fra Nano til $3 og op, findes i en version med egen IPv4-adresse, og der ser verden det, du ser i ss, minus din firewall.

FAQ

Hvilke porte er åbne på en ny VPS?

På vores Ubuntu 24.04-image én: SSH på port 22. Ud over den lytter kun den lokale DNS-resolver på 127.0.0.53 og 127.0.0.54, som internettet ikke kan nå. En scanning af alle 65.535 TCP-porte fra en anden maskine fandt præcis én åben port.

Hvad er forskellen på en closed og en filtered port?

Closed betyder, at serveren svarede, at intet lytter der, så scanneren ved det med det samme. Filtered betyder slet intet svar, hvilket er det, en firewall gør, når den smider pakker væk. Begge holder ubudne gæster ude, men filtered skjuler også, hvilke tjenester der findes, og gør en fuld scanning cirka tolv gange langsommere på vores server.

Hvorfor viser ss en port, som nmap siger er closed?

Tjenesten lytter kun på 127.0.0.1, loopback-adressen. Programmer på selve serveren kan forbinde, ingen udefra. Se i ss på kolonnen Local Address: 127.0.0.1:8080 er privat, 0.0.0.0:8080 eller [::]:8080 kan nås fra internettet, hvis firewallen tillader det.

Jeg har slået ufw til, hvorfor er min Docker-port stadig åben?

Docker skriver sine egne firewallregler, som evalueres før ufw's. En container startet med -p 8081:80 kunne nås udefra på vores server med ufw aktiv og uden regel for 8081. Udgiv på localhost i stedet, -p 127.0.0.1:8081:80, og sæt nginx eller Caddy foran til den offentlige side.

Hvordan tjekker jeg en port fra min egen computer?

Kør nc -zv server-ip 443 for én port, eller installer nmap og kør nmap server-ip for de tusind mest almindelige porte. På en NAT-plan svarer kun din videresendte SSH-port fra internettet; alt andet er med vilje utilgængeligt.

Kommentarer

Ingen kommentarer endnu. Vær den første.

Skriv en kommentar

Kommentarer modereres, før de vises.