-
Notifications
You must be signed in to change notification settings - Fork 293
Muxer selection in security handshake #446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dbde5fd
a8804dd
ad1bae7
0d35e15
ec2e959
0042384
dcac239
245361c
a5b3ef0
349ac76
d6eb581
07f5d70
808a6f6
c7a1db0
811fc05
239dfca
f0fe69a
1c716e2
24d021d
5c28fc1
3e3394a
c6b8ed2
54379a9
06896c3
cc2bbcb
f81c6f4
0b73a38
aecfbb8
5192ad1
4ff74a7
f69b691
8e51f46
eb4e697
ef8657d
8296442
0fc4452
a11ff1d
b4ce114
9b11a68
002e37f
e3fcb38
4a167d1
3e9586b
f682f6b
c07fb79
1e7a3c0
eafbffc
1e52c1e
fe88ccf
da63658
1306199
bb070b2
d90a15e
447be1f
c23af93
6fe4166
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| # Stream multiplexer negotiation in security handshake <!-- omit in toc --> | ||
|
|
||
|
|
||
| | Lifecycle Stage | Maturity | Status | Latest Revision | | ||
| |-----------------|---------------|--------|-----------------| | ||
| | 1A | Working Draft | Active | r1, 2022-12-07 | | ||
|
|
||
| Authors: [@julian88110], [@marten-seemann] | ||
|
|
||
| Interest Group: [@marcopolo], [@mxinden] | ||
|
|
||
| [@marten-seemann]: https://github.com/marten-seemann | ||
| [@marcopolo]: https://github.com/marcopolo | ||
| [@mxinden]: https://github.com/mxinden | ||
| [@julian88110]: https://github.com/julian88110 | ||
|
|
||
| See the [lifecycle document][lifecycle-spec] for context about maturity level | ||
| and spec status. | ||
|
|
||
| [lifecycle-spec]: https://github.com/libp2p/specs/blob/master/00-framework-01-spec-lifecycle.md | ||
|
|
||
| ## Table of Contents <!-- omit in toc --> | ||
|
|
||
| - [Overview](#overview) | ||
| - [Design](#design) | ||
| - [Multiplexer Negotiation over TLS](#multiplexer-negotiation-over-tls) | ||
| - [Multiplexer Negotiation over Noise](#multiplexer-negotiation-over-noise) | ||
| - [Privacy](#privacy) | ||
| - [Alternative options considered](#alternative-options-considered) | ||
|
|
||
| ## Overview | ||
|
|
||
| Transports that don't support native stream multiplexing (e.g. TCP, WebSocket) negotiate | ||
| a stream multiplexer after completion of the cryptographic handshake, as described in [connections]. | ||
| Negotiating the stream multiplexer takes one network roundtrip. | ||
| This document defines a backwards-compatible optimization, which allows running the | ||
| multiplexer negotiation during the cryptographic handshake, thereby reducing the latency of | ||
| connection establishment by one roundtrip. | ||
|
|
||
|
|
||
| ## Design | ||
|
|
||
| ### Multiplexer Negotiation over TLS | ||
|
|
||
| When using TLS, the [ALPN] extension is used to negotiate the multiplexer. | ||
|
|
||
| The ALPN TLS extension allows the client to send a list of supported application | ||
| protocols as part of the TLS `ClientHello` message. The server chooses | ||
| a protocol and sends the selected protocol as part of the TLS | ||
| `ServerHello` message. | ||
|
|
||
| For the purpose of multiplexer negotiation, the protocol IDs of the stream | ||
| multiplexers are sent, followed by the `"libp2p"` protocol code. The multiplexer list is ordered by | ||
| the client's preference, with the most preferred multiplexer at the beginning. | ||
| The server SHOULD respect the client's preference and pick the first protocol | ||
| from the list that it supports. | ||
|
|
||
| Example for a node supporting both yamux and mplex, with a preference for yamux: | ||
| ```json | ||
| [ "/yamux/1.0.0", "/mplex/6.7.0", "libp2p" ] | ||
| ``` | ||
|
|
||
| The `"libp2p"` protocol code MUST always be the last item in the multiplexer list. | ||
| According to [TLS], nodes that don't implement the optimization described in | ||
| this document use `"libp2p"` for their ALPN. If `"libp2p"` is the result of the | ||
|
Comment on lines
+64
to
+65
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless I am missing something this is not true: the TLS spec does not specify what ALPN to use.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you could accept HTTP and libp2p at the same time. That's WebTransport does, by the way.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Good catch. Both Go and Rust do this. @marten-seemann can you add it to the TLS spec? Either in this pull request or a separate one? |
||
| ALPN process, nodes MUST use protocol negotiation of the stream multiplexer | ||
| as described in [connections]. | ||
|
|
||
| ### Multiplexer Negotiation over Noise | ||
|
|
||
| The libp2p Noise Specification allows Noise handshake messages to carry | ||
| early data. [Noise-Early-Data] is carried in the second and third message of | ||
| the XX handshake pattern as illustrated in the following message sequence chart. | ||
| The second message carries early data in the form of a list of multiplexers | ||
| supported by the responder. The initiator sends its supported multiplexer list | ||
| in the third message of the handshake process, ordered by its preference. It | ||
| MAY choose a single multiplexer from the responder's list and only send that | ||
| value. | ||
|
|
||
| The multiplexer to use is determined by picking the first item from the | ||
| initiator's list that both parties support. | ||
|
|
||
| Example: Noise handshake between two clients that both support mplex and yamux. The | ||
| client prefers yamux, whereas the server prefers mplex. | ||
|
|
||
| ``` | ||
| XX: | ||
| -> e | ||
| <- e, ee, s, es, [ "/mplex/6.7.0", "/yamux/1.0.0" ] | ||
| -> s, se, [ "/yamux/1.0.0", "/mplex/6.7.0" ] | ||
| ``` | ||
|
|
||
| The result of this negotiation is `"/mplex/6.7.0"`. | ||
|
|
||
| If there is no overlap between the multiplexers support by client and server, | ||
| the handshake MUST fail. | ||
|
|
||
| The format of the early data is specified in [Noise-handshake-payload]. | ||
|
|
||
|
|
||
| ## Privacy | ||
|
|
||
| The list of multiplexers carried in the TLS ALPN extension field is part of the | ||
| unencrypted ClientHello message. Therefore, using this optimization | ||
| exposes the list of supported multiplexers to an on-path observer. This leak can | ||
| be considered insignificant, since a libp2p node reveals its list of supported | ||
| multiplexers to any node that connects to it. | ||
|
|
||
| However, the NoiseExtensions in the Noise handshake are sent after the peers have | ||
| established a shared key, so an on-path observer won't be able to obtain the | ||
| list of multiplexers. | ||
|
|
||
|
|
||
| ## Alternative options considered | ||
|
|
||
| Instead of ALPN for multiplexer selection to reduce RTT, other options such as | ||
| TLS extension and X.509 extension were considered. The pros and cons are explored | ||
| and the discussion details can be found at [#454]. | ||
|
|
||
|
|
||
| [TLS]: https://github.com/libp2p/specs/blob/master/tls/tls.md | ||
| [connections]: https://github.com/libp2p/specs/tree/master/connections | ||
| [ALPN]: https://datatracker.ietf.org/doc/html/rfc7301 | ||
| [Noise-Early-Data]: https://github.com/libp2p/specs/tree/master/noise#libp2p-data-in-handshake-messages | ||
| [ECH]: https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ | ||
| [#454]: https://github.com/libp2p/specs/issues/454 | ||
| [Noise-handshake-payload]: https://github.com/libp2p/specs/tree/master/noise#the-libp2p-handshake-payload | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.