Izpis odprtih vrat v Linuxu: ss, lsof, netstat

Linux Branje: 8 min

Na strežniku vsaka omrežna storitev sprejema povezave na svojih vratih: SSH na 22, spletni strežnik na 80 in 443, MariaDB na 3306. Katera vrata so trenutno odprta in kateri program jih zaseda, izveš z ukazom ss. Ta članek pokaže tudi, zakaj ni dovolj, da vrata na strežniku poslušajo: od zunaj so dosegljiva le, če jih prepusti tudi požarni zid.

Ukaze smo novembra 2026 preizkusili v sistemu AlmaLinux 10.2, na katerem so tekli nginx, MariaDB, Valkey, aplikacija Node.js in Docker 29.9, ter v sistemu Ubuntu 26.04 z nginx. Na lastnem KVM VPS je seznam dobro občasno pregledati: vsaka po nepotrebnem odprta vrata so še ena površina za napad.

Vrata, ki poslušajo: ss -tulpn

ss je del paketa iproute (v Ubuntuju in Debianu iproute2), nameščen je v vseh današnjih distribucijah.

sudo ss -tulpn

Stikala:

  • -t: TCP;
  • -u: UDP;
  • -l: le vtičnice, ki poslušajo (listening), brez vzpostavljenih povezav;
  • -p: ime in PID programa, ki zaseda vrata (process);
  • -n: izpiše številke, ne imen storitev (:22, ne :ssh).

-p programe drugih uporabnikov (na primer root ali mysql) pokaže le s sudo; brez njega stolpec Process ostane prazen. Če te zanimajo le vrata, zadošča ss -tuln tudi brez sudo in se prilega tudi ozkemu oknu:

ss -tuln pokaže vrata TCP in UDP, ki poslušajo, sudo lsof -nP -i :3306 pa proces MariaDB, ki zaseda vrata 3306 v AlmaLinux

V preizkusu je bil izpis sudo ss -tulpn (skrajšano):

Netid State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp   UNCONN 0      0          127.0.0.1:323       0.0.0.0:*    users:(("chronyd",pid=642,fd=4))
tcp   LISTEN 0      80           0.0.0.0:3306      0.0.0.0:*    users:(("mariadbd",pid=839,fd=20))
tcp   LISTEN 0      511          0.0.0.0:80        0.0.0.0:*    users:(("nginx",pid=1217,fd=6),...)
tcp   LISTEN 0      128          0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=1188,fd=7))
tcp   LISTEN 0      511        127.0.0.1:6379      0.0.0.0:*    users:(("valkey-server",pid=1190,fd=8))
tcp   LISTEN 0      511             [::]:80           [::]:*    users:(("nginx",pid=1217,fd=7),...)

Stolpci izpisa

Stolpec Pomen
Netid protokol: tcp ali udp
State pri TCP LISTEN (posluša); UDP nima povezave, zato je tam UNCONN
Recv-Q, Send-Q pri vtičnici, ki posluša, število čakajočih povezav oziroma velikost čakalne vrste; pri vsakdanji uporabi ni pomembno
Local Address:Port naslov in vrata, na katerih program posluša
Peer Address:Port pri vtičnici, ki posluša, * (povezavo lahko pričakuje od kjer koli)
Process ime programa, PID in datotečni deskriptor vtičnice (fd); le s stikalom -p

Kaj pomeni naslov pred vrati?

Local Address pokaže, od kod je storitev dosegljiva:

Naslov Pomen
0.0.0.0:80 posluša na vseh naslovih IPv4, dosegljivo tudi od zunaj (če požarni zid dovoli)
[::]:80 posluša na vseh naslovih IPv6
*:3000 na vseh naslovih IPv4 in IPv6, z eno vtičnico (v preizkusu se je tako prikazala aplikacija Node.js)
127.0.0.1:6379, [::1]:6379 dosegljivo le znotraj strežnika (localhost)
127.0.0.53%lo:53 le na vmesniku loopback; v Ubuntuju tako posluša lokalni razreševalnik DNS systemd-resolved
10.0.2.15:68 le na tem enem naslovu IP

