Otwarty i zapomniany port to klasyczna droga do wnętrza serwera: baza danych na publicznym adresie, panel debugowania, kontener, który opublikował port, choć nikt tego nie chciał. Sprawdzenie zajmuje minutę, jeśli znasz dwa polecenia i jedną pułapkę. Wszystko poniżej wykonaliśmy na świeżym serwerze Ubuntu 24.04 z naszego obrazu i przeskanowaliśmy go z drugiej maszyny, więc wyniki będą takie same jak na Twoim serwerze.
1. Co nasłuchuje
Polecenie to ss. Litery oznaczają TCP, UDP, nasłuchujące gniazda, numery portów i nazwę procesu:
sudo ss -tulpn
Na świeżym serwerze wypisuje sześć wierszy:
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
Najważniejsza jest kolumna Local Address. Mówi, kto może się połączyć:
| Adres | Kto ma dostęp |
|---|---|
127.0.0.1:… lub 127.0.0.53 | Tylko programy na tym serwerze |
0.0.0.0:… | Każdy przez IPv4, o ile firewall nie blokuje |
[::]:… | Każdy przez IPv6 (zwykle też IPv4) |
10.0.0.5:… (konkretny adres) | Każdy, kto dosięga tego adresu |
Świeży serwer wystawia więc na zewnątrz dokładnie jedną rzecz: SSH na porcie 22, przez IPv4 i IPv6. Resolver DNS na 127.0.0.53 jest prywatny.
Aby wypisać tylko to, co mógłby zobaczyć internet, odfiltruj adresy pętli zwrotnej:
sudo ss -tlnp | awk 'NR>1 && $4 !~ /^(127\.|\[::1\])/ {print $4, $6}'
Uruchamiaj to po każdej instalacji. Zainstalowaliśmy nginx, Dockera i jedną małą aplikację w Pythonie — lista urosła z 2 wierszy do 10, w tym docker-proxy na 0.0.0.0:8081 i gniazdo containerd na losowym porcie localhost.
2. Który proces zajmuje port
Gdy port jest zajęty i chcesz wiedzieć przez kogo:
sudo lsof -i :80 -P -n
sudo fuser 80/tcp
sudo ss -tlnp 'sport = :80'
lsof czyta się najłatwiej. Dla nginx pokazał jeden proces główny jako root i workera jako www-data, oba na *:80, dla IPv4 i IPv6. fuser wypisuje tylko PID-y, wygodne w skryptach. Jeśli musisz zwolnić port, zatrzymaj usługę, zamiast zabijać PID, bo inaczej systemd ją uruchomi ponownie: sudo systemctl stop nginx.
3. Co widzi internet
ss pokazuje punkt widzenia serwera. Punkt widzenia internetu może być inny, bo po drodze stoi firewall albo usługa jest powiązana z 127.0.0.1. Aby zobaczyć prawdziwy obraz, skanuj serwer z innej maszyny — z laptopa lub drugiego serwera. Narzędzie to nmap (apt install nmap, a dla Windows i macOS instalator z nmap.org).
nmap your-server-ip
nmap -p- your-server-ip
nmap -p 22,80,443,3306 your-server-ip
Pierwsza forma sprawdza 1000 najczęstszych portów, druga wszystkie 65 535, trzecia listę. Na naszym świeżym serwerze, przed włączeniem firewalla:
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
Pełny skan 65 535 portów trwał 8,9 sekundy i znalazł ten sam jedyny port. Zamknięte porty od razu odpowiadają resetem, dlatego skanuje się je szybko.
Liczą się trzy stany:
- open: program przyjął połączenie. To Twoja powierzchnia ataku.
- closed: serwer odpowiedział, że nic tu nie nasłuchuje. Bezpieczne, ale potwierdza, że serwer istnieje, i pokazuje, czego na nim nie ma.
- filtered: brak odpowiedzi. Firewall odrzucił pakiet. Skaner nie wie, czy stoi za nim usługa.
Dla jednego portu bez instalowania czegokolwiek: nc -zv ip-serwera 443 zwraca succeeded lub refused, a na porcie filtered wisi aż do limitu czasu. Dla UDP dodaj do nmap -sU i przygotuj się na czekanie; na naszym serwerze trzy popularne porty UDP — 53, 123 i 161 — były closed.
Uwaga dla planów NAT: z internetu dostępny jest tylko port SSH, który Ci przekierowaliśmy. Skan wspólnego adresu pokaże naszą granicę, a nie Twój serwer, a pozostałe porty są niedostępne bez względu na to, co na nich nasłuchuje. Na planie z własnym IPv4 każdym otwartym portem zarządzasz Ty.
4. Zamknij to, czego nie potrzebujesz
Trzy sposoby — od najlepszego do najszerszego.
Powiąż z localhost. Jeśli z usługi korzystają tylko programy na serwerze, niech nasłuchuje na 127.0.0.1. Uruchomiliśmy małą aplikację webową z --bind 127.0.0.1 8080: ss pokazał ją na 127.0.0.1:8080, a nmap z zewnątrz zgłosił 8080/tcp closed. Dla baz danych to właściwe ustawienie domyślne: Redis, MySQL i PostgreSQL na Ubuntu od razu nasłuchują na localhost, a nasze poradniki do Redis i MySQL tak to zostawiają.
Zatrzymaj usługę. sudo systemctl disable --now nazwa usuwa nasłuchiwanie na stałe. Sprawdź w ss, że zniknęło.
Włącz firewall. Najpierw zezwól na SSH, potem na to, co udostępniasz, potem włącz:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status verbose
Skan z zewnątrz zmienił się całkowicie:
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
Każdy niedozwolony port zmienił stan z closed na filtered, a pełny skan 65 535 portów trwał teraz 110 sekund zamiast 8,9. Więcej czasu na każdy port dla skanera, mniej informacji o Twoim serwerze. Nasz poradnik UFW omawia limity, dostęp z jednego IP i IPv6.
Ale spójrz na trzeci wiersz.
5. Niespodzianka od Dockera
Port 8081 pozostał otwarty przy włączonym firewallu i bez reguły, która by na niego pozwalała. Ten port należy do kontenera uruchomionego poleceniem docker run -p 8081:80 nginx:alpine. Docker dodaje do firewalla jądra własne reguły, a te są sprawdzane przed regułami ufw. Reguła, którą zapisał na naszym serwerze:
-A DOCKER ! -i docker0 -p tcp --dport 8081 -j DNAT --to-destination 172.17.0.2:80
Każdy pakiet na port 8081 jest przekierowywany do kontenera, zanim ufw zdąży zabrać głos. Tak robi każdy kontener z -p lub wpisem w ports:, a ss uczciwie pokazuje to jako docker-proxy na 0.0.0.0:8081.
Poprawka to publikowanie portu tylko na localhost:
docker rm -f web
docker run -d --name web -p 127.0.0.1:8081:80 nginx:alpine
W Compose wpisz "127.0.0.1:8081:80" w ports:. Po zmianie ss pokazał 127.0.0.1:8081, w regule Dockera pojawiło się -d 127.0.0.1/32, a skan z zewnątrz zgłosił 8081/tcp filtered. Postaw z przodu nginx jako reverse proxy z HTTPS, aby na serwerze otwarte były tylko porty 22, 80 i 443.
Lista kontrolna po każdej zmianie
sudo ss -tulpn: czy każdy wiersz z0.0.0.0lub[::]to coś, co naprawdę chciałeś udostępnić?nmap ip-serweraz laptopa: czy otwarte porty się zgadzają?- Baza danych, cache lub panel administracyjny na publicznym adresie: jeszcze dziś przenieś na
127.0.0.1lub za firewall. - Każdy wpis
ports:w Dockerze: czy zaczyna się od127.0.0.1:, jeśli to nie jest publiczny port webowy? - SSH otwarty dla wszystkich: dodaj fail2ban lub logowanie tylko kluczem.
Na Windows Server ta sama kontrola to Get-NetTCPConnection -State Listen, a reguły mieszkają w Zaporze Windows. Każdy plan Linux, od Nano za $3, ma wersję z własnym adresem IPv4, i tam to, co widzisz w ss, widzi cały świat — z wyjątkiem tego, co zatrzyma Twój firewall.
Komentarze
Brak komentarzy. Bądź pierwszy.