Skip to main content

QMux over WebSocket
draft-lcurley-qmux-websocket-00

Document Type Active Internet-Draft (individual)
Author Luke Curley
Last updated 2026-08-03
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-lcurley-qmux-websocket-00
moq                                                            L. Curley
Internet-Draft                                             3 August 2026
Intended status: Informational                                          
Expires: 4 February 2027

                          QMux over WebSocket
                    draft-lcurley-qmux-websocket-00

Abstract

   QMux [qmux] is a polyfill that runs QUIC applications over an
   ordered, reliable byte-stream transport such as TCP with TLS.  This
   document defines a binding for QMux over WebSocket [RFC6455].  A
   WebSocket binding lets QUIC applications reach environments where UDP
   is blocked and where only an HTTP/WebSocket stack is available,
   including web browsers that lack WebTransport.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 4 February 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Curley                   Expires 4 February 2027                [Page 1]
Internet-Draft                   qmux-ws                     August 2026

Table of Contents

   1.  Conventions and Definitions . . . . . . . . . . . . . . . . .   2
   2.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
   3.  WebSocket Binding Overview  . . . . . . . . . . . . . . . . .   3
   4.  Establishing a Connection . . . . . . . . . . . . . . . . . .   3
   5.  Subprotocol Negotiation . . . . . . . . . . . . . . . . . . .   3
   6.  Record Framing  . . . . . . . . . . . . . . . . . . . . . . .   4
   7.  WebSocket Message Types . . . . . . . . . . . . . . . . . . .   5
   8.  QMux Version  . . . . . . . . . . . . . . . . . . . . . . . .   5
   9.  Keep-Alive and Idle Timeout . . . . . . . . . . . . . . . . .   5
   10. Datagrams . . . . . . . . . . . . . . . . . . . . . . . . . .   6
   11. Connection Close  . . . . . . . . . . . . . . . . . . . . . .   6
   12. Security Considerations . . . . . . . . . . . . . . . . . . .   6
   13. IANA Considerations . . . . . . . . . . . . . . . . . . . . .   6
   14. References  . . . . . . . . . . . . . . . . . . . . . . . . .   7
     14.1.  Normative References . . . . . . . . . . . . . . . . . .   7
     14.2.  Informative References . . . . . . . . . . . . . . . . .   7
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .   8
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .   8

1.  Conventions and Definitions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

   This document uses the terms QMux Record, QMux Frame, and transport
   parameter as defined in [qmux], and the terms WebSocket connection,
   message, frame, and subprotocol as defined in [RFC6455].

2.  Introduction

   QMux [qmux] lets an application written against the QUIC stream and
   datagram API run over an ordered, reliable byte-stream transport.  It
   defines a binding over TCP and over TLS, but a WebSocket binding is
   out of scope for the QUIC working group charter.

   A WebSocket binding is nevertheless useful: WebSocket [RFC6455] is
   available where UDP is blocked, in web browsers that lack
   WebTransport, and behind HTTP load balancers that cannot route raw
   TCP or QUIC.

Curley                   Expires 4 February 2027                [Page 2]
Internet-Draft                   qmux-ws                     August 2026

   This document specifies how to carry QMux over WebSocket: the message
   framing, the subprotocol negotiation used in place of TLS ALPN, keep-
   alive behavior, connection close, and datagrams.  All other QMux
   semantics (in-order STREAM frame delivery, stream identifiers, flow
   control, and transport parameters) apply unchanged from [qmux].

   This binding is application agnostic: any QUIC application that can
   run over QMux can run over QMux over WebSocket.  Media over QUIC
   Transport [moqt] is the motivating use case, but nothing in this
   document is specific to it.

3.  WebSocket Binding Overview

   A QMux-over-WebSocket connection is an ordinary WebSocket connection
   [RFC6455] whose binary messages carry QMux frames, taking the place
   of the underlying byte-stream transport in [qmux].

   Both the QMux Record layer and the WebSocket message layer provide
   self-delimiting messages over a reliable, ordered byte stream.  The
   two layers are therefore collapsed: instead of prefixing each Record
   with its Size, the binding relies on the WebSocket message boundary
   to delimit it.

