SSD Nodes Learn 🎉 VPS vanaf $5.50/mnd
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-21

FTP passive mode werkt niet: firewall oplossing

FTP logt in maar de directory listing blijft hangen door geblokkeerde poorten. Configureer een vast poortbereik en open de firewall voor de dataverbinding om dit op te lossen.

Waarom FTP wel inlogt maar de directory-listing blijft hangen

FTP passive mode werkt niet achter een firewall omdat FTP twee TCP-verbindingen gebruikt in plaats van één. De verbinding met poort 21 verwerkt de login en de commando's, waardoor de gebruikersnaam en het wachtwoord worden geaccepteerd en de firewall correct lijkt te staan. De eerste ls vereist vervolgens een tweede verbinding op een andere poort. De firewall staat deze verbinding niet toe, waardoor de client blijft wachten totdat de verbinding verloopt (timeout).

De oplossing is een vast bereik aan poorten voor deze dataverbindingen, in combinatie met een firewallregel die dit bereik toestaat. Een server achter NAT (network address translation) heeft nog één instelling nodig zodat deze het juiste adres adverteert. Voorheen deden connection tracking helpers dit werk voor u. Tegenwoordig is dat niet meer het geval, en het is nuttig om te weten waarom voordat u een verouderde handleiding kopieert.

Het controlekanaal en het datakanaal

FTP (file transfer protocol) is gespecificeerd in RFC 959 en dateert van vóór zowel NAT als de stateful firewall. Een sessie opent één controleverbinding naar TCP-poort 21 en houdt deze gedurende de gehele sessie open. Commando's worden als platte tekst verstuurd. Antwoorden komen terug als een driecijferige code en een regel tekst. Die verbinding transporteert nooit bestandsinhoud.

Elk stuk data krijgt een eigen TCP-verbinding: één voor een directory-listing (LIST), één voor elke download (RETR), één voor elke upload (STOR). Deze wordt geopend, eenmalig gebruikt en weer gesloten. Authenticatie vindt volledig plaats via het controlekanaal, waardoor een verbroken datapad er altijd hetzelfde uitziet: een geslaagde login, gevolgd door een hangende verbinding. Als de client een 230-antwoord geeft en vervolgens stopt bij de listing, dan is er een probleem met het datakanaal en niet met de inloggegevens.

Actieve modus: de server maakt verbinding met de client

In de actieve modus kiest de client een poort, luistert hierop en vertelt de server waar deze moet aankloppen:

PORT 192,168,1,50,195,80

De eerste vier getallen vormen het IP-adres van de client. De laatste twee getallen vormen de poort, gecodeerd als twee bytes: 195 * 256 + 80 = 50000. De server opent vervolgens de dataverbinding vanaf zijn eigen poort 20 naar poort 50000 op de client.

Deze verbinding is inkomend en ongevraagd vanuit het perspectief van de client, waardoor een firewall op de client deze blokkeert. Als de client zich achter een thuisrouter bevindt, is het adres in het PORT-commando een privaat adres dat de server in het geheel niet kan bereiken. De actieve modus is de reden waarom FTP bekendstaat als een protocol dat vaak niet werkt.

Passieve modus: de client opent beide verbindingen

De passieve modus draait de dataconnectie om. De client verstuurt PASV en de server antwoordt met een eigen adres en poort:

227 Entering Passive Mode (203,0,113,10,195,80)

De codering is identiek, dus de client maakt verbinding met 203.0.113.10 op poort 50000. De client opent nu beide verbindingen; dit is de reden waarom de passieve modus werkt achter NAT aan de clientzijde en waarom elke moderne client hier als eerste om vraagt.

Het probleem is verplaatst in plaats van verdwenen. De ongevraagde inkomende verbinding komt nu aan op uw server, op een hoge poort die bij elke overdracht wijzigt. Die firewall is van u, dus nu is het probleem ook van u.

EPSV (extended passive mode, RFC 2428) berust op hetzelfde principe met een schoner antwoord:

229 Entering Extended Passive Mode (|||50000|)

Hierin staat geen adres. De client hergebruikt het adres dat al in gebruik is voor de controleverbinding. Dit zorgt ervoor dat het werkt via IPv6 en elimineert een hele klasse aan NAT-fouten. De handleiding van curl stelt dat curl normaal gesproken eerst EPSV probeert vóór PASV. De poort wordt nog steeds tijdens runtime gekozen, dus EPSV verandert niets aan uw firewallregels.