V preizkusu je Valkey privzeto poslušal le na naslovu 127.0.0.1, zato od zunaj ni dosegljiv, tudi če je požarni zid odprt. MariaDB pa je s paketom AlmaLinux 10 privzeto poslušal na naslovu 0.0.0.0:3306: če podatkovno bazo uporablja le spletna stran na strežniku, jo lahko z vrstico bind-address=127.0.0.1 v razdelku [mysqld] datoteke /etc/my.cnf.d/mariadb-server.cnf in ponovnim zagonom storitve omejiš na lokalni dostop (v preizkusu je ss nato kazal le še naslov 127.0.0.1:3306). Namestitev MariaDB opisuje ločen članek.

Filtriranje po vratih

sudo ss -tlnp 'sport = :80'
sudo ss -tlnp | grep ':3306 '

sport (source port) pomeni lokalna vrata. Pri grep se zaradi presledka za vrati :3306 ne ujema na primer z vrati :33060.

Vzpostavljene povezave

Brez -l, s filtrom po stanju, vidiš trenutno žive povezave, na primer kdo je povezan prek SSH:

sudo ss -tnp state established

ss -s da povzetek števila vtičnic po protokolih; veliko povezav timewait ali estab je na obremenjenem spletnem strežniku normalno, na mirnem strežniku pa je lahko sumljivo.

Kateri program zaseda vrata? lsof in fuser

lsof izpiše odprte datoteke, v Linuxu pa tudi omrežna vtičnica šteje za datoteko:

sudo lsof -nP -i :80
sudo lsof -nP -i -sTCP:LISTEN
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mariadbd  839  mysql  20u  IPv4   9075      0t0  TCP *:3306 (LISTEN)
mariadbd  839  mysql  21u  IPv6   9076      0t0  TCP *:3306 (LISTEN)

-n pusti naslove, -P pa vrata kot številke (brez njega se prikaže *:http). Na cloud image AlmaLinux 10 lsof ni bil nameščen (sudo dnf install lsof), na Ubuntu 26.04 pa je bil.

fuser (iz paketa psmisc, nameščen je bil v obeh sistemih) da le PID-e:

sudo fuser -v 80/tcp

fuser -k 80/tcp programe, ki zasedajo vrata, tudi ubije. Pri storitvi namesto tega ustavi storitev (glej spodaj), ker lahko systemd ubito storitev glede na nastavitev znova zažene.

netstat: stari ukaz

netstat je del paketa net-tools, ki ni bil nameščen niti na cloud image AlmaLinux 10 niti na Ubuntu 26.04. Če si ga navajen, ga lahko namestiš (sudo dnf install net-tools ali sudo apt install net-tools) in uporabljaš z istimi stikali:

sudo netstat -tulpn

Izpis je podoben, naslove IPv6 piše v obliki :::80. Brez sudo je v stolpcu PID/Program name le -. V novih skriptih je priporočen ss, ker je nameščen povsod.

Ustavitev storitve, ki zaseda vrata

ss -tulpn pokaže ime in PID programa. Katera storitev systemd ga je zagnala, povesta ps ali systemctl status:

ps -p 1217 -o pid,comm,unit
systemctl status 1217

Nato jo lahko ustaviš in izklopiš njen samodejni zagon:

sudo systemctl disable --now nginx

Upravljanje storitev podrobno opisuje članek o ukazu systemctl.

V Ubuntu 26.04 se pri vratih 22 poleg sshd pojavi tudi systemd (PID 1): tam SSH zažene aktivacija prek vtičnice (ssh.socket), vrata pa drži odprta tudi systemd. O nastavitvah SSH, med njimi o premiku na druga vrata, govori članek o varni nastavitvi strežnika SSH.

Address already in use: zasedena vrata

Če program poskuša odpreti vrata, ki jih že zaseda drug, se ne zažene. V preizkusu se nginx tako ni zagnal, ker je na vratih 80 poslušal drug program:

$ sudo journalctl -u nginx | grep bind
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

