UFW en IPv6 beveiliging op uw VPS
Uw firewall blokkeert mogelijk alleen IPv4, waardoor IPv6-poorten openstaan. Ontdek hoe u dit gat op uw VPS dicht en voorkom onbedoelde toegang via IPv6.
De IPv6-firewallval in één zin
Uw firewall beschermt IPv4. Uw VPS heeft vrijwel zeker ook een publiek IPv6-adres, en veel services luisteren hier standaard naar. Als uw firewall alleen IPv4 dekt, of als u vertrouwt op een cloud-firewall die alleen IPv4 filtert, is elke service via IPv6 bereikbaar vanaf het hele internet, terwijl uw IPv4-zijde beveiligd lijkt. U test een poort met curl, ziet een geweigerde verbinding en voelt zich veilig. Een aanvaller verbindt via IPv6 met dezelfde poort en krijgt toegang.
Deze gids laat zien waar dit gat ontstaat op een standaard Ubuntu 24.04 VPS, hoe u precies ziet wat u blootstelt en hoe u dit sluit. UFW is hier niet de boosdoener. Op een moderne Ubuntu-installatie regelt UFW IPv6 al. De blootstelling komt door de lagen eromheen en door services waarvan u niet wist dat ze luisterden.
Waarom uw VPS standaard IPv6 gebruikt
Bijna elke huidige VPS wordt geleverd met een publiek IPv6-adres, vaak een volledig /64, naast het IPv4-adres. Controleer uw eigen adres:
ip -6 addr show scope global2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
inet6 2001:db8:2a::1/64 scope globalDat 2001:db8:2a::1 is routeerbaar vanaf elke locatie op het internet, precies zoals uw IPv4-adres. Bekijk nu welke processen luisteren:
sudo ss -tlnpState Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 [::]:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:8080 docker-proxyLees de Local Address-kolom nauwkeurig. 0.0.0.0:22 betekent "luisteren op elk IPv4-adres." [::]:22 betekent "luisteren op elk IPv6-adres." 127.0.0.1:5432 is gebonden aan loopback en is niet publiek toegankelijk, dus de Postgres-regel is veilig. De twee [::]-regels beantwoorden het volledige internet via IPv6, en de docker-proxy-regel is het type dat u vergeet dat u het heeft gestart.
De meeste daemons zijn standaard gebonden aan ::, omdat op Linux een ::-socket meestal ook IPv4 accepteert. De standaardinstelling van een nieuwe server is daarom "antwoorden op beide stacks, overal." Uw firewall is het enige dat dit tegenhoudt. Een firewall die slechts één stack ziet, vormt daarom een groot risico.
Waar het IPv6-gat daadwerkelijk vandaan komt
Er zijn vier veelvoorkomende oorzaken. Op een specifieke machine kan er één of meerdere van deze oorzaken aanwezig zijn.
1. Een cloud-firewall die alleen IPv4 filtert. Veel firewalls van providers en security-group producten zijn ontwikkeld rondom IPv4. Deze negeren IPv6 of vereisen aparte IPv6-regels die u handmatig moet toevoegen. Als uw enige firewall de firewall in het dashboard van de provider is en deze dekt geen IPv6, dan staan uw [::] services open, ongeacht wat er staat over port 22 op IPv4. Lees de firewall-documentatie van uw provider en zoek specifiek naar het woord IPv6.
2. Handmatig gemaakte iptables zonder ip6tables. Het iptables commando beïnvloedt alleen de IPv4-tables. IPv6 heeft een volledig apart commando, ip6tables, met eigen regels. Als u een firewall-script heeft geschreven met alleen iptables -A INPUT ... regels en nooit de bijbehorende ip6tables regels heeft toegevoegd, dan is uw IPv6-firewall leeg. Een lege INPUT-chain met een standaard ACCEPT-policy staat alles toe:
sudo ip6tables -L INPUT -nChain INPUT (policy ACCEPT)
target prot opt source destinationDeze output laat de volledige valstrik in één scherm zien. IPv4 wordt gefilterd, terwijl IPv6 alles accepteert.
3. Docker die poorten direct voorbij uw firewall publiceert. Wanneer u docker run -p 8080:80 uitvoert, voegt Docker eigen regels toe vóór die van UFW. Een gepubliceerde port is hierdoor bereikbaar, zelfs als ufw status aangeeft dat de port geweigerd wordt. Bij moderne Docker geldt dit ook voor IPv6. Waarom Docker UFW omzeilt en hoe u container-ports correct filtert legt het mechanisme en de oplossingen uit. Zie de basis van Docker Compose op een VPS voor hoe deze gepubliceerde ports worden gedeclareerd.
4. UFW waarbij IPv6 is uitgeschakeld. UFW ondersteunt IPv6, maar alleen als dit expliciet is aangegeven. Controleer de instelling:
grep IPV6 /etc/default/ufwModerne Ubuntu-versies leveren IPV6=yes, waardoor UFW elke regel op beide stacks toepast. Als u IPV6=no ziet, afkomstig van een oude image of een oude handleiding, dan is elke geschreven UFW-regel alleen voor IPv4 en blijft IPv6 onbeheerd.
Zie precies wat u blootstelt
Gok niet. Meet het vanaf de buitenkant. Maak eerst een lijst van uw listeners en noteer elke listener die gebonden is aan :::
sudo ss -tlnp | grep '::'Maak vervolgens vanaf een andere machine verbinding met het publieke IPv6-adres van de server en probeer een poort die volgens u gesloten is:
curl -6 -v http://[2001:db8:2a::1]:8080/Als dit een pagina of een banner retourneert, staat de poort open op IPv6. Een gesloten poort geeft Connection refused of een timeout. Gebruik nmap vanaf een externe machine om het IPv6-adres te scannen voor een volledig overzicht:
nmap -6 2001:db8:2a::1Elke poort die nmap als open rapporteert over IPv6 is een poort die het hele internet kan bereiken, ongeacht wat uw IPv4-scan liet zien. Het naast elkaar vergelijken van de IPv4- en IPv6-scans is de snelste manier om het verschil te vinden: alles wat open staat op -6 maar gesloten is op IPv4, is een service die uw firewall mist.
Sluit het gat
Zorg dat UFW beide stacks dekt en standaard op deny staat. Controleer de wijziging, stel een default-deny inbound policy in en sta alleen toe wat noodzakelijk is:
sudo sed -i 's/^IPV6=no/IPV6=yes/' /etc/default/ufw
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseAls UFW al actief was toen u IPV6=yes wijzigde, treedt de verandering pas in werking nadat u sudo ufw reload heeft uitgevoerd.
ufw status vermeldt elke regel twee keer: eenmaal zonder en eenmaal met een (v6) suffix. Wanneer u de (v6) regels ziet, filtert UFW IPv6:
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)Als u iptables handmatig beheert, kopieer dan elke regel naar ip6tables, of stap over naar nftables. De inet tables van nftables dekken IPv4 en IPv6 op één plek, wat deze fouten voorkomt. Een enkele nftables inet filter table is de meest efficiënte oplossing wanneer u zelf regels schrijft.
Koppel services die niet publiek hoeven te zijn aan loopback. Een database, een admin panel of een metrics endpoint heeft zelden een publiek adres nodig. Koppel deze aan 127.0.0.1 en ::1 zodat de service nooit luistert op een routeerbaar adres. Stel voor Postgres listen_addresses = 'localhost' in. Koppel een app server aan 127.0.0.1 en plaats een reverse proxy ervoor. Het sluiten van de listener is effectiever dan een firewall gebruiken, omdat er dan niets bereikbaar is.
Vertrouw niet op UFW voor de gepubliceerde poorten van Docker. Publiceer container poorten op een specifiek adres in plaats van op alle interfaces, bijvoorbeeld -p 127.0.0.1:8080:80. Hierdoor is de poort alleen bereikbaar vanaf de host en de services die u bewust proxy't. Wanneer een container echt publiek moet zijn, plaats deze dan achter een Traefik reverse proxy en publiceer alleen de proxy, niet elke individuele app.
Voeg IPv6 regels toe aan de firewall van uw provider, of accepteer dat dit niet uw firewall is voor IPv6 en laat UFW of nftables op de host deze taak uitvoeren.
Controleer of u daadwerkelijk gesloten bent
Voer de externe test opnieuw uit nadat u de wijzigingen heeft doorgevoerd:
curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1De poort die eerder reageerde, moet nu weigeren of een time-out geven. nmap moet de poort als filtered of closed rapporteren. Als een poort nog steeds open is, controleer dan de vier bovenstaande bronnen: een service die nog steeds aan :: is gekoppeld zonder regel ervoor, een Docker-regel die voor UFW staat, of een firewall van de provider die IPv6 helemaal niet herkent.
Het volledig buiten het publieke internet houden van gevoelige services biedt nog meer beveiliging. Plaats SSH en admin panels achter een WireGuard VPN en blokkeer de poorten via de firewall, zodat ze alleen via de tunnel reageren. De kwestie van IPv6-blootstelling is dan niet meer van toepassing op deze services. Om brute-force scans op publieke services te vertragen, kunt u Fail2ban voor SSH gebruiken in combinatie met een default-deny firewall.
Als poorten nieuw voor u zijn, lees dan eerst wat poorten zijn en hoe services luisteren.
FAQ
Blokkeert UFW standaard IPv6?
Op een moderne Ubuntu 24.04 installatie is het antwoord ja. UFW leest IPV6=yes uit /etc/default/ufw en past elke regel toe op zowel IPv4 als IPv6. ufw status toont de IPv6-regels met een (v6) suffix. Problemen ontstaan bij IPV6=no (van een oude image of tutorial), wanneer u vertrouwt op een firewall van een provider die alleen IPv4 filtert, of wanneer Docker een poort publiceert buiten UFW om. Controleer de instelling met grep IPV6 /etc/default/ufw.
Hoe controleer ik welke poorten mijn VPS blootstelt op IPv6?
Voer sudo ss -tlnp uit en noteer elke listener waarvan het lokale adres begint met [::]. Dit betekent dat de service reageert op elke IPv6-interface. Test vervolgens vanaf een andere machine het publieke IPv6-adres van de server direct met curl -6 -v http://[YOUR:IPV6::ADDR]:PORT/, of scan het met nmap -6 YOUR:IPV6::ADDR. Elke poort die open staat in de IPv6-scan maar gesloten is op IPv4, vormt een beveiligingslek.
Waarom is de poort van mijn Docker-container bereikbaar terwijl UFW aangeeft dat deze geblokkeerd is?
Docker voegt eigen firewall-regels toe vóór de regels van UFW wanneer u een poort publiceert met -p. De gepubliceerde poort is hierdoor bereikbaar, ook al geeft ufw status aan dat deze geweigerd is. Dit gebeurt op IPv4, en ook op IPv6 wanneer de IPv6-ondersteuning van Docker aan staat. Publiceer naar een specifiek adres zoals -p 127.0.0.1:8080:80, of plaats de container achter een reverse proxy en publiceer alleen de proxy.
Heb ik nog een IPv6-firewall nodig als mijn IPv4-firewall correct is ingesteld?
Ja. IPv4 en IPv6 zijn gescheiden netwerkstacks met gescheiden firewall-regels. Een perfecte set IPv4-regels heeft geen effect op IPv6-verkeer. Als uw VPS een publiek IPv6-adres heeft (wat bijna altijd het geval is), dan blijft elke service die luistert op :: bereikbaar via IPv6, totdat een IPv6-firewallregel of een loopback-binding dit stopt.
Hoe zorg ik dat een service alleen op IPv4 of alleen op localhost luistert?
Stel het bind-adres van de service in via de eigen configuratie van de service. Bind aan 127.0.0.1 voor alleen IPv4 loopback, of aan 0.0.0.0 voor alle IPv4-adressen zonder IPv6-listener. Postgres gebruikt listen_addresses, SSH gebruikt ListenAddress, en de meeste app-servers hebben een host- of bind-flag. Controleer het resultaat met sudo ss -tlnp en verifieer dat Local Address geen [::] meer toont.