Start · Sprachen · JavaScript · Referenz · RTCDtlsTransport

RTCDtlsTransport

Schnittstelle

Stellt Informationen über den DTLS-Transport bereit, über den eine <code>RTCPeerConnection</code> RTP-/RTCP-Pakete und SCTP-Daten verschlüsselt sendet und empfängt.

seit JavaScript Baseline 2023: Chrome 72+, Edge 79+, Firefox 122+, Kategorie: webapi

Signatur

interface RTCDtlsTransport extends EventTarget

Beschreibung

Das Interface RTCDtlsTransport steht für die DTLS-Schicht (Datagram Transport Layer Security) einer WebRTC-Verbindung. Über diesen Transport laufen die verschlüsselten RTP- und RTCP-Pakete der RTCRtpSender- und RTCRtpReceiver-Objekte sowie die SCTP-Pakete von RTCDataChannels. Man erzeugt es nie selbst. Der Browser legt es bei der Aushandlung an, und man erreicht es über sender.transport, receiver.transport oder pc.sctp.transport.

Die wichtigsten Mitglieder sind:

  • state: der aktuelle DTLS-Zustand, also "new", "connecting", "connected", "closed" oder "failed".
  • iceTransport: das darunterliegende RTCIceTransport-Objekt mit Informationen über die ICE-Kandidatenpaare.
  • getRemoteCertificates(): gibt ein Array von ArrayBuffers mit den DER-kodierten Zertifikaten der Gegenseite zurück.
  • Events: statechange (auch als onstatechange) und error (auch als onerror, liefert ein RTCErrorEvent).

In der Praxis nutzt man RTCDtlsTransport für die Diagnose. Damit lässt sich genauer als mit connectionState feststellen, ob die Verschlüsselung tatsächlich steht, ob ein DTLS-Handshake fehlgeschlagen ist oder welches Zertifikat die Gegenseite vorgelegt hat. Mit dem Standard-Bündelungsverhalten (bundlePolicy: "max-bundle") teilen sich meist alle Sender, Empfänger und der SCTP-Transport ein einziges RTCDtlsTransport-Objekt.

Rückgabewert

Typ
RTCDtlsTransport
Beschreibung
Ein vom Browser verwaltetes Objekt. Man erhält es über RTCRtpSender.transport, RTCRtpReceiver.transport oder RTCSctpTransport.transport. Vor der Aushandlung ist der Wert null.

Beispiele

DTLS-Transport eines Senders ermitteln und Zustand überwachen

const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const sender = pc.addTrack(stream.getAudioTracks()[0], stream);

// Die Transport-Objekte gibt es erst nach setLocalDescription
await pc.setLocalDescription(await pc.createOffer());

const dtls = sender.transport;
console.log('DTLS-Zustand:', dtls.state);

dtls.addEventListener('statechange', () => {
  console.log('DTLS-Zustand geändert:', dtls.state);
  if (dtls.state === 'failed') {
    console.error('DTLS-Handshake fehlgeschlagen');
  }
});
DTLS-Zustand: new

Fehler über die on-Property abfangen

const handleDtls = (dtls) => {
  dtls.onerror = (event) => {
    const err = event.error; // RTCError
    console.error('DTLS-Fehler:', err.errorDetail, err.message);
  };
  dtls.onstatechange = () => console.log('Zustand:', dtls.state);
};

// Beispielaufruf, sobald die Verbindung ausgehandelt ist
const [sender] = pc.getSenders();
if (sender?.transport) handleDtls(sender.transport);
Zustand: connecting Zustand: connected

Zertifikat der Gegenseite als SHA-256-Fingerprint ausgeben

const fingerprint = async (buffer) => {
  const hash = await crypto.subtle.digest('SHA-256', buffer);
  return [...new Uint8Array(hash)]
    .map((b) => b.toString(16).padStart(2, '0').toUpperCase())
    .join(':');
};

const dtls = pc.getReceivers()[0].transport;
if (dtls.state === 'connected') {
  const certs = dtls.getRemoteCertificates();
  for (const cert of certs) {
    console.log('Remote-Fingerprint:', await fingerprint(cert));
  }
}
Remote-Fingerprint: 3A:9F:…:C2

Vom DTLS- zum ICE-Transport navigieren

const dtls = pc.sctp?.transport ?? pc.getSenders()[0]?.transport;
const ice = dtls?.iceTransport;

ice?.addEventListener('selectedcandidatepairchange', () => {
  const pair = ice.getSelectedCandidatePair();
  console.log('Lokal:', pair.local.type, '→ Remote:', pair.remote.type);
});
Lokal: host → Remote: srflx

// Wichtig · Fallstricke

  • Erst nach der Aushandlung verfügbar: sender.transport und receiver.transport sind null, solange setLocalDescription() oder setRemoteDescription() noch nicht aufgerufen wurde. Vor dem Zugriff also immer auf null prüfen, z. B. mit optionaler Verkettung (?.).
  • Geteiltes Objekt: Beim Bundling teilen sich mehrere Sender und Empfänger ein einziges RTCDtlsTransport-Objekt. Wer an jedem Sender einen Listener anmeldet, registriert ihn womöglich mehrfach am selben Objekt.
  • getRemoteCertificates() liefert erst im Zustand "connected" Daten, vorher ist das Array leer. Die Zertifikate sind DER-kodiert. Zum Vergleich mit dem SDP-Fingerprint muss man selbst hashen, z. B. mit crypto.subtle.digest.
  • Ein beendeter Transport bleibt beendet: "closed" und "failed" sind Endzustände. Um die Verbindung wiederherzustellen, braucht es einen ICE-Neustart (pc.restartIce()) oder eine neue RTCPeerConnection.
  • Browser-Kompatibilität: Chrome und Edge unterstützen das Interface ab Version 72 bzw. 79, Safari ab 15.4 und Firefox erst ab Version 122. In älteren Firefox-Versionen fehlen sender.transport und receiver.transport, dort bleibt als Ausweichlösung nur pc.connectionState. Eine Funktionserkennung ist mit 'RTCDtlsTransport' in window möglich.
  • Sicherheit: DTLS-SRTP ist in WebRTC Pflicht, unverschlüsselte Medien sind nicht möglich. Die Echtheit der Gegenseite hängt aber davon ab, dass das SDP mit dem Fingerprint über einen vertrauenswürdigen Signalisierungskanal (HTTPS/WSS) übertragen wird.