WebRTC Dateiübertragung: Browser-to-Browser Tutorial
Übertragen Sie Dateien directly between browsers using WebRTC. Data channels, signaling, und peer connection setup für real-time Datei sharing.
Ende-zu-Ende-Verschlüsselung ist kein Merkmal, das man nachträglich ergänzt — bei WebRTC ist sie technisch erzwungen und nicht abwählbar. WebRTC-Dateiübertragung bewegt Bytes direkt zwischen zwei Browsern über einen RTCDataChannel, ohne dass ein Server im Datenpfad sitzt, nachdem der initiale Handshake abgeschlossen ist. Was Sie brauchen: einen Signaling-Kanal (WebSocket oder ein kleines Relay) für den Austausch von SDP-Angeboten und ICE-Kandidaten, STUN-Server für NAT-Discovery, einen TURN-Fallback für symmetrische NATs und einen Datenkanal, der auf zuverlässige geordnete Zustellung konfiguriert ist.
Ist die Peer-Verbindung aufgebaut, senden Sie via channel.send() Chunks von 16–256 KB und beobachten die Bytes über eine DTLS-1.2-verschlüsselte SCTP-Verbindung mit annähernder Leitungsgeschwindigkeit fließen.
Wie WebRTC echte Peer-to-Peer-Verbindungen herstellt
WebRTC ist keine Magie — es ist ICE plus SDP plus DTLS plus SCTP, übereinander gestapelt. Der Sender erstellt eine RTCPeerConnection, öffnet einen Datenkanal, generiert ein SDP-Angebot und schickt es via Signaling-Kanal zum Empfänger. Der Empfänger antwortet. Beide Seiten tauschen dann ICE-Kandidaten (lokale IP, reflexive IP via STUN, Relay-IP via TURN) aus, bis sie einen funktionierenden Pfad finden. DTLS handshakt Ende-zu-Ende, SCTP läuft darüber für zuverlässiges Streaming, und die Bytes fließen.
Die Verschlüsselung ist verpflichtend und eingebaut — Sie können sie nicht deaktivieren. Das ist ein echter Sicherheitsgewinn: Anders als bei WebSockets müssen Sie nicht daran denken, alles in anwendungsseitige Kryptographie zu hüllen, um Netzwerk-Lauscher zu schützen. Für echte Ende-zu-Ende-Verschlüsselung gegen den eigenen Signaling-Server fügen Sie eine zweite Runde AES-256-GCM hinzu, weil ein bösartiger Signaling-Server sein eigenes DTLS-Zertifikat einschmuggeln könnte.
Signaling: Der Teil, den WebRTC nicht definiert
WebRTC lässt Signaling bewusst offen. Ein WebSocket auf Ihrem Server ist in Ordnung; ebenso ein geteilter Raumcode in einer Firebase-Realtime-DB oder sogar manuell eingefügte SDP-Strings. Entscheidend ist, dass beide Peers schließlich ein Angebot, eine Antwort und einen Strom von ICE-Kandidaten austauschen.
Minimaler Signaling-Server in Node:
const rooms = new Map();
wss.on('connection', (ws) => {
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'join') {
const room = rooms.get(msg.room) ?? new Set();
room.add(ws); rooms.set(msg.room, room);
} else {
for (const peer of rooms.get(msg.room) ?? []) {
if (peer !== ws) peer.send(raw);
}
}
});
});
Unter 20 Zeilen. Der Server sieht keine Datei-Bytes — nur SDP und ICE-Metadaten. Sie können das auf einem 5-Dollar-VPS oder Cloudflare Workers hosten und Hunderte gleichzeitiger Übertragungen bedienen.
Die Peer-Verbindung aufbauen
Erstellen Sie die Verbindung mit Googles öffentlichem STUN plus TURN-Fallback:
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'turn:turn.example.com:3478',
username: 'user', credential: 'pass' }
]
});
Etwa 15–25 % der Heimanschlüsse befinden sich hinter symmetrischen NATs, die STUN nicht durchdringen kann — TURN ist daher kein optionales Extra für Produktionsdienste. Betreiben Sie coturn auf einem VPS mit ausreichend Bandbreite für Relay-Traffic oder nutzen Sie einen verwalteten TURN-Anbieter wie Xirsys oder Twilio.
Öffnen Sie den Datenkanal auf der Angebotsseite vor dem Erstellen des Angebots:
const channel = pc.createDataChannel('file', {
ordered: true, maxRetransmits: null
});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: offer.sdp });
Geordnet + unbegrenzte Wiederholungen ergibt TCP-äquivalente Zuverlässigkeit. Ungeordneter Modus ist schneller, erfordert aber anwendungsseitige Neuzusammenstellung.
Die Datei in Chunks für den Kanal aufteilen
SCTP hat ein praktisches Limit von 256 KB pro Nachricht, und ältere Browser haben Probleme über 16 KB. Ein sicherer Standard sind 16-KB-Chunks, die via File.slice() aus der Datei gelesen werden:
const chunkSize = 16 * 1024;
let offset = 0;
channel.bufferedAmountLowThreshold = 1024 * 1024;
function sendNext() {
while (offset < file.size && channel.bufferedAmount < 4 * 1024 * 1024) {
const chunk = file.slice(offset, offset + chunkSize);
chunk.arrayBuffer().then((buf) => channel.send(buf));
offset += chunkSize;
}
}
channel.onbufferedamountlow = sendNext;
sendNext();
Das bufferedAmount-Wasserzeichen verhindert, dass Gigabytes in SCTPs Sendepuffer eingereiht werden und den Speicher erschöpfen. Wenn der Puffer unter 1 MB sinkt, auf 4 MB auffüllen. Das ergibt Durchsätze nahe 40–80 MB/s in lokalen Netzwerken und 5–20 MB/s bei typischen Heimanschlüssen.
Bytes empfangen und auf die Festplatte schreiben
Auf der Antwort-Seite auf den eingehenden Kanal lauschen:
pc.ondatachannel = ({ channel }) => {
const chunks = [];
let received = 0;
channel.onmessage = ({ data }) => {
chunks.push(data);
received += data.byteLength;
updateProgress(received);
if (received === expectedSize) finish(chunks);
};
};
Für Dateien über 500 MB nicht im RAM ansammeln. Nutzen Sie stattdessen die File System Access API zum direkten Streamen auf die Festplatte:
const handle = await window.showSaveFilePicker({ suggestedName: fileName });
const writable = await handle.createWritable();
channel.onmessage = async ({ data }) => writable.write(data);
Firefox und Safari unterstützen showSaveFilePicker noch nicht vollständig; nutzen Sie als Fallback Blob + URL.createObjectURL, begrenzt auf 2 GB.
Datei-Metadaten vor den Bytes senden
Der Empfänger muss Dateiname, Größe und MIME-Typ kennen, bevor der Byte-Strom beginnt. Verwenden Sie einen kleinen JSON-Handshake auf dem Datenkanal:
channel.send(JSON.stringify({
type: 'metadata', name: file.name,
size: file.size, mime: file.type, sha256: fileHash
}));
Dann in den Binärmodus wechseln. Der Empfänger unterscheidet anhand dessen, ob data ein String oder ArrayBuffer ist. Einen SHA-256 der Datei zur Integritätsverifizierung nach der Übertragung einschließen und optional einen Schlüssel-Fingerprint, wenn Sie anwendungsseitiges AES-GCM überlagern.
Mit Verbindungsfehlern umgehen
WebRTC-Datenkanäle scheitern auf drei Wegen: ICE schließt nie ab (NAT, Firewall), DTLS-Handshake schlägt fehl (Uhrabweichung, Zertifikatsprobleme) oder die Verbindung bricht während der Übertragung ab (Laptop-Schlafmodus, Netzwerkwechsel). Auf pc.oniceconnectionstatechange lauschen und bei 'failed' oder 'disconnected' reagieren.
Bei Fehler mitten in der Übertragung ICE neu starten ohne die gesamte Verbindung neu aufzubauen:
await pc.restartIce();
const offer = await pc.createOffer({ iceRestart: true });
// erneut via Signaling senden
Falls der Neustart fehlschlägt, auf wiederaufnehmbare Server-Uploads zurückfallen — eine hybride P2P-plus-Server-Architektur. Einige WebRTC-Transfer-Tools nutzen dieses Muster, weil es die 15 % der Netzwerkbedingungen abdeckt, wo reines P2P schlicht nicht funktioniert.
Ende-zu-Ende-Verschlüsselung gegen den eigenen Server ergänzen
WebRTCs eingebautes DTLS schützt gegen Netzwerk-Angreifer, nicht gegen einen bösartigen oder kompromittierten Signaling-Server. Für echte Ende-zu-Ende-Verschlüsselung lassen beide Peers ein ECDH-P-256-Schlüsselpaar erzeugen, tauschen öffentliche Schlüssel über einen kurzen Out-of-Band-Code (QR oder 6-Wort-Passphrase) aus, leiten ein gemeinsames Geheimnis via HKDF-SHA256 ab und verschlüsseln jede Datenkanalwachricht mit AES-256-GCM vor dem Senden. Selbst wenn der Signaling-Server DTLS-Zertifikate austauscht, kann er Ihre Dateien nicht lesen.
HexaTransfer nutzt eine hybride Architektur — clientseitig mit AES-256-GCM verschlüsselter Geheimtext wird serverseitig gespeichert, anstatt P2P zu verwenden — und tauscht Direktheit gegen offline-tolerante Freigabe. Testen Sie es unter https://hexatransfer.com — kostenlos, kein Konto, bis 10 GB.
Wo WebRTC gewinnt und verliert
WebRTC-Dateiübertragung glänzt, wenn beide Peers gleichzeitig online sind, wenn Privatsphäre vor dem eigenen Server wichtig ist, und wenn Dateien groß genug sind (100 MB+), dass Relay-Bandbreitekosten schmerzhaft wären. Es verliert, wenn Nutzer senden und weggehen wollen, wenn Empfänger den Link Stunden später öffnen oder wenn Empfänger sich in restriktiven Firmennetzwerken befinden, die STUN und TURN blockieren. Für ein universelles Übertragungswerkzeug deckt reines P2P etwa 60 % der Anwendungsfälle komfortabel ab. Die anderen 40 % benötigen einen server-gestützten Fallback — weshalb fast jedes „P2P-Dateiübertragungs"-Produkt irgendwo in der Architektur ein Relay hat.
Große Dateien sicher mit Ende-zu-Ende-Verschlüsselung senden
Übertragen Sie Dateien bis zu 10 GB kostenlos mit Ende-zu-Ende-Verschlüsselung. Kein Konto erforderlich. Ihre Dateien werden in Ihrem Browser verschlüsselt, bevor sie hochgeladen werden — niemand sonst kann sie lesen.
Datei senden