Waarom een normale firewallregel het datakanaal niet kan toestaan

Omdat het poortnummer nog niet bestaat op het moment dat u de regel schrijft. De server kiest dit per overdracht. Bij de standaardinstellingen documenteert vsftpd pasv_min_port en pasv_max_port als 0, wat betekent "gebruik een willekeurige poort". De dataverbinding kan dus binnenkomen op elke poort boven 1023. sudo ufw allow 21/tcp staat het controlekanaal toe en niets anders, en dat is precies de configuratie die zorgt voor een werkende login maar een niet-werkende bestandslijst. Als het concept van een service die op één vaste poort luistert nog onduidelijk is, biedt hoe poorten en listening sockets werken op Linux de nodige achtergrondinformatie.

Een stateful firewall houdt verbindingen bij, en de kernel kan een nieuwe verbinding toelaten als RELATED bij een bestaande verbinding. Voor FTP is daarvoor iets nodig dat de controlestroom leest en het poortnummer uit een 227- of PORT-regel haalt. Standaard doet niets dit.

Waarom de FTP connection tracking helper niet langer de oplossing is

De kernelmodule nf_conntrack_ftp is waar oudere handleidingen naar verwijzen. Deze leest het onversleutelde controlekanaal, identificeert de aangekondigde poort en registreert een verwachting, waardoor de dataverbinding wordt toegelaten zonder dat er een specifieke regel voor die poort nodig is. Sinds het schrijven van die handleidingen zijn er vier zaken veranderd.

Automatische toewijzing van helpers is uitgeschakeld. De kernel documenteert de nf_conntrack_helper sysctl als "0 - disabled (default)" en voegt toe: "If disabled it is required to set up iptables rules to assign helpers to connections." Het laden van de module heeft op zichzelf geen effect.

In huidige kernels is de schakelaar verdwenen. Voer sysctl net.netfilter.nf_conntrack_helper uit. Een antwoord van sysctl: cannot stat /proc/sys/net/netfilter/nf_conntrack_helper: No such file or directory betekent dat de kernel geen automatische helper-toewijzing meer heeft die ingeschakeld kan worden. Als u wel een getal terugkrijgt, is de schakelaar nog aanwezig en is de standaardwaarde 0.

De firewall-frontends hebben deze methode eveneens als verouderd gemarkeerd. man ufw-framework op Ubuntu 24.04 stelt over de IPT_MODULES regel in /etc/default/ufw: "Unconditional loading of connection tracking modules (nf_conntrack_*) in this manner is deprecated", en voegt toe dat helper-regels "must be managed in via the RULES FILES". firewalld documenteert AutomaticHelpers in firewalld.conf als "Deprecated. This option is ignored and no longer used." Het toewijzen van een helper betekent nu dat u handmatig een expliciete regel met het CT target moet schrijven. Dit is meer werk dan de onderstaande oplossing en werkt niet meer zodra u TLS inschakelt. iptables en nftables op Ubuntu beschrijft waar deze regels daadwerkelijk thuishoren.

TLS beëindigt de discussie. Een helper werkt door het controlekanaal als tekst te lezen. Versleutel dat kanaal en de helper ziet enkel cijfertekst, waardoor de poort niet gevonden kan worden. Hier is geen oplossing voor, en dat hoort ook zo te zijn: een middlebox die uw controlekanaal kan lezen, is een middlebox die uw wachtwoord kan lezen.

Declareer een passief poortbereik op de server

Elke FTP-server kan worden geconfigureerd om passieve poorten te kiezen uit een bereik dat u zelf bepaalt. De namen van de opties verschillen per software, dus raadpleeg de documentatie van de server die u daadwerkelijk gebruikt.

vsftpd, in /etc/vsftpd.conf:

pasv_enable=YES
pasv_min_port=30000
pasv_max_port=30099

pasv_enable gebruikt standaard al YES. De twee poortopties staan standaard op 0, het hierboven beschreven gedrag waarbij "elke poort wordt gebruikt". Pas de wijzigingen toe met sudo systemctl restart vsftpd en controleer daarna met systemctl status vsftpd of de service weer actief is. vsftpd weigert te starten bij een configuratieregel die het niet kan parsen in plaats van deze te negeren. Als de herstart mislukt, lees dan journalctl -u vsftpd -n 20 voor de 500 OOPS:-regel waarin de optie staat die u zojuist heeft ingevoerd.