4.  Establishing a Connection

   A client establishes a QMux-over-WebSocket connection by opening a
   WebSocket connection per [RFC6455] (the opening handshake over
   HTTP/1.1) or per [RFC9220] (the bootstrapping mechanism over HTTP/2
   or HTTP/3).

   The ws URI scheme is used over an unencrypted transport and the wss
   URI scheme is used over a TLS-encrypted transport.  Deployments
   SHOULD use wss; an application that expects a TLS transport when
   running natively over QUIC SHOULD require wss here.

   How the underlying connection is authenticated and authorized is out
   of scope for this document, as it is for [qmux].

5.  Subprotocol Negotiation

   QMux over TCP/TLS uses TLS ALPN [RFC8446] to agree on the application
   protocol.  WebSocket has no ALPN exchange, so this binding uses the
   WebSocket subprotocol negotiation of [RFC6455] Section 1.9 (the Sec-
   WebSocket-Protocol header) in its place, carrying the same
   application protocol identifier.

Curley                   Expires 4 February 2027                [Page 3]
Internet-Draft                   qmux-ws                     August 2026

   The subprotocol identifier is exactly the identifier the application
   would use as its ALPN over native QUIC, for example moq-transport-18.
   It also determines the QMux wire-format version, so there is no
   separate QMux version negotiation (see Section 8).

   A client offers one or more identifiers in the Sec-WebSocket-Protocol
   request header, in decreasing order of preference, one per protocol
   version it is willing to use.  A server selects at most one, in its
   own order of preference, and echoes it in the response header; if it
   supports none of the offered identifiers, it MUST fail the handshake.
   A client MUST treat a response value it did not offer as a failed
   handshake per [RFC6455], and this binding additionally requires a
   selection: a client MUST treat the absence of a Sec-WebSocket-
   Protocol response header as a failed handshake too, since without one
   no QMux version was agreed.

6.  Record Framing

   Each WebSocket binary message carries exactly one QMux Record's
   Frames field: one or more QMux frames concatenated, as defined in
   [qmux].  Because the WebSocket framing layer already delimits each
   message, the QMux Record Size field is redundant: it MUST NOT be
   transmitted and MUST NOT be expected by the receiver.

   A QMux-over-WebSocket record is therefore:

   WebSocket Binary Message {
     Frames (..),
   }

   The frames inside a message are encoded exactly as in [qmux],
   including the in-order STREAM frame requirement: for each QUIC
   stream, a sender MUST send that stream's payload in order, so a
   receiver can deliver payload to the application as it arrives without
   reassembly.

   An endpoint MAY place multiple frames in a single binary message and
   MAY split a logical sequence of frames across multiple messages,
   subject to the constraint that each STREAM frame's payload bytes are
   delivered in order.  An empty binary message (zero frames) is
   permitted and carries no frames; a receiver MUST accept it and treat
   it as a no-op.

   The maximum size of a binary message is bounded by the
   max_record_size transport parameter defined in [qmux] and by any
   WebSocket implementation limits.  An endpoint MUST NOT send a binary
   message whose payload exceeds the peer's advertised max_record_size,
   and MAY treat receipt of an oversized message as a connection error.

Curley                   Expires 4 February 2027                [Page 4]
Internet-Draft                   qmux-ws                     August 2026

7.  WebSocket Message Types

   This binding uses WebSocket message and control frames as follows:

   *  _Binary messages_ carry QMux frames as defined in Section 6.

   *  _Text messages_ MUST NOT be sent.  A receiver MUST treat a text
      message as a connection error and close the WebSocket connection.

   *  _Close frames_ terminate the connection as defined in Section 11.

   *  _Ping and Pong frames_ are used for keep-alive as defined in
      Section 9 and are otherwise handled by the WebSocket layer; they
      carry no QMux frames.

   The first QMux frame sent by each endpoint MUST be the
   QX_TRANSPORT_PARAMETERS frame, exactly as required by [qmux]; this
   binding does not change that requirement.

8.  QMux Version

   The QMux version is not signaled on the wire.  As with QMux over TLS,
   it is implied by the negotiated application protocol: each
   application protocol that runs over QMux specifies which QMux version
   each of its identifiers uses.  An application protocol used with this
   binding MUST select a QMux version that provides the Record layer
   (see Section 6), i.e. [qmux] or later.

