Transferify
Zurück zum Blog

Wie Transferify eine Datei in einem eigenen Container umwandelt

Oft brauchst du eine Datei in einem anderen Format, bevor du sie sendest: ein HEIC-Foto als JPG, ein MOV als MP4, ein DOCX als PDF. Transferify erledigt diesen Schritt jetzt für dich, auf der Umwandlungsseite und als Modus des Sendebereichs, von dem aus du die umgewandelten Dateien weitersendest.

Der Konverter ist Transmute, ein Open-Source-Programm, das wir selbst betreiben. Wir haben es nicht geschrieben, und wir können den Dateien, die Leute ihm geben, nicht trauen. Dieser Beitrag erklärt, wie wir es betreiben, damit jede Umwandlung ihre eigene Datei sieht und sonst nichts, und was die Umwandlung ändert: Während eine Datei umgewandelt wird, ist sie auf unseren Servern lesbar.

Der Weg einer Umwandlung. Der Browser bittet unsere API, eine Umwandlung anzulegen, und die API prüft die Art der Datei, ihre Größe, die Anzahl im Monat und das Formatpaar. Der Browser lädt die lesbare Datei in einen Staging-Bereich im EU-Speicher hoch. Die API bittet den Worker, den Job zu starten, und der Worker startet einen neuen Container, benannt nach der ID der Umwandlung. Der Worker streamt die Datei aus dem Staging-Bereich in den Container und das Ergebnis zurück; der Container hält keine Zugangsdaten für den Speicher. Der Browser liest das Ergebnis und verschlüsselt es, bevor er es als normalen Transfer sendet.Der Weg einer Umwandlung. Der Browser bittet unsere API, eine Umwandlung anzulegen, und die API prüft die Art der Datei, ihre Größe, die Anzahl im Monat und das Formatpaar. Der Browser lädt die lesbare Datei in einen Staging-Bereich im EU-Speicher hoch. Die API bittet den Worker, den Job zu starten, und der Worker startet einen neuen Container, benannt nach der ID der Umwandlung. Der Worker streamt die Datei aus dem Staging-Bereich in den Container und das Ergebnis zurück; der Container hält keine Zugangsdaten für den Speicher. Der Browser liest das Ergebnis und verschlüsselt es, bevor er es als normalen Transfer sendet.
Eine Umwandlung. Kleine Nachrichten gehen über unsere API; die Datei geht direkt in den Staging-Speicher, und nur der für diesen Job gestartete Container wandelt sie um.

Transmute, von uns betrieben

Wir betreiben das veröffentlichte Image von Transmute, Version 2.1.1, fest per Digest angegeben. Transmute ist jung, deshalb ändert sich die festgelegte Version nur mit Absicht, und nach jeder Änderung läuft in unserer Entwicklungsumgebung ein Ende-zu-Ende-Test gegen das echte Image.

Drei Einstellungen sind wichtiger als der Rest:

  • Transmute ist nie aus dem Internet erreichbar.
  • Seine Einstellung ALLOW_UNAUTHENTICATED bleibt false.
  • Nichts ruft den Endpunkt von Transmute auf, der eine Datei von einer URL herunterlädt. Die einzige Datei, die ein Job sieht, ist die für ihn hochgeladene.

Ein Container pro Umwandlung

Jede Umwandlung läuft in ihrem eigenen Cloudflare Container. Ein Worker startet ihn über ein Durable Object und benennt ihn nach der ID der Umwandlung. Der Container wird nur abgerechnet, solange er läuft, und er stoppt, wenn der Job endet.

Ein Container pro Job entfernt alles, was sich Jobs sonst teilen würden. Es gibt keinen gemeinsamen Konverter, keine gemeinsame Festplatte und keine Warteschlange vor einer einzigen Maschine, und die Datei eines Kontos liegt nie neben der eines anderen. Die Festplatte des Containers endet mit dem Container, also überdauert nichts, was ein Job auf diese Festplatte geschrieben hat, den Job.

Die Container laufen in dem Cloudflare-Konto, das unseren Datei-Bucket hält, weil die Dateien schon dort sind. Die Datei-Buckets liegen in der eu-Jurisdiktion von R2, und die Container haben die Platzierungsvorgabe jurisdiction = "eu", also bleibt die lesbare Datei in Europa, während sie umgewandelt wird.

Nur der Worker erreicht den Container

Ein Cloudflare Container hat keine eigene Adresse. Der einzige Weg zu ihm führt über den Worker, der ihn gestartet hat.