ProFTPD, in proftpd.conf:

PassivePorts 30000 30099

ProFTPD specificeert hier geen standaardwaarde: zonder de richtlijn kiest de kernel de poort. De documentatie vermeldt ook dat wanneer er geen poort in uw bereik vrij is, de server terugvalt op een door de kernel toegewezen poort en een bericht logt. Een bereik dat te klein is, faalt daarom af en toe in plaats van direct een foutmelding te geven, wat veel lastiger te diagnosticeren is. Gebruik niet-geprivilegieerde poorten, 1024 en hoger.

Pure-FTPd gebruikt een vlag, -p first:last, die in man pure-ftpd wordt gedocumenteerd als "Gebruik alleen poorten in het bereik van eerste tot laatste inclusief voor downloads in passieve modus", wat "pure-ftpd compatibeler maakt met pakketfilters". Gepackagede builds verpakken die vlag meestal in een configuratiebestand, dus raadpleeg de documentatie van uw distributie voor de bestandsnaam in plaats van te gokken.

Hoeveel poorten heeft u nodig? Eén per actieve dataverbinding. Een gesloten TCP-poort blijft enkele minuten in TIME_WAIT staan voordat deze opnieuw kan worden gebruikt, dus houd rekening met een veelvoud van uw verwachte piekbelasting. Honderd poorten is ruim voldoende voor enkele gebruikers; een drukke publieke server heeft er veel meer nodig.

Waar moet het bereik zich bevinden? Voer eerst sysctl net.ipv4.ip_local_port_range uit. Op een standaard Ubuntu-systeem leest dit 32768 60999, de poorten die de kernel toewijst voor uitgaande verbindingen. Een passief bereik binnen dat venster kan botsen met een uitgaande verbinding die de poort al bezet houdt, dus houd het bereik daaronder. 30000 tot 30099 is veilig op een standaard systeem. Controleer uw eigen systeem in plaats van op dat getal te vertrouwen.

Open hetzelfde bereik in de firewall

ufw schrijft een bereik met een dubbele punt, en de handleiding stelt dat een bereik of een lijst "ook kan worden gebruikt om meerdere poorten op te geven, in welk geval het protocol vereist is":

sudo ufw allow 21/tcp
sudo ufw allow 30000:30099/tcp
sudo ufw status verbose

ufw status verbose zou nu beide vermeldingen moeten weergeven. Hetzelfde commando zonder /tcp wordt geweigerd met een foutmelding die aangeeft dat u tcp of udp moet opgeven, omdat ufw niet zal gokken. ufw regelsyntaxis op een VPS behandelt de rest.

firewalld schrijft het bereik met een koppelteken en vereist een herlaadactie:

sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=30000-30099/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

--add-service=ftp opent 21/tcp en vraagt de ftp-helper aan, zoals gedefinieerd in de meegeleverde servicedefinitie. Dit opent niet uw passieve bereik, dus op zichzelf laat dit u achter op het punt waar u begon. firewalld zones en services op een VPS biedt een breder overzicht.

Directe nftables, binnen uw input-chain:

tcp dport { 21, 30000-30099 } accept

Nog één firewall om te onthouden: de meeste providers draaien een netwerkfirewall in het configuratiescherm, buiten het besturingssysteem om. Als de regels op de server correct lijken en pakketten nog steeds niet aankomen, open dan daar ook hetzelfde bereik.

Het publieke adres van de server instellen bij gebruik van NAT

Voer ip -4 addr show uit op de server. Als het adres op de interface overeenkomt met het adres waarmee clients verbinding maken, kunt u deze sectie overslaan. Als de interface een privaat adres bevat (10.x, 172.16 tot 172.31.x, 192.168.x) en het platform hierop een publiek adres mapt, is het publieke adres van de server onbekend bij de server zelf. vsftpd documenteert de standaardwaarde voor pasv_address als "het adres wordt overgenomen van de inkomende verbonden socket", waardoor het 227-antwoord het private adres bevat en de client naar een onbereikbare locatie wordt gestuurd.

FileZilla benoemt dit specifiek:

Server sent passive reply with unroutable address. Using server address instead.