Drugi programi to sporočijo s svojimi besedami (v Pythonu na primer OSError: [Errno 98] Address already in use). Kaj narediti:

  1. Poglej, kdo zaseda vrata: sudo ss -tlnp 'sport = :80' ali sudo lsof -nP -i :80.
  2. Če gre za staro ali nepotrebno storitev, jo ustavi (sudo systemctl disable --now apache2). Pogost primer je, da se Apache in nginx hkrati poskušata zagnati na vratih 80 ali da vrata zaseda vsebnik Docker.
  3. Če potrebuješ oba, enega preusmeri na druga vrata.

Posluša, a ni dosegljivo? Požarni zid

ss pokaže le, da bi program sprejel povezavo. Ali je od zunaj res dosegljiv, odloči požarni zid. V preizkusu je nginx poslušal na naslovu 0.0.0.0:80, od zunaj pa ni odgovarjal, dokler firewalld ni dovolil storitve http; nato je bil takoj dosegljiv.

Preverjanje pravil požarnega zidu:

# AlmaLinux, Rocky Linux (firewalld)
sudo firewall-cmd --list-all

# Ubuntu, Debian (ufw)
sudo ufw status verbose

Na cloud image AlmaLinux 10 firewalld ni bil nameščen, na Ubuntu 26.04 je bil ufw nameščen, a izklopljen (Status: inactive). Kakšna je osnovna nastavitev na tvojem strežniku, vedno preveri. Nastavitev požarnega zidu prikazuje članek Kako nastavim požarni zid na svojem VPS?

Docker obide požarni zid

Docker objavljena vrata vsebnikov (-p 8081:80) odpre z lastnimi pravili. V preizkusu je bil vsebnik nginx, zagnan s stikalom -p 8081:80, dosegljiv od zunaj, čeprav je cona public v firewalld dovoljevala le SSH; hkrati nginx, ki je tekel neposredno na računalniku, na vratih 80 ni bil dosegljiv. V izpisu ss taka vrata zaseda program docker-proxy.

Če želiš vsebnik doseči le lokalno (na primer za obratnim proxyjem), ga veži na lokalni naslov:

docker run -d -p 127.0.0.1:8082:80 nginx:alpine

Takrat ss pokaže naslov 127.0.0.1:8082. Namestitev in osnove Dockerja opisuje članek o namestitvi Dockerja.

Preverjanje od zunaj: nc in nmap

Ali so vrata res dosegljiva, preveri z drugega računalnika (na primer s svojega). Preizkus znotraj strežnika požarnega zidu ne preizkusi.

nc -zv 203.0.113.10 80
nc -zv -w 3 203.0.113.10 3306

Ukaz nc v Ubuntuju (netcat-openbsd) ob uspešni povezavi izpiše Connection to ... 443 port [tcp/https] succeeded!, pri zaprtih vratih Connection refused, pri paketih, ki jih zavrže požarni zid, pa po -w 3 sekundah napako timed out. V AlmaLinux je nc v paketu nmap-ncat in da sporočilo Ncat: Connected to ... ali Ncat: Connection refused..

Več vrat hkrati preveri nmap:

nmap -Pn -p 22,80,443,3306 203.0.113.10
PORT     STATE    SERVICE
443/tcp  open     https
3306/tcp filtered mysql
  • open: vrata so dosegljiva, program sprejme povezavo;
  • closed: računalnik odgovori, a na vratih nič ne posluša;
  • filtered: odgovora ni bilo, pakete verjetno zavrže požarni zid.

Tako preverjaj le svoj strežnik: skeniranje vrat tujih računalnikov brez dovoljenja lahko velja za zlorabo. Druga orodja za iskanje omrežnih napak (ping, traceroute, curl) predstavlja članek o iskanju omrežnih napak.

Povzetek

Naloga Ukaz
Vrata, ki poslušajo, s programi sudo ss -tulpn
Vrata, ki poslušajo, brez sudo ss -tuln
Preverjanje enih vrat sudo ss -tlnp 'sport = :80'
Kdo zaseda vrata? sudo lsof -nP -i :80
Žive povezave sudo ss -tnp state established
Stara oblika sudo netstat -tulpn (net-tools)
Katera storitev? systemctl status PID
Pravila požarnega zidu sudo firewall-cmd --list-all ali sudo ufw status verbose
Je dosegljivo od zunaj? nc -zv IP PORT ali nmap -Pn -p PORT IP (z drugega računalnika)
Nazaj: Linux – članki (76)