De lijst met open poorten is de lijst met wegen naar uw server. Al het overige — firewall, WAF, inbraakdetectie — wordt daarbovenop gebouwd. Daarom staat «wat luistert hier» voorop in elke doorlichting, en daarom is het ook de controle die het vaakst een onaangenaam resultaat geeft: de helft van wat opduikt is niet door u geopend maar door het installatieprogramma van een of ander pakket.
De uitvoer lezen
sudo ss -tulpn
De opties: t voor TCP, u voor UDP, l alleen wat luistert, p het proces, n zodat getallen getallen blijven. Zonder sudo blijft de proceskolom leeg en verliest de oefening haar zin.
Het gaat om de kolom Local Address:Port, en het verschil daar is wezenlijk:
127.0.0.1:3306— de dienst is alleen vanaf de machine zelf bereikbaar. Dat is goed;0.0.0.0:3306— vanaf elk IPv4-adres, dus vanaf internet. Dat is wat gecontroleerd moet worden;[::]:3306— hetzelfde voor IPv6. Een aparte regel, en die wordt regelmatig over het hoofd gezien;203.0.113.25:443— op een specifiek adres, doorgaans met opzet.
Stel daarna bij elke regel met 0.0.0.0 of [::] één vraag: hoort een buitenstaander hier bij te kunnen? Voor 80 en 443 is het antwoord ja. Voor vrijwel al het overige nee.
De gebruikelijke vondsten
Redis, poort 6379. De gevaarlijkste regel die er is. Standaard vraagt Redis geen wachtwoord, en met zijn commando's kan een bestand naar schijf worden geschreven — dus een vreemde sleutel in authorized_keys. Tussen het verschijnen van Redis op een openbaar adres en het misbruik ervan zitten uren, soms minder. Controleer bind 127.0.0.1 en protected-mode yes in de configuratie.
Memcached, 11211/UDP. Zelfs als er niets waardevols in zit, wordt uw server een versterker voor andermans aanvallen — en de klacht komt van de hoster.
MySQL en PostgreSQL, 3306 en 5432. Er is een wachtwoord, maar daarop wordt onafgebroken geraden, en databaseversies worden minder vaak bijgewerkt dan wenselijk. Naar buiten hoeven ze vrijwel nooit: de toepassing draait op dezelfde machine, en voor uw werk volstaat een SSH-tunnel.
Elasticsearch 9200, MongoDB 27017. Historisch zonder standaardauthenticatie. Openbare exemplaren daarvan zijn een vaste bron van nieuws over datalekken.
De Docker-API, 2375. Een open Docker-stuurpoort is root op de host zonder enig wachtwoord. Die verschijnt meestal na experimenten met externe toegang tot Docker.
Beheerpanelen en phpMyAdmin op hun poorten: 8080, 8083, 10000. Niet dat ze nooit opengezet mogen worden, maar juist zij vangen het gros van de pogingen op.
Bij de dienst verhelpen, niet bij de firewall
De neiging om elke vondst met een UFW-regel dicht te zetten is begrijpelijk, maar dat is de tweede lijn, niet de eerste. Een regel kan per ongeluk worden verwijderd, een firewall tijdens het foutzoeken even worden uitgezet, en Docker publiceert poorten volledig langs UFW heen. Een bindinstelling in de configuratie van de dienst overleeft dat alles:
- MySQL/MariaDB —
bind-address = 127.0.0.1; - PostgreSQL —
listen_addresses = 'localhost'; - Redis —
bind 127.0.0.1 ::1; - Docker Compose — publiceren als
"127.0.0.1:5432:5432".
De firewall komt daar als verzekering bovenop, niet in plaats daarvan.
Het proces vinden als het onduidelijk is
ss geeft de naam en de pid. Daarna:
sudo systemctl status <pid>
sudo lsof -i :8080
Het eerste commando noemt de systemd-unit waartoe het proces behoort, en dat volstaat meestal om te begrijpen wat het is en of het nodig is. Een onbekend proces dat op een hoge poort luistert en buiten de systeemmappen is gestart — vanuit /tmp of /dev/shm bijvoorbeeld — is geen configuratiekwestie meer maar aanleiding voor een apart onderzoek.
De controle van buitenaf is verplicht
ss beantwoordt «wat luistert», niet «waar valt bij te komen». Daartussen staan de firewall, NAT en de regels van de hoster. Het enige eerlijke antwoord komt van een scan vanaf een andere machine:
nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1
Sla het tweede commando niet over: vrijwel elke VPS heeft een IPv6-adres, de regels daarvoor worden apart geschreven, en de dienst luistert op beide protocolversies tegelijk.
Dit is geen eenmalige controle
De lijst met open poorten verandert vanzelf. U installeerde een pakket en dat bracht een dienst mee die een poort opende. U werkte een paneel bij en dat zette een standaardwaarde terug. U startte een container en die publiceerde een poort langs de firewall heen. Een eenmalige controle geldt voor vandaag en voor niets anders.
De waarde zit niet in de lijst zelf maar in de veranderingen ervan: een nieuwe poort die er gisteren niet was, is een kort en zeer sprekend signaal. Zo is het ook de moeite waard ernaar te kijken — als momentopname met historie, en niet als uit het geheugen gereconstrueerde ss-uitvoer. De demopagina hieronder laat precies dat zien.