FTP-Passivmodus: Firewall blockiert Verzeichnisauflistung
FTP meldet sich an, doch die Verzeichnisauflistung hängt. Erlauben Sie den festen passiven Portbereich zusätzlich zu TCP 21 in der Firewall.
Warum sich FTP anmeldet, aber die Verzeichnisauflistung hängt
Der passive FTP-Modus schlägt an einer Firewall fehl, weil FTP zwei TCP-Verbindungen verwendet und nicht nur eine. Die Verbindung zu Port 21 überträgt die Anmeldung und die Befehle. Deshalb werden Benutzername und Passwort akzeptiert und die Firewall-Konfiguration wirkt korrekt. Für den ersten ls ist anschließend eine zweite Verbindung zu einem anderen Port erforderlich. Die Firewall erlaubt diese Verbindung nicht. Der Client wartet daher, bis ein Timeout auftritt.
Die Lösung ist ein fester Portbereich für diese Datenverbindungen sowie eine Firewall-Regel, die denselben Bereich erlaubt. Ein Server hinter NAT (Network Address Translation) benötigt zusätzlich eine Einstellung, damit er die richtige Adresse ankündigt. Helfer für das Connection Tracking haben diese Aufgabe früher automatisch übernommen. Das ist heute nicht mehr der Fall. Den Grund sollten Sie kennen, bevor Sie eine alte Anleitung übernehmen.
Der Steuerkanal und der Datenkanal
FTP (File Transfer Protocol) ist in RFC 959 spezifiziert und wurde vor NAT und Stateful Firewalls entwickelt. Eine Sitzung öffnet eine Steuerverbindung zu TCP-Port 21 und hält sie während der gesamten Sitzung offen. Befehle werden als Klartext übertragen. Antworten bestehen aus einem dreistelligen Code und einer Textzeile. Diese Verbindung überträgt niemals Dateiinhalte.
Jede Datenübertragung verwendet eine eigene TCP-Verbindung: eine für eine Verzeichnisauflistung (LIST), eine für jeden Download (RETR) und eine für jeden Upload (STOR). Sie wird geöffnet, einmal verwendet und anschließend geschlossen. Die Authentifizierung erfolgt vollständig über den Steuerkanal. Ein fehlerhafter Datenpfad äußert sich daher immer gleich: Die Anmeldung ist erfolgreich, danach hängt der Vorgang. Wenn der Client eine 230-Antwort ausgibt und anschließend bei der Verzeichnisauflistung stehen bleibt, liegt das Problem beim Datenkanal und nicht bei den Zugangsdaten.
Aktiver Modus: Der Server verbindet sich zurück zum Client
Im aktiven Modus wählt der Client einen Port aus, lauscht darauf und teilt dem Server mit, wohin er die Verbindung herstellen soll:
PORT 192,168,1,50,195,80Die ersten vier Zahlen sind die IP-Adresse des Clients. Die letzten beiden Zahlen geben den Port als zwei Bytes an: 195 * 256 + 80 = 50000. Der Server öffnet die Datenverbindung anschließend von seinem eigenen Port 20 zu Port 50000 auf dem Client.
Aus Sicht des Clients ist diese Verbindung eingehend und nicht angefordert. Eine Client-Firewall verwirft sie daher. Befindet sich der Client hinter einem Heimrouter, enthält der PORT-Befehl eine private Adresse, die der Server überhaupt nicht erreichen kann. Der aktive Modus ist der Grund für den Ruf von FTP, häufig nicht zu funktionieren.
Passivmodus: Der Client öffnet beide Verbindungen
Im Passivmodus wird die Datenverbindung umgekehrt aufgebaut. Der Client sendet PASV, und der Server antwortet mit einer eigenen Adresse und einem eigenen Port:
227 Entering Passive Mode (203,0,113,10,195,80)Die Codierung ist identisch. Der Client verbindet sich also mit 203.0.113.10 an Port 50000. Der Client öffnet nun beide Verbindungen. Deshalb funktioniert der Passivmodus hinter NAT auf der Clientseite und wird von jedem aktuellen Client zuerst angefordert.
Das Problem ist nicht verschwunden, sondern hat sich verlagert. Die nicht angeforderte eingehende Verbindung trifft nun auf Ihren Server. Sie verwendet einen hohen Port, der sich bei jeder Übertragung ändert. Diese Firewall gehört Ihnen. Damit liegt auch dieses Problem bei Ihnen.
EPSV (erweiterter Passivmodus, RFC 2428) folgt demselben Prinzip, verwendet aber eine übersichtlichere Antwort:
229 Entering Extended Passive Mode (|||50000|)Die Antwort enthält keine Adresse. Der Client verwendet die Adresse erneut, die er bereits für die Steuerverbindung nutzt. Dadurch funktioniert der Modus über IPv6, und eine ganze Klasse von NAT-Fehlern entfällt. Im Handbuch von curl steht, dass curl normalerweise zuerst EPSV und danach PASV versucht. Der Port wird weiterhin zur Laufzeit ausgewählt. EPSV ändert daher nichts an Ihren Firewall-Regeln.
Warum eine normale Firewall-Regel den Datenkanal nicht freigeben kann
Die Portnummer existiert noch nicht, wenn Sie die Regel schreiben. Der Server wählt sie für jede Übertragung. In der Standardkonfiguration dokumentiert vsftpd pasv_min_port und pasv_max_port als 0, also „beliebigen Port verwenden“. Dadurch kann die Datenverbindung an jedem Port oberhalb von 1023 eingehen. sudo ufw allow 21/tcp erlaubt den Steuerkanal und nichts anderes. Genau diese Konfiguration führt zu einer funktionierenden Anmeldung und einer leeren Verzeichnisauflistung. Falls die Vorstellung eines Dienstes, der auf einem festen Port lauscht, noch unklar ist, erklärt wie Ports und Listening-Sockets unter Linux funktionieren die Grundlagen.
Eine zustandsbehaftete Firewall verfolgt Verbindungen. Der Kernel kann eine neue Verbindung als RELATED zu einer bestehenden Verbindung zulassen. Bei FTP muss dafür jedoch ein Dienst den Steuerdatenstrom lesen und den Port aus einer 227- oder PORT-Zeile extrahieren. Standardmäßig übernimmt das kein Dienst.
Warum der FTP-Verbindungsverfolgungshelfer keine Lösung mehr ist
Das Kernelmodul nf_conntrack_ftp wird in älteren Anleitungen empfohlen. Es liest den unverschlüsselten Steuerkanal, ermittelt den angekündigten Port und registriert eine Erwartung. Dadurch wird die Datenverbindung zugelassen, ohne dass eine Regel ihren Port angeben muss. Seit der Veröffentlichung dieser Anleitungen haben sich vier Dinge geändert.
Die automatische Zuweisung von Helfern ist deaktiviert. Der Kernel dokumentiert den Sysctl-Schalter nf_conntrack_helper mit „0 - disabled (default)“ und ergänzt: „If disabled it is required to set up iptables rules to assign helpers to connections.“ Das Laden des Moduls allein bewirkt nichts.
In aktuellen Kerneln ist dieser Schalter nicht mehr vorhanden. Führen Sie sysctl net.netfilter.nf_conntrack_helper aus. Eine Antwort sysctl: cannot stat /proc/sys/net/netfilter/nf_conntrack_helper: No such file or directory bedeutet, dass der Kernel keine automatische Helferzuweisung mehr unterstützt, die aktiviert werden könnte. Wenn stattdessen eine Zahl ausgegeben wird, ist der Schalter noch vorhanden. Sein Standardwert ist dann 0.
Auch die Firewall-Frontends haben die Funktion als veraltet eingestuft. man ufw-framework auf Ubuntu 24.04 bezeichnet die Zeile IPT_MODULES in /etc/default/ufw als „Unconditional loading of connection tracking modules (nf_conntrack_*) in this manner is deprecated“ und ergänzt, dass Helferregeln „must be managed in via the RULES FILES“. firewalld dokumentiert AutomaticHelpers in firewalld.conf als „Deprecated. This option is ignored and no longer used.“ Einen Helfer zuzuweisen bedeutet nun, manuell eine explizite Regel mit dem Ziel CT zu schreiben. Das ist aufwendiger als die unten beschriebene Lösung und funktioniert nicht mehr, sobald Sie TLS aktivieren. iptables und nftables auf Ubuntu beschreibt, wo diese Regeln tatsächlich abgelegt werden.
TLS beendet dieses Verfahren. Ein Helfer funktioniert, indem er den Steuerkanal als Text liest. Wird dieser Kanal verschlüsselt, sieht der Helfer nur Chiffretext und kann den Port nicht ermitteln. Dafür gibt es keine Lösung. Das ist auch richtig so: Ein Netzwerkgerät, das Ihren Steuerkanal lesen kann, kann auch Ihr Passwort lesen.
Einen passiven Portbereich auf dem Server festlegen
Jeder FTP-Server kann so konfiguriert werden, dass er seine passiven Ports aus einem von Ihnen festgelegten Bereich auswählt. Die Namen der Optionen unterscheiden sich. Prüfen Sie daher die Dokumentation des tatsächlich eingesetzten Servers.
vsftpd wird in /etc/vsftpd.conf konfiguriert:
pasv_enable=YES
pasv_min_port=30000
pasv_max_port=30099pasv_enable ist bereits standardmäßig auf YES gesetzt. Die beiden Portoptionen sind standardmäßig auf 0 gesetzt. Dadurch wird das oben beschriebene Verhalten „beliebigen Port verwenden“ aktiviert. Wenden Sie die Änderung mit sudo systemctl restart vsftpd an. Prüfen Sie anschließend mit systemctl status vsftpd, ob der Dienst wieder läuft. vsftpd startet nicht, wenn es eine Konfigurationszeile nicht einlesen kann. Stattdessen verweigert es den Start. Wenn der Neustart fehlschlägt, lesen Sie journalctl -u vsftpd -n 20. Suchen Sie dort nach der 500 OOPS:-Zeile, die die gerade eingegebene Option nennt.
ProFTPD wird in proftpd.conf konfiguriert:
PassivePorts 30000 30099ProFTPD dokumentiert hier keinen Standardwert. Ohne diese Direktive wählt der Kernel den Port aus. Die Dokumentation weist außerdem darauf hin, dass der Server auf einen vom Kernel zugewiesenen Port ausweicht und eine Meldung protokolliert, wenn kein Port aus Ihrem Bereich frei ist. Ein zu kleiner Bereich führt daher gelegentlich zu Fehlern, statt kontrolliert fehlschlagen zu können. Das ist deutlich schwieriger zu diagnostizieren. Verwenden Sie nicht privilegierte Ports ab 1024.
Pure-FTPd verwendet das Flag -p first:last. Dieses ist in man pure-ftpd als „Nur Ports im inklusiven Bereich von first bis last für Downloads im passiven Modus verwenden“ dokumentiert. Dadurch wird „pure-ftpd mit Paketfiltern kompatibler“. Bei paketierten Builds wird dieses Flag normalerweise über eine Konfigurationsdatei gesetzt. Prüfen Sie daher die Dokumentation Ihrer Distribution auf den Dateinamen, statt ihn zu erraten.
Wie viele Ports benötigen Sie? Einen pro gleichzeitig bestehender Datenverbindung. Ein geschlossener TCP-Port bleibt einige Minuten lang in TIME_WAIT, bevor er wiederverwendet werden kann. Planen Sie daher ein Mehrfaches des erwarteten Spitzenwerts ein. Einhundert Ports reichen für einige Benutzer bequem aus. Ein stark ausgelasteter öffentlicher Server benötigt deutlich mehr.
Wo sollte der Bereich liegen? Führen Sie zuerst sysctl net.ipv4.ip_local_port_range aus. Auf einem unveränderten Ubuntu-System lautet die Ausgabe 32768 60999. Das sind die Ports, die der Kernel für ausgehende Verbindungen vergibt. Ein passiver Bereich innerhalb dieses Fensters kann mit einer bereits bestehenden ausgehenden Verbindung kollidieren, die den Port hält. Legen Sie den Bereich daher darunter. 30000 bis 30099 sind auf einem Standardsystem frei. Prüfen Sie Ihr eigenes System, statt dieser Zahl zu vertrauen.
Den gleichen Bereich in der Firewall öffnen
ufw schreibt einen Bereich mit einem Doppelpunkt. In der Manpage steht, dass ein Bereich oder eine Liste „auch verwendet werden kann, um mehrere Ports anzugeben; in diesem Fall ist das Protokoll erforderlich“:
sudo ufw allow 21/tcp
sudo ufw allow 30000:30099/tcp
sudo ufw status verboseufw status verbose sollte nun beide Einträge anzeigen. Derselbe Befehl ohne /tcp wird mit einem Fehler abgewiesen, der tcp oder udp verlangt, weil ufw nicht selbst entscheidet. ufw-Regelsyntax auf einem VPS behandelt die übrigen Fälle.
firewalld schreibt den Bereich mit einem Bindestrich und benötigt anschließend einen Reload:
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 öffnet 21/tcp und fordert den ftp-Helper an, den die mitgelieferte Servicedefinition festlegt. Der passive Bereich wird dadurch nicht geöffnet. Allein damit bleibt die Situation daher unverändert. firewalld-Zonen und -Dienste auf einem VPS erläutert die Zusammenhänge.
Direktes nftables innerhalb Ihrer input-Chain:
tcp dport { 21, 30000-30099 } acceptEine weitere Firewall darf nicht übersehen werden: Die meisten Provider betreiben außerhalb des Betriebssystems eine Netzwerk-Firewall im Control Panel. Wenn die Regeln auf dem Server korrekt aussehen und die Pakete trotzdem nicht ankommen, öffnen Sie dort ebenfalls denselben Bereich.
Geben Sie dem Server seine öffentliche Adresse bekannt, wenn er hinter NAT steht
Führen Sie ip -4 addr show auf dem Server aus. Wenn die Adresse auf dem Interface der Adresse entspricht, zu der sich die Clients verbinden, überspringen Sie diesen Abschnitt. Wenn das Interface eine private Adresse (10.x, 172.16 bis 172.31.x, 192.168.x) hat und die Plattform eine öffentliche Adresse darauf abbildet, kennt der Server seine eigene öffentliche Adresse nicht. Die vsftpd-Dokumentation beschreibt den Standardwert für pasv_address als „the address is taken from the incoming connected socket“. Daher enthält die 227-Antwort die private Adresse, und der Client wird an ein Ziel verwiesen, das er nicht erreichen kann.
FileZilla bezeichnet diesen Fall genau so:
Server sent passive reply with unroutable address. Using server address instead.FileZilla korrigiert das Problem und setzt die Verbindung fort. Viele andere Clients tun das nicht. Sie verbinden sich mit 10.0.0.5 und bleiben hängen.
Auch curl verbirgt das Problem. Das ist relevant, wenn Sie curl für den Test verwenden. Im Handbuch steht, dass --ftp-skip-pasv-ip „is enabled by default (added in 7.74.0)“. Daher ignoriert curl die Adresse in der 227-Antwort und verwendet erneut die Adresse der Steuerverbindung. Ein Transfer, der mit curl funktioniert, kann aus genau diesem Grund in einem grafischen Client trotzdem fehlschlagen.
Legen Sie die Adresse explizit fest. vsftpd verwendet pasv_address=203.0.113.10 sowie pasv_addr_resolve=YES (Standardwert NO), wenn Sie stattdessen einen Hostnamen angeben möchten. ProFTPD verwendet MasqueradeAddress. Diese Option akzeptiert eine Adresse, einen DNS-Namen oder einen Interface-Namen. Pure-FTPd verwendet -P. Diese Option ist für den Fall dokumentiert, dass „the server is behind a masquerading (NAT) box“. EPSV vermeidet das gesamte Problem, weil seine Antwort kein Adressfeld enthält. Darauf können Sie sich jedoch nicht verlassen, da der Client entscheidet, welchen Befehl er sendet.
Was sich durch TLS ändert
FTPS ist FTP über TLS (Transport Layer Security). Der Client verbindet sich wie gewohnt mit Port 21 und sendet AUTH TLS, um den Steuerkanal zu schützen. Anschließend sendet er PROT P, um auch den Datenkanal zu verschlüsseln. Bei einfachem FTP wird das Passwort als lesbarer Text über das Netzwerk übertragen. Wenn Sie FTP weiterhin benötigen, verwenden Sie FTPS. vsftpd wird mit ssl_enable ausgeliefert, das standardmäßig auf NO gesetzt ist.
Daraus ergeben sich zwei Folgen. Kein Connection-Tracking-Helper kann funktionieren. Das ist derselbe Punkt wie oben, nur aus der anderen Richtung betrachtet. Außerdem zeigt sudo tcpdump -nAi any 'tcp port 21' nicht mehr die 227-Antwort an. Wenn Sie wissen müssen, welche Adresse und welchen Port der Server angekündigt hat, lesen Sie stattdessen das Server-Log und nicht den Netzwerkverkehr.
Testen der Änderung von außen
Führen Sie diese Befehle auf einem anderen Rechner aus. Beim Testen direkt auf dem Server umgehen Sie die Firewall, die Sie korrigieren möchten.
sudo ss -ltnp | grep :21
curl -v --disable-epsv --user ftpuser:secret ftp://example.com/
nc -vz example.com 30000ss sollte zeigen, dass der FTP-Daemon auf Port 21 lauscht. Im passiven Portbereich lauscht im Leerlauf nichts, weil diese Sockets für eine Übertragung erstellt und danach geschlossen werden.
--disable-epsv zwingt curl auf den PASV-Pfad. Dieser Pfad macht das Adressproblem sichtbar. Die Ablaufverfolgung gibt zuerst die Antwort des Servers und anschließend die Adresse und den Port aus, die curl verwendet:
< 227 Entering Passive Mode (203,0,113,10,117,52)117 * 256 + 52 = 30004 liegt innerhalb des angegebenen Bereichs. Eine private Adresse in dieser Zeile bedeutet, dass pasv_address nicht gesetzt ist. Ein Port außerhalb Ihres Bereichs bedeutet, dass der Server die Konfigurationsänderung nicht eingelesen hat. Prüfen Sie daher, ob Sie die Datei bearbeitet haben, die der laufende Dienst verwendet.
nc beantwortet die Firewall-Frage allein. Ein sofortiges Connection refused bedeutet, dass das Paket den Server erreicht hat, dort aber nichts lauschte. Das ist bei einem passiven Port im Leerlauf das korrekte Ergebnis: Ihre Regel funktioniert. Wenn die Verbindung hängen bleibt, bis nc abbricht, wurde das Paket lautlos verworfen. Verantwortlich ist dann eine Firewall, entweder auf dem Server selbst oder im Panel Ihres Providers. Diese Unterscheidung entspricht der in bei SSH: abgelehnt oder Timeout beschriebenen und gilt für jeden Port.
Sollten Sie noch FTP einsetzen?
Für neue Projekte: nein. SFTP (SSH file transfer protocol) läuft über eine einzelne SSH-Verbindung auf Port 22. Es gibt keinen zweiten Kanal, keinen passiven Portbereich, keine NAT-Einstellung und keinen zusätzlichen Daemon, der abgesichert werden muss, weil OpenSSH diese Funktion bereits bereitstellt. sftp user@example.com funktioniert auf einem System, auf dem Sie überhaupt keinen Dateiübertragungsdienst konfiguriert haben. Wenn Sie jemandem ausschließlich Dateien bereitstellen möchten, verwendet sshd_config ForceCommand internal-sftp zusammen mit ChrootDirectory. Dieses Verzeichnis muss root gehören und darf für den Benutzer nicht beschreibbar sein. Andernfalls verweigert sshd die Sitzung und protokolliert eine Zeile mit bad ownership or modes for chroot directory.
FTP bleibt sinnvoll, wenn die Gegenstelle nicht geändert werden kann. Scanner und Multifunktionsdrucker werden mit Firmware ausgeliefert, die ausschließlich FTP unterstützt. Labor- und Industrieanlagen laufen häufig mit einem unveränderlichen Image, das niemand erneut zertifizieren wird. Geschäftspartner stellen einen FTPS-Upload bereit und fügen für einen einzelnen Lieferanten kein weiteres Protokoll hinzu. In all diesen Fällen besteht die gesamte Aufgabe aus dem passiven Portbereich und der passenden Firewall-Regel. Sie sollten dann FTPS statt einfachem FTP einsetzen. Das Zwei-Kanal-Design ist eine Entscheidung aus dem Jahr 1985, die heute in einer Umgebung eingesetzt wird, die ihre Entwickler nicht vorausgesehen haben. Dieses Thema wird in der Geschichte der Dateiübertragungsprotokolle behandelt.
FAQ
Warum meldet sich FTP an, aber die Verzeichnisauflistung hängt?
Für die Anmeldung wird nur die Steuerverbindung auf Port 21 verwendet. Diese Verbindung lässt Ihre Firewall zu. Für die Verzeichnisauflistung ist eine zweite TCP-Verbindung auf einem anderen Port erforderlich. Diese Verbindung wird blockiert. Legen Sie auf dem FTP-Server einen passiven Portbereich fest und öffnen Sie denselben Bereich in der Firewall. Danach wird die Auflistung abgeschlossen. Eine hängende Auflistung ist ein Problem des Datenkanals und niemals ein Passwortproblem.
Welche Ports muss ich für den passiven FTP-Modus öffnen?
Port 21 für den Steuerkanal sowie den Bereich, den Sie für passive Datenverbindungen konfiguriert haben. Es gibt keinen Standardbereich, weil Sie ihn selbst festlegen. Ein Bereich wie 30000 bis 30099 funktioniert. Die Größe muss zur maximalen Anzahl gleichzeitiger Übertragungen passen. Außerdem darf der Bereich nicht mit dem ausgehenden Portbereich des Kernels überlappen. Diesen Bereich können Sie mit sysctl net.ipv4.ip_local_port_range anzeigen. Wenn Ihr Anbieter eine Netzwerk-Firewall im Control Panel betreibt, öffnen Sie denselben Bereich auch dort.
Benötige ich nf_conntrack_ftp weiterhin?
Nein. Auf einem aktuellen Kernel können Sie sich nicht darauf verlassen. Die automatische Zuweisung von Helpern ist standardmäßig deaktiviert. Auf neueren Kernels wurde der Schalter net.netfilter.nf_conntrack_helper entfernt. Daher meldet sysctl, dass die Datei nicht existiert. Das Handbuch von ufw bezeichnet das bedingungslose Laden dieser Module als veraltet. firewalld ignoriert AutomaticHelpers vollständig. Ein Helper muss den Steuerkanal außerdem als Klartext lesen. Deshalb funktioniert er nicht mehr, sobald Sie FTPS aktivieren. Legen Sie stattdessen einen passiven Portbereich fest.
Warum meldet mein FTP-Client, dass die passive Antwort eine nicht routbare Adresse enthält?
Der Server hat auf PASV mit der Adresse geantwortet, die er auf seiner eigenen Schnittstelle sieht. Diese Adresse ist privat. Das passiert, wenn die Plattform eine öffentliche Adresse auf eine private Adresse abbildet. Legen Sie die öffentliche Adresse explizit fest: pasv_address in vsftpd, MasqueradeAddress in ProFTPD oder -P in Pure-FTPd. FileZilla umgeht das Problem, indem es die Adresse wiederverwendet, zu der bereits eine Verbindung besteht. Im Protokoll erscheint dann „Using server address instead“. Deshalb funktionieren manche Clients trotz dieser Fehlkonfiguration, während andere hängen.
Sollte ich FTPS oder SFTP verwenden?
Verwenden Sie SFTP für alles, was Sie an beiden Enden kontrollieren. Es nutzt eine Verbindung über SSH auf Port 22. Sie müssen keinen Datenkanal öffnen, und SSH läuft bereits. FTPS ist FTP über TLS. Das Zwei-Kanal-Design und alle damit verbundenen Firewall-Probleme bleiben daher bestehen. Wählen Sie FTPS, wenn die Gegenstelle kein anderes Protokoll unterstützt. Verwenden Sie kein unverschlüsseltes FTP über das Internet. Das Passwort wird dabei als lesbarer Klartext über das Netzwerk übertragen.