FileZilla herstelt dit en gaat door. Veel andere clients doen dit niet. Zij bellen 10.0.0.5 en blijven hangen.

curl verbergt het probleem eveneens, wat relevant is als u curl gebruikt voor uw tests. De handleiding stelt dat --ftp-skip-pasv-ip "standaard is ingeschakeld (toegevoegd in 7.74.0)", waardoor curl het adres in het 227-antwoord negeert en het adres van de controleverbinding hergebruikt. Een overdracht die werkt met curl kan om deze reden alsnog falen in een grafische client.

Stel het adres expliciet in. vsftpd gebruikt pasv_address=203.0.113.10, plus pasv_addr_resolve=YES (standaard NO) als u liever een hostnaam opgeeft. ProFTPD gebruikt MasqueradeAddress, dat een adres, een DNS-naam of een interfacenaam accepteert. Pure-FTPd gebruikt -P, gedocumenteerd voor situaties waarin "de server zich achter een masquerading (NAT) box bevindt". EPSV vermijdt het hele probleem omdat het antwoord geen adresveld bevat, maar u kunt hier niet op vertrouwen, aangezien de client bepaalt welk commando wordt verzonden.

Wat TLS-wijzigingen inhouden

FTPS is FTP over TLS (transport layer security). De client maakt verbinding met poort 21 zoals gebruikelijk, verstuurt AUTH TLS om het controlekanaal te beveiligen en verstuurt vervolgens PROT P om ook het datakanaal te versleutelen. Standaard FTP verstuurt het wachtwoord als leesbare tekst over de lijn; als u FTP moet blijven gebruiken, gebruik dan FTPS. vsftpd wordt geleverd met ssl_enable waarbij de standaardwaarde NO is.

Dit heeft twee gevolgen. Geen enkele connection tracking helper kan werken, wat hetzelfde is als het bovenstaande punt, maar dan vanuit een ander perspectief bekeken. Bovendien zal sudo tcpdump -nAi any 'tcp port 21' u niet langer het 227-antwoord tonen. Wanneer u dus wilt weten welk adres en welke poort de server heeft geadverteerd, dient u het logbestand van de server zelf te raadplegen in plaats van het netwerkverkeer te inspecteren.

De wijziging testen vanaf een externe locatie

Voer deze commando's uit vanaf een andere machine. Testen vanaf de server zelf omzeilt de firewall die u probeert te herstellen.

sudo ss -ltnp | grep :21
curl -v --disable-epsv --user ftpuser:secret ftp://example.com/
nc -vz example.com 30000

ss hoort aan te tonen dat de FTP-daemon luistert op poort 21. Er luistert niets op het passieve bereik terwijl de server inactief is, omdat die sockets pas worden aangemaakt voor een bestandsoverdracht en daarna weer worden gesloten.

--disable-epsv dwingt curl om het PASV-pad te volgen; dit is het pad dat het adresprobleem blootlegt. De trace toont het antwoord van de server, gevolgd door het adres en de poort waarmee curl verbinding probeert te maken:

< 227 Entering Passive Mode (203,0,113,10,117,52)

117 * 256 + 52 = 30004, dit valt binnen het opgegeven bereik. Een privaat adres op die regel betekent dat pasv_address niet is ingesteld. Een poort buiten uw bereik betekent dat de server de configuratiewijziging niet heeft ingelezen; controleer daarom of u het bestand heeft bewerkt dat de actieve service daadwerkelijk gebruikt.

nc beantwoordt de firewall-vraag op zichzelf. Een onmiddellijke Connection refused betekent dat het pakket de server heeft bereikt en daar niets vond dat luisterde; dit is het juiste resultaat voor een inactieve passieve poort: uw regel werkt. Een verbinding die blijft hangen totdat nc opgeeft, betekent dat iets het pakket stilletjes heeft gedropt. Dit is een firewall, hetzij op de server zelf, hetzij in het configuratiepaneel van uw provider. Dat onderscheid is hetzelfde als beschreven in refused versus timed out voor SSH, en het is van toepassing op elke poort.

Moet u nog steeds FTP gebruiken?

