EQVPS
KontrollpanelKom igång

Så kontrollerar du öppna portar på en VPS: vad som lyssnar, vad internet ser och Docker-överraskningen

Se varje port din server lyssnar på, hitta processen bakom den, skanna servern utifrån som en angripare skulle göra och stäng det du inte behöver. Med Docker-porten som förblir öppen även när brandväggen är på. Varje siffra uppmätt på en ny Ubuntu 24.04-server.

En öppen och bortglömd port är den klassiska vägen in i en server: en databas på en publik adress, en felsökningspanel, en container som publicerade en port som ingen ville publicera. Kontrollen tar en minut om du kan två kommandon och en fälla. Vi körde allt nedan på en ny Ubuntu 24.04-server från vår avbild och skannade den från en andra maskin, så utskrifterna är det du kommer att se på din egen server.

1. Vad som lyssnar

Kommandot är ss. Bokstäverna står för TCP, UDP, lyssnande socketar, numeriska portar och processnamn:

sudo ss -tulpn

På en ny server skriver det ut sex rader:

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

Kolumnen som spelar roll är Local Address. Den säger vem som kan ansluta:

AdressVem som når den
127.0.0.1:… eller 127.0.0.53Bara program på den här servern
0.0.0.0:…Vem som helst över IPv4, om inte brandväggen blockerar
[::]:…Vem som helst över IPv6 (och oftast IPv4 också)
10.0.0.5:… (en specifik adress)Vem som helst som når den adressen

Den nya servern exponerar alltså exakt en sak: SSH på port 22, över IPv4 och IPv6. DNS-resolvern på 127.0.0.53 är privat.

För att bara lista det internet skulle kunna se, filtrera bort loopback-adresserna:

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

Kör det efter varje installation. Vi installerade nginx, Docker och en liten Python-app, och listan växte från 2 rader till 10, bland annat en docker-proxy på 0.0.0.0:8081 och en containerd-socket på en slumpmässig localhost-port.

2. Vilken process som äger en port

När en port är upptagen och du vill veta av vem:

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

lsof är lättast att läsa. För nginx visade det en masterprocess som root och en worker som www-data, båda på *:80, för IPv4 och IPv6. fuser skriver bara ut PID:er, praktiskt i skript. Behöver du frigöra porten, stoppa tjänsten i stället för att döda PID:en, annars startar systemd om den: sudo systemctl stop nginx.

3. Vad internet ser

ss visar serverns perspektiv. Internets perspektiv kan skilja sig, eftersom en brandvägg sitter emellan eller en tjänst är bunden till 127.0.0.1. För den verkliga bilden, skanna servern från en annan maskin, din laptop eller en andra server. Verktyget är nmap (apt install nmap, eller installationsprogrammet från nmap.org på Windows och macOS).

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

Den första formen kontrollerar de 1 000 vanligaste portarna, den andra alla 65 535, den tredje en lista. På vår nya server, före någon brandvägg:

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 fullständiga skanningen av 65 535 portar tog 8,9 sekunder och hittade samma enda port. Stängda portar svarar direkt med en reset, därför går det snabbt att skanna dem.

Tre tillstånd spelar roll:

  • open: ett program accepterade anslutningen. Det här är din attackyta.
  • closed: servern svarade att inget lyssnar där. Säkert, men det bekräftar att servern finns och vad den inte kör.
  • filtered: inget svar. En brandvägg kastade paketet. Skannern kan inte veta om en tjänst finns bakom.

För en enda port utan att installera något svarar nc -zv server-ip 443 med succeeded eller refused, och hänger kvar till timeouten på en filtrerad port. För UDP lägger du till -sU i nmap och räknar med väntan; på vår server var de tre vanliga UDP-portarna, 53, 123 och 161, closed.

En anmärkning om NAT-abonnemang: från internet nås bara den SSH-port vi vidarebefordrat till dig. En skanning av den delade adressen visar vår kant, inte din server, och övriga portar är onåbara oavsett vad som lyssnar på dem. På ett abonnemang med egen IPv4-adress hanterar du varje öppen port själv.

4. Stäng det du inte behöver

Tre sätt, från bäst till bredast.

Bind till localhost. Om bara program på servern använder en tjänst, låt den lyssna på 127.0.0.1. Vi startade en liten webbapp med --bind 127.0.0.1 8080: ss visade den på 127.0.0.1:8080, och nmap utifrån rapporterade 8080/tcp closed. För databaser är det rätt standard: Redis, MySQL och PostgreSQL lyssnar på localhost direkt efter installation på Ubuntu, och våra guider för Redis och MySQL låter det vara så.

