FTP - Der unsterbliche Leiche

Als mir im Jahr 2000 mein “erster” fester Internetprovider eine Warnung wegen der Verletzung der Nutzungsbestimmungen zusandte, war der Grund ein FTP Server.

Denn im Vertrag stand tatsächlich, dass der Zugang nur für TCP Clientdienste bestimmt war und das Hochfahren eines beliebigen Servers wie HTTP oder FTP war zwar technisch möglich, doch der Provider überwachte die eingehenden Transmissionen und ermahnte seine Kunden daraufhin.

Das war dann eigentlich schon der erste und letzte Moment, wo ich einen FTP Server zu Hause in Betrieb hatte …


Anders sah es allerdings im Internet aus. Denn der Wechsel von FTP zu HTTP und anderen Dateiserver-Diensten wurde erst langsam zwischen 2000 bis 2010 vollzogen. Und auch heute ist dieses schreckliche Uraltprotokoll nicht tot zu kriegen.

Das ursprüngliche FTP ist deshalb so unglaublich umständlich, weil in der Zeit seiner Entwicklung zwei Kriterien galten:

  1. Jeder vertraut jedem blind
  2. Jeder hängt direkt mit einer fixen IP am Internet

Und deshalb kamen die Macher auf die Idee, dass neue eingehende Verbindungen des TCP Server-Sockets nur für Kontrollnachrichten zuständig sind. Man kann sich also mit Benutzernamen und Passwort anmelden, sich Verzeichnisinhalte ansehen und Downloads und Uploads vorbereiten.

Doch für den eigentlich Download bzw. Upload wird eine weitere Verbindungen auf einem anderen Port aufgebaut und darüber fließen die Bits des Inhalts.

Das schlimmste daran ist, dass neben dem Problem des Betriebs von mehreren Ports auch noch das Server-Client Prinzip umgedreht wird. Denn für den Verbindungsaufbau ist der “Konsument” der Client und der “Bereitsteller” der Server, so wie man es erwartet.
Doch beim Download muss der “Konsument” einen dynamischen TCP-Server hochfahren und der “Bereitsteller” verbindet sich als Client zu diesem um ihm seine Daten zu senden.

Das ist ein Alptraum für Administratoren, die Firewalls warten müssen, denn statt einem einzigen Serverport müssen nun ganze Port-Bereiche freigegeben werden, die zufällig mal benutzt werden und dann wieder nicht.
Und nachdem der Client ebenso als Server funktioniert, muss auch seine Firewall das Öffnen eines Portbereiches unterstützen.

Diesem zweiten Punkt wurde mit Passiven FTP entgegengearbeitet, bei dem nur der FTP-Server mehrere TCP-Server betreibt und der Client auch immer nur Client-Verbindungen initiiert anstatt selbst zum TCP-Server zu werden.

Nicht zu vergessen sei, dass der FTP-Server immer seine öffentliche Internetadresse kennen muss, denn im Protokoll muss der Gegenseite mitgeteilt werden, auf welchen anderen Port auf welcher IP sie sich für Up- und Downloads verbinden soll.
Und ist die interne IP des Servers nicht gleich der externen, dann muss dies von Hand im Server konfiguriert sein. Besonders dumm ist, wenn sich die öffentliche IP (z.B. durch Einwahlnetze) ändert.

Wie auch immer, viele Daten wie Treiber oder Betriebssystem-Images liegen auch heute immer noch auf FTP Servern. Und auch bei IT-Lösungen für Kunden, wo man Daten austauschen muss, wird schnell ein FTP-Server bereitgestellt, weil dieser “schnell” aufgesetzt ist und Clients weit verbreitet sind.
Natürlich geht das schnell, denn wegen fehlender Sicherheitsfunktionen reicht es einfach einen Account anzulegen und ihm ein Verzeichnis zuzuordnen. Dann schaltet man noch die Firewall für den FTP-Port 21 und die Übertragungs-Port-Range ab (z.B.: Ports 13000 bis 14000, tausend gleichzeitige Verbindungen sind mehr als ausreichend für kleine Projekte), und man ist fertig.

In der Programmierung nutzte ich ganz analog zu HTTP immer WinINET unter Windows und die libCURL unter Linux bzw. POSIX Systemen um FTP Clients zu implementieren.

WinINET

WinINET stellt uns neben seinen generischen Funktionen für alle Protokolle einige FTP-spezifische zur Verfügung, wie z.B.: FtpFindFirstFile um Dateien aufzulisten oder FtpCreateDirectory um Unterverzeichnisse anzulegen. Ansonsten funktioniert der Nutzung genau so wie für HTTP.

libCURL

Bei der libCURL ist das leider nicht so, dass es für Verzeichnisoperationen eigene APIs gibt, womit nur Up- und Downloads von im Vorhinein bekannten Pfaden “leicht” zu implementieren sind. Das Lesen eines Verzeichnisses führt zu einem Text-Stream, der geparst werden muss und das ist kein Zuckerschlecken, da jeder FTP-Server seinen eigenen Ausgabestandard wählt. Sie sind zwar ähnlich zueinander, aber eben nicht identisch.

CURL lässt uns aber native Kommandos für das Protokoll injizieren und so können wir das Kommando MLST für standardisierte Verzeichniseinträge nutzen, oder MKD um Unterverzeichnisse anzulegen.

Aber Vorsicht! Ich musste einst lange mit einer Implementierung kämpfen, da es FTP-Server gibt, die keine absoluten Pfade verkraften. Die libCURL wechselt daher immer (im Hintergrund) in das angenommene Zielverzeichnis und dort muss dann der relative Pfad und nicht der absolute genutzt werden, weil sich der Server ansonsten den übergebenen absoluten Pfad an seinen aktuelles “Working-Directory” anhängt und das Ergebnis dann ein ganz anderes (nicht existierendes= Verzeichnis ist.

Fazit

FTP ist wegen seiner Unsicherheit und Server-Client-Port-Murxerei und dann noch wegen seiner unterschiedlichen Implementierungen ein einziger Graus. Wer Dateien sicher übertragen will, sollte SFTP von SSH benutzen, oder per VPN einen sicheren Tunnel nutzen um dann per SMB fortzufahren.

Eigentlich könnte HTTP das alte FTP vollkommen ablösen, denn mit der WebDAV Erweiterung existiert für HTTP ein Standard um ebenso Verzeichnisse maschinell auszulesen und somit ein Dateisystem abzubilden (was im klassischen HTTP leider fehlt).

Doch … wie wir wissen, bleiben solche Altlasten auf unbestimmte Zeit aktiv, und so werde ich wohl noch meine letzten Atemzüge vor Programmen wie FileZilla verbringen, über welche ich meinen letzten Blog-Post per FTP zum Webserver übertrage.