Das macht ein Verhalten von Transmute harmlos. Nach einem Start gibt Transmute das Admin-Konto seinem ersten Aufrufer. Bei einem Konverter mit Adresse gehörte er dem, der nach einem Neustart als Erster aufruft. Hier startet jeder Job einen frischen Container, und der Worker ist sein erster und einziger Aufrufer. Bei jedem Start legt der Worker den Dienstbenutzer von Transmute an und fordert bei ihm ein Token an, mit Secrets, die unser Terraform setzt.

Der Worker selbst hat einen öffentlichen Hostnamen, wie jede Worker-Route. Unsere API ruft ihn über HTTPS mit einem Dienst-Token auf, für genau vier Dinge: einen Job anlegen, seinen Status lesen, ihn abbrechen und ihn löschen. Das sind kleine JSON-Nachrichten; die API sieht nie die Bytes einer Datei. Eine Rate-Limiting-Regel auf der Route des Workers ist der zweite Schutz.

Unsere API entscheidet, bevor sich ein Byte bewegt

Der Browser und unsere API sprechen über eine Umwandlung per Connect RPC. Wenn der Browser eine Umwandlung anlegt, prüft die API vier Dinge gegen deinen Plan: die Art der Datei, ihre Größe, die Anzahl im Monat und das Formatpaar. Eine Umwandlung über der Anzahl oder Größe deines Plans wird mit einem Grund wie FILE_CONVERSION_LIMIT_REACHED abgelehnt, und die Seite zeigt die Pläne, die sie erlauben würden. Zu diesem Zeitpunkt ist noch nichts hochgeladen, und eine Datei, die sich nicht umwandeln lässt, kannst du trotzdem so senden, wie sie ist.

Der Worker und der Container setzen nichts zu Plänen, Anzahlen oder Größen durch. Sie führen aus, was die API erlaubt hat. Die Regeln liegen dort, wo der Plan und die Zählung schon sind, so prüft und ändert sie ein einziger Ort.

  • Die Art einer Datei ist die Familie ihres Quellformats: Video, Audio, Bild oder Dokument. Ein MP4, das in ein MP3 umgewandelt wird, ist eine Video-Umwandlung, weil die Quelle als Video dekodiert wird.
  • Die Zählung reserviert eine Umwandlung, wenn sie startet, und zählt sie, wenn sie gelingt; eine fehlgeschlagene oder abgebrochene zählt nicht. Eine neue Umwandlung wird gegen die fertigen plus die noch laufenden geprüft, also können zwei offene Tabs nicht beide die letzte des Monats nehmen.
  • Die Last hat ebenfalls eine Obergrenze: Die API begrenzt, wie viele Jobs gleichzeitig laufen, pro Konto und insgesamt, und der Rest wartet.

Auch die Liste der Formate kommt von Transmute, nie aus einer Liste, die wir pflegen. Transmute meldet seine Eingaben und Ausgaben als zwei Mengen, nicht als Paare, und erkennt den Typ einer Datei an ihrer Endung. Deshalb lädt unsere API einmal eine winzige Datei für jede Eingabe-Endung hoch und speichert die Ziele zwischen, die Transmute dafür anbietet. Das letzte Wort hat trotzdem die Antwort von Transmute für deine echte Datei; eine Wahl, die es ablehnt, schlägt mit einer klaren Meldung fehl und zählt nicht.

Die Datei nimmt einen anderen Weg

Datei-Bytes gehen nie über RPC, weil das Gateway vor unserer API eine Nachricht auf 1 MiB begrenzt. Der Browser lädt das Original mit vorsignierten Multipart-URLs hoch, mit demselben Speicher-Code wie beim Upload eines gehosteten Transfers, an einen Staging-Schlüssel in unserem Datei-Bucket: 1-days/file-conversions/<account>/<conversion id>/source. R2 legt es verschlüsselt ab.

Der Worker streamt die Quelle aus seinem R2-Binding in Transmute und streamt die umgewandelte Datei dann zurück in den Bucket. Die Bytes gehen nie durch unsere API, und der Container selbst hält keine Zugangsdaten für den Speicher.

Wann jede Kopie gelöscht wird

WasWann es gelöscht wird
Das Original, im Staging-BereichVon unserer API, wenn der Job endet
Die umgewandelte Datei, im Staging-BereichVon unserer API, 24 Stunden nach ihrer Erstellung
Ein Upload, den der Browser nie abgeschlossen hatVon unserer API innerhalb von 24 Stunden abgebrochen
Alles auf der Festplatte des ContainersMit dem Container, wenn der Job endet
Alles, was unter dem Staging-Präfix übrig istDurch die Ein-Tages-Regel des Buckets, als zweite Linie

