Moin,
FTP unterscheidet sich ein wenig von den meisten Protokollen mit denen man sonst so zu tun hat. Es ist aufgeteilt in einen Steuerkanal (i.d.R. TCP 21) und einen Datenkanal (kann TCP 20 sein, kann aber auch ein beliebiger highport sein).
Der Steuerkanal macht z.B. login oder changedir. Dazu baut der Client von einem TCP highport eine Verbindung zum FTP-Server TCP 21 auf, dieser antwortet dann auch auf diesem Wege. Das ist das übliche für Paketfilter - auf der Clientseite ausgehend erlaubt, vermutlich noch NAT und auf Serverseite in&out erlaubt.
Nun ist die Frage, hat Dein Client aktives oder passives FTP angefordert? Aktiv läuft so, dass der Server den Client über den Steuerkanal mitteilt, dass der Client an einem beliebigen highport _lauschen_ und diesen dem Server mitteilen soll. Datentransfer würde dann so laufen, dass der Server von TCP 20 den Client am vereinbarten highport kontaktiert. Server out sicher erlaubt aber Client in (und dann ggf noch das NAT)? Das versucht das connection tracking modul zu lösen, indem es auf dem Steuerkanal mithört was vereinbart wird und dann dynamisch Regeln nachbaut. Wann funktioniert das nicht? Richtig, wenn TLS im Einsatz ist.
Das war wohl auch den Protokolldesignern aufgefallen und man entwarf noch den passive-mode. Hier teilt der Server dem Client mit, auf welchem highport (die Range kannst Du i.d.R am FTP-Server definieren) der Server auf Clientanfragen lauscht. Hier müssen am Server also noch diese möglichen highports in offen sein (auch das kann conntrack wohl übernehmen) und auf Clientseite das entsprechende out (was man aber i.d.R. zu hat, also auch hier conntrack).
Login kein Problem, aber keine Dateiauflistung und Übertragung.
Der Steruerkanal läuft bei Dir - Du sagtest ja: login geht.
root@ns:~# lsmod | grep conn nf_conntrack_ftp 24576 0 nf_conntrack 176128 7
Auf connection tracking bist Du auf Serverseite auch vorbereitet, die nötigen Module sind geladen.
-A INPUT -m state --state RELATED,ESTABLISHED -m comment --comment "Connection tracking" -j ACCEPT -A INPUT -d 91.216.245.10/32 -i isp0 -p tcp -m multiport --dports 20,21 -m comment --comment Rico -j ACCEPT
Die eingehenden Server-Regeln für die bekannten Ports hast Du und alles Verbindungszugehörige (established, related) auch.
Leider bist Du schuldig geblieben, wie das ausgehend so aussieht. Ob Du den FTP auch wirklich an 21 gebunden hast und ob die IF stimmen, musst du allein prüfen. Vom Client wissen wir auch nix.
Wie Du meiner Beschreibung nun aber hoffentlich entnehmen kannst, ist auch der Paketfilter auf Clientseite entscheidend - hier könntest Du mit z.B. 'tcpdump' mal einem Verbindungsaufbau und dann vor allem versuchtem PUT/GET/DIR|LS auf beiden Kisten zuschauen, um herauszufinden, welche Seite hier Pakete verwirft/blockiert.
Ferner ist mir so, als müsse man bei neueren Kernen (ab oder größer 4.7?) das connection tracking jetzt erst "initialisieren". In 'nftables'/'nft' läuft das z.B. so
nft add ct helper inet $TABLE ftp { type "ftp" protocol tcp; } nft add rule inet $TABLE INPUT ct helper ftp accept #auch für OUTPUT und FORWARD ggf.
mit 'iptables' sollte das wohl so aussehen
iptables -A $CHAIN -m conntrack --ctstate RELATED -m helper --helper ftp -d $DESTINATION -p tcp --dport 1024: -j ACCEPT #statt der 1024: auch gern die Portrange des FTP-Servers; gilt dann für passives FTP
conclusion - SSL am FTP-Client aus - active und passive probieren - vielleicht geht ein Mode schon - kernel und helper initialisierung prüfen - mit 'tcpdump' debuggen
Mit freundlichen Grüßen / Kind regards Ronny Seffner