Stoppa tjänsten. sudo systemctl disable --now namn tar bort lyssnaren för gott. Kontrollera med ss att den är borta.

Slå på brandväggen. Tillåt SSH först, sedan det du tillhandahåller, och aktivera sedan:

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

Skanningen utifrån förändrades helt:

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

Varje icke tillåten port gick från closed till filtered, och den fullständiga skanningen av 65 535 portar tog nu 110 sekunder i stället för 8,9. Mer tid per port för skannern, mindre information om din server. Vår UFW-guide tar upp hastighetsbegränsning, att tillåta en enda IP och IPv6.

Men titta på tredje raden.

5. Docker-överraskningen

Port 8081 förblev öppen med brandväggen på och utan någon regel som tillät den. Porten tillhör en container som vi startade med docker run -p 8081:80 nginx:alpine. Docker lägger till egna regler i kärnans brandvägg, och de utvärderas före ufw:s. Regeln den skrev på vår server:

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

Varje paket till port 8081 vidarebefordras in i containern innan ufw får säga sitt. Det gör varje container med -p eller en ports:-post, och ss visar det ärligt som docker-proxy på 0.0.0.0:8081.

Lösningen är att bara publicera 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 visade ss 127.0.0.1:8081, Docker-regeln fick -d 127.0.0.1/32, och skanningen utifrån rapporterade 8081/tcp filtered. Sätt nginx som omvänd proxy framför för den publika sidan, med HTTPS, så att de enda öppna portarna på servern är 22, 80 och 443.

Checklista efter varje ändring

  1. sudo ss -tulpn: är varje rad med 0.0.0.0 eller [::] något du ville exponera?
  2. nmap server-ip från din laptop: stämmer de öppna portarna?
  3. En databas, cache eller adminpanel på en publik adress: flytta den till 127.0.0.1 eller bakom brandväggen i dag.
  4. Varje Docker-ports:-post: börjar den med 127.0.0.1: om det inte är den publika webbporten?
  5. SSH öppen för alla: lägg till fail2ban eller inloggning endast med nyckel.

På Windows Server är samma kontroll Get-NetTCPConnection -State Listen, och reglerna finns i Windows-brandväggen. Varje Linux-abonnemang, från Nano för $3 och uppåt, finns i en version med egen IPv4-adress, och där ser världen det du ser i ss, minus din brandvägg.

FAQ

Vilka portar är öppna på en ny VPS?

På vår Ubuntu 24.04-avbild en: SSH på port 22. Utöver den lyssnar bara den lokala DNS-resolvern på 127.0.0.53 och 127.0.0.54, som internet inte når. En skanning av alla 65 535 TCP-portar från en annan maskin hittade exakt en öppen port.

Vad är skillnaden mellan en closed och en filtered port?

Closed betyder att servern svarade att inget lyssnar där, så skannern vet direkt. Filtered betyder inget svar alls, vilket är vad en brandvägg gör när den kastar paket. Båda håller inkräktare ute, men filtered döljer också vilka tjänster som finns och gör en fullständig skanning ungefär tolv gånger långsammare på vår server.

Varför visar ss en port som nmap säger är closed?

Tjänsten lyssnar bara på 127.0.0.1, loopback-adressen. Program på själva servern kan ansluta, ingen utifrån. Titta i ss på kolumnen Local Address: 127.0.0.1:8080 är privat, 0.0.0.0:8080 eller [::]:8080 nås från internet om brandväggen tillåter det.

Jag slog på ufw, varför är min Docker-port fortfarande öppen?

Docker skriver egna brandväggsregler som utvärderas före ufw:s. En container startad med -p 8081:80 nåddes utifrån på vår server med ufw aktivt och utan regel för 8081. Publicera på localhost i stället, -p 127.0.0.1:8081:80, och sätt nginx eller Caddy framför för den publika sidan.

Hur kontrollerar jag en port från min egen dator?

Kör nc -zv server-ip 443 för en port, eller installera nmap och kör nmap server-ip för de tusen vanligaste portarna. På ett NAT-abonnemang svarar bara din vidarebefordrade SSH-port från internet; allt annat är avsiktligt onåbart.

Kommentarer

Inga kommentarer än. Bli först.

Lämna en kommentar

Kommentarer modereras innan de visas.