Die eigenen Löschungen der API halten das Versprechen, dass eine umgewandelte Datei nach 24 Stunden weg ist. Die Regel des Buckets ist für den Fall da, dass eine davon nicht stattfindet. Ohne den Abbruch durch die API würde der Bucket allein die Teile eines unfertigen Uploads 7 Tage lang behalten.

Warum die umgewandelte Datei trotzdem in deinem Browser verschlüsselt wird

Heute wird jede gehostete Datei in deinem Browser mit AES-256-GCM verschlüsselt, bevor eines ihrer Bytes gesendet wird, mit einem Schlüssel, der auf deinem Gerät entsteht, wie in wie Transferify Dateien im Browser verschlüsselt erklärt. Unser Dienst entschlüsselt keine Dateiinhalte.

Ein Konverter kann nicht mit einer verschlüsselten Datei arbeiten, also war die Frage, wo die umgewandelte Datei zu einem verschlüsselten Transfer wird. Es gab zwei Wege.

Über den Browser, so haben wir es gebaut. Der Browser lädt das lesbare Original hoch, der Container wandelt es um, und der Browser liest das Ergebnis abschnittsweise aus dem Speicher zurück und gibt es direkt in den bestehenden verschlüsselten Upload, sodass nichts im Browser gespeichert wird. Die umgewandelte Datei wird dann wie jede andere Datei gesendet, also funktionieren Transfers genau wie vorher. Der Preis ist der Datenverkehr: Eine große Datei reist dreimal, hoch, runter und wieder hoch.

Auf dem Server, das haben wir in dieser Version weggelassen. Unsere API würde die umgewandelte Datei selbst verschlüsseln und in den Transfer legen, was eine Reise spart. Aber dann hielte die API gleichzeitig den Schlüssel einer Datei und ihren lesbaren Inhalt, was sie heute nie tut. Sie bräuchte außerdem eine zweite Kopie des Verschlüsselungscodes des Browsers, in Java.

Der Kompromiss, offen gesagt

Um eine Datei umzuwandeln, müssen wir sie lesen können. Bis der Job endet, ist das Original auf unseren Servern lesbar: im Staging-Bereich, wo der Speicher es verschlüsselt ablegt, und im Container, der es umwandelt. Die umgewandelte Datei bleibt bis zu 24 Stunden im Staging-Bereich, damit du sie herunterladen oder senden kannst, und wird dann gelöscht. Das gilt, egal wie du die Datei danach sendest: Eine Datei, die du umwandelst und dann Peer-to-Peer sendest, ist trotzdem zuerst durch unseren Konverter gegangen.

Deshalb wird eine umgewandelte Datei auch nie als Zero-Knowledge gesendet. Im Zero-Knowledge-Modus erhalten wir den Schlüssel nie und halten nie etwas, das wir lesen können, und eine umgewandelte Datei war auf unseren Servern lesbar. Solange eine umgewandelte Datei in der Liste ist, ist die Zero-Knowledge-Option aus, und sie kommt zurück, wenn die Datei entfernt wird.

Wenn eine Datei den Konverter angreift

Konverter wie LibreOffice und ffmpeg sind ein bekanntes Ziel für präparierte Dateien, deshalb planen wir für eine Datei, die im Konverter ausbricht.

Eine solche Datei sieht nur ihren eigenen Job: ihren eigenen Container, ihre eigene Quelldatei und den Worker, der ihn gestartet hat. Sie käme an keine Datei eines anderen Kontos, nicht an unsere Datenbank, unsere API, irgendeinen Schlüssel oder einen gespeicherten Transfer. Der Container startet mit abgeschaltetem Internetzugang und hält kein Speicher-Token, also hat er keinen Weg hinaus und nichts, was er erreichen könnte. Der Container ist neu für diesen Job und endet mit ihm, also liegt keine Datei eines früheren Jobs auf seiner Festplatte, und kein späterer Job läuft in ihm. Er hat keine Adresse, also kann ihn nichts im Internet aufrufen.

Was der Container einer Umwandlung erreichen kann. In ihm sind Transmute sowie Quelle und Ergebnis dieses Jobs. Sein einziger Aufrufer ist der Worker, der ihn gestartet hat. Außer Reichweite sind die Container anderer Umwandlungen, die Dateien anderer Konten, unsere Datenbank, unsere API, Verschlüsselungsschlüssel und gespeicherte Transfers. Das Internet kann den Container nicht aufrufen, weil er keine Adresse hat.Was der Container einer Umwandlung erreichen kann. In ihm sind Transmute sowie Quelle und Ergebnis dieses Jobs. Sein einziger Aufrufer ist der Worker, der ihn gestartet hat. Außer Reichweite sind die Container anderer Umwandlungen, die Dateien anderer Konten, unsere Datenbank, unsere API, Verschlüsselungsschlüssel und gespeicherte Transfers. Das Internet kann den Container nicht aufrufen, weil er keine Adresse hat.
Eine Datei, die aus dem Konverter ausbricht, findet einen Job: ihren eigenen Container, ihre eigene Datei und den Worker. Alles andere ist außer Reichweite.