9.  Keep-Alive and Idle Timeout

   A WebSocket connection has no built-in idle timeout: if the peer's
   host crashes without a TCP FIN, the local socket can remain "open"
   for hours.

   To detect a dead peer, an endpoint SHOULD send WebSocket Ping frames
   [RFC6455] periodically and SHOULD close the connection if no
   WebSocket frame of any kind is received within a timeout, a small
   multiple of the ping interval.  Reasonable defaults are a 5-second
   ping interval and a 30-second timeout, but the values are a local
   policy decision.  Receipt of any WebSocket frame from the peer
   (binary, Ping, or Pong) resets the idle timer.

   This keep-alive operates at the WebSocket layer and is separate from
   the QMux max_idle_timeout transport parameter and QX_PING frame,
   either of which an endpoint MAY also use.

Curley                   Expires 4 February 2027                [Page 5]
Internet-Draft                   qmux-ws                     August 2026

10.  Datagrams

   QMux datagrams are supported.  They are negotiated and encoded
   exactly as in [qmux]: an endpoint advertises the datagram transport
   parameter and carries QMux DATAGRAM frames inside binary messages,
   like any other frame (Section 6).

11.  Connection Close

   An endpoint terminates a QMux-over-WebSocket connection by sending a
   WebSocket Close frame [RFC6455] and then closing the underlying
   transport.

   A QMux CONNECTION_CLOSE frame, if sent, conveys the QMux-level error
   code and reason and SHOULD be sent in a final binary message before
   the WebSocket Close frame.  Because the WebSocket layer provides its
   own connection close, there is no draining period: an endpoint MAY
   close immediately after sending its Close frame.

   Receipt of a WebSocket Close frame, or loss of the underlying
   transport, terminates the QMux connection and all of its streams.

12.  Security Considerations

   This binding inherits the security considerations of QMux [qmux],
   WebSocket [RFC6455], and, when wss is used, TLS [RFC8446].

   Carrying QMux over WebSocket does not add or remove any QMux-level
   security property.  In particular, this binding provides no
   transport-layer confidentiality or integrity of its own; deployments
   that require those properties MUST use wss (WebSocket over TLS).

   The keep-alive mechanism in Section 9 causes an endpoint to send
   periodic Ping frames.  An endpoint SHOULD bound the rate at which it
   sends and responds to Ping/Pong frames to avoid amplification or
   resource-exhaustion concerns.

   Because a server selects the subprotocol from a client-supplied list,
   a server MUST validate the selected identifier against its own
   supported set and MUST NOT echo an arbitrary client-supplied value,
   as required by [RFC6455].

13.  IANA Considerations

   This document has no IANA actions.

Curley                   Expires 4 February 2027                [Page 6]
Internet-Draft                   qmux-ws                     August 2026

   This binding defines no subprotocol identifiers of its own: the Sec-
   WebSocket-Protocol value is the application protocol identifier,
   which is owned by the application protocol's specification (for
   example, [moqt]).  Whether those identifiers are registered in the
   WebSocket Subprotocol Name Registry [RFC6455] is therefore up to each
   application protocol, not this document.

14.  References

14.1.  Normative References

   [qmux]     Oku, K., Pardue, L., Iyengar, J., and E. Kinnear, "QMux",
              Work in Progress, Internet-Draft, draft-ietf-quic-qmux-02,
              6 July 2026, <https://datatracker.ietf.org/doc/html/draft-
              ietf-quic-qmux-02>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC6455]  Fette, I. and A. Melnikov, "The WebSocket Protocol",
              RFC 6455, DOI 10.17487/RFC6455, December 2011,
              <https://www.rfc-editor.org/rfc/rfc6455>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

14.2.  Informative References

   [moqt]     Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell,
              "Media over QUIC Transport", Work in Progress, Internet-
              Draft, draft-ietf-moq-transport-19, 6 July 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-moq-
              transport-19>.

   [RFC8446]  Rescorla, E., "The Transport Layer Security (TLS) Protocol
              Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
              <https://www.rfc-editor.org/rfc/rfc8446>.

   [RFC9220]  Hamilton, R., "Bootstrapping WebSockets with HTTP/3",
              RFC 9220, DOI 10.17487/RFC9220, June 2022,
              <https://www.rfc-editor.org/rfc/rfc9220>.

Curley                   Expires 4 February 2027                [Page 7]
Internet-Draft                   qmux-ws                     August 2026

Acknowledgments

   QMux is the work of the QUIC working group; this document only
   defines a WebSocket binding for it.  Thanks to the Media over QUIC
   working group for motivating a transport that works where UDP does
   not.

Author's Address

   Luke Curley
   Email: kixelated@gmail.com

Curley                   Expires 4 February 2027                [Page 8]