Voor nieuwe projecten niet. SFTP (SSH file transfer protocol) draait binnen een enkele SSH-verbinding op poort 22. Er is geen tweede kanaal, geen passief bereik, geen NAT-instelling en geen extra daemon om te beveiligen, omdat OpenSSH dit al biedt. sftp user@example.com werkt op een systeem waar u nooit een bestandsoverdrachtservice heeft geconfigureerd. Om iemand toegang te geven tot bestanden en niets anders, gebruikt sshd_config de optie ForceCommand internal-sftp in combinatie met ChrootDirectory. Die map moet eigendom zijn van root en mag niet beschrijfbaar zijn voor de gebruiker, anders weigert sshd de sessie en logt het een bad ownership or modes for chroot directory-regel.

FTP is nog steeds nuttig wanneer de tegenpartij niet kan wijzigen. Scanners en multifunctionele printers bevatten firmware die alleen FTP spreekt. Laboratorium- en industriële apparatuur draait vaak op een vaste image die niemand opnieuw zal certificeren. Zakelijke partners publiceren een FTPS-drop en voegen geen protocol toe voor één leverancier. In elk van die gevallen is het passieve bereik plus de bijbehorende firewallregel het volledige werk, en is FTPS in plaats van standaard FTP de versie die u moet gebruiken. Het ontwerp met twee kanalen is een beslissing uit 1985 die nu in een wereld draait waarop het nooit was voorbereid, een verhaal dat wordt behandeld in de geschiedenis van bestandsoverdrachtprotocollen.

FAQ

Waarom lukt het inloggen via FTP wel, maar blijft de mappenlijst hangen?

Het inloggen gebruikt alleen de controleverbinding op poort 21, die uw firewall toestaat. De mappenlijst vereist een tweede TCP-verbinding op een andere poort, en die verbinding wordt geblokkeerd. Definieer een passief poortbereik op de FTP-server, open hetzelfde bereik in de firewall, en de lijst wordt correct geladen. Een hangende mappenlijst is een probleem met het datakanaal, nooit een wachtwoordprobleem.

Welke poorten moet ik openen voor de passieve modus van FTP?

Poort 21 voor het controlekanaal, plus het bereik dat u heeft geconfigureerd voor passieve dataverbindingen. Er is geen standaardbereik, omdat u dit zelf kiest. Een bereik zoals 30000 tot 30099 werkt prima: stem de grootte af op uw piekbelasting van gelijktijdige overdrachten en houd het bereik buiten de uitgaande poorten van de kernel, die u kunt inzien met sysctl net.ipv4.ip_local_port_range. Als uw provider een netwerkfirewall in het configuratiescherm aanbiedt, open daar dan hetzelfde bereik.

Heb ik nog steeds nf_conntrack_ftp nodig?

Nee, en op een moderne kernel kunt u hier niet op vertrouwen. Automatische toewijzing van helpers is standaard uitgeschakeld en in recente kernels is de net.netfilter.nf_conntrack_helper-schakelaar verwijderd, waardoor sysctl meldt dat het bestand niet bestaat. De handleiding van ufw noemt het onvoorwaardelijk laden van deze modules verouderd en firewalld negeert AutomaticHelpers volledig. Een helper moet bovendien het controlekanaal als platte tekst kunnen lezen, waardoor deze stopt met werken zodra u FTPS inschakelt. Definieer in plaats daarvan een passief poortbereik.

Waarom meldt mijn FTP-client dat het passieve antwoord een onbereikbaar adres bevat?

De server antwoordde met PASV met het adres dat hij op zijn eigen interface ziet, en dat adres is privaat. Dit gebeurt wanneer het platform een publiek adres naar een privaat adres mapt. Stel het publieke adres expliciet in: pasv_address in vsftpd, MasqueradeAddress in ProFTPD, of -P in Pure-FTPd. FileZilla omzeilt dit door het adres te hergebruiken waarmee het al verbonden was, en logt "Using server address instead"; daarom werken sommige clients wel bij deze foutieve configuratie en blijven andere hangen.

Moet ik FTPS of SFTP gebruiken?

Gebruik SFTP voor alles wat u aan beide kanten beheert: één verbinding via SSH op poort 22, geen datakanaal om te openen, en het is al actief. FTPS is FTP over TLS, dus het behoudt het ontwerp met twee kanalen en elk firewallprobleem dat daarbij hoort. Kies hiervoor wanneer de tegenpartij niets anders ondersteunt. Gebruik geen onversleutelde FTP over het internet, omdat het wachtwoord als leesbare tekst over het netwerk wordt verstuurd.