Video läuft auf der CPU

Transmute kodiert Video mit libx264 neu, auf der CPU. Es hat keinen Weg über die GPU, und Cloudflare Containers bieten keinen GPU-Typ. Video ist also der langsame Fall, und weil ein Container für seine Laufzeit abgerechnet wird, ist ein langsamer Job auch ein teurer.

Jeder Video-Job darf bis zu zwei Stunden laufen. Transmute kann einen laufenden Job nicht stoppen, aber der Worker kann den Container beenden. Ein Job, der das Limit überschreitet, wird beendet, als zu lang gemeldet, nicht auf deinen Plan angerechnet und nicht neu gestartet. Unsere API startet einen Job nur, wenn seine Art und Größe bei den gemessenen Umwandlungsraten in das Zeitlimit passen.

So sehen diese Raten in unserer Entwicklungsumgebung aus, mit generierten Testdateien. Ein 3 MB großes Foto, ein 10-seitiges PDF, das zu Bildern wurde, und ein 50 MB großes WAV, das zu MP3 wurde, brauchten jeweils etwa eine halbe Minute, und ein 1 MB großes Word-Dokument brauchte 48 Sekunden, um ein PDF zu werden. Etwa 12 bis 15 Sekunden jedes Jobs sind der Start des Containers, bei einer kleinen Datei ist der Start also der größte Teil der Wartezeit. Die meiste Zeit kostet Video: 1080p-Video mit etwa 17 Mbit/s brauchte 2 Minuten 43 Sekunden für 100 MB, 23 Minuten für 1 GB und 91 Minuten für 4 GB.

Cloudflare verspricht auch nicht, dass ein Container eine bestimmte Zeit läuft. Stoppt ein Container früher, schlägt der Job mit diesem Grund fehl, er zählt nicht, und du wandelst noch einmal um.

Probier es aus

Wandle eine Datei auf der Umwandlungsseite um und sende sie dann. Dein Browser verschlüsselt die umgewandelte Datei wie jeden anderen Transfer.

Häufige Fragen

Ist meine Datei während der Umwandlung auf euren Servern lesbar?

Ja. Ein Konverter braucht die lesbare Datei. Das Original kommt in einen Staging-Bereich in unserem EU-Speicher, der es verschlüsselt ablegt, und unsere API löscht es, wenn die Umwandlung endet. Die umgewandelte Datei bleibt dort 24 Stunden, damit du sie herunterladen oder senden kannst, und wird dann gelöscht. Wenn du sie sendest, verschlüsselt dein Browser sie wie jede andere Datei.

Kann ich eine Datei in einem Zero-Knowledge-Transfer umwandeln?

Umwandeln kannst du sie, aber eine umgewandelte Datei wird nie als Zero-Knowledge gesendet. Im Zero-Knowledge-Modus erhalten wir den Schlüssel nie, also halten wir nie etwas, das wir lesen können, und eine umgewandelte Datei war auf unseren Servern lesbar. Solange eine umgewandelte Datei in der Liste ist, ist die Zero-Knowledge-Option aus.

Kann meine Datei neben der Datei von jemand anderem landen?

Nein. Jede Umwandlung läuft in ihrem eigenen Container, benannt nach der ID der Umwandlung, für diesen Job gestartet und beendet, wenn der Job endet. Es gibt keinen gemeinsamen Konverter und keine gemeinsame Festplatte.

Entscheidet der Konverter, was mein Plan erlaubt?

Nein. Unsere API prüft die Art der Datei, ihre Größe, die Anzahl im Monat und das Formatpaar, bevor dein Browser irgendetwas hochlädt. Der Worker und der Container führen nur aus, was die API erlaubt hat.

Warum schlägt ein langes Video fehl, statt später fertig zu werden?

Video wird auf der CPU neu kodiert, und jeder Video-Job darf bis zu zwei Stunden laufen. Transmute kann einen laufenden Job nicht stoppen, also beendet der Worker, der den Container gestartet hat, diesen Container. Die Umwandlung wird als zu lang gemeldet, zählt nicht für deinen Plan und wird nicht neu gestartet.

Ähnliche Seiten

Nach oben