From 9677aa2f340638e34b7759f1fc7a66593385cf0d Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 11 May 2022 20:12:36 +0200 Subject: [PATCH 001/128] webrtc/: Add libp2p WebRTC specification --- webrtc/README.md | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 webrtc/README.md diff --git a/webrtc/README.md b/webrtc/README.md new file mode 100644 index 000000000..f2aa5fa0f --- /dev/null +++ b/webrtc/README.md @@ -0,0 +1,103 @@ +# WebRTC + +| Lifecycle Stage | Maturity | Status | Latest Revision | +|-----------------|---------------|--------|-----------------| +| 1A | Working Draft | Active | | + +Authors: [@mxinden] + +Interest Group: [@marten-seemann] + +## Motivation + +1. **No need for valid TLS certificates.** Enable browsers to connect to public + server nodes without those server nodes providing a TLS certificate within + the browsers trustchain. Note that we can not do this today with our + Websocket transport. + +2. **Hole punching in the browser**: Enable two browsers or a browser and a + non-public server node to connect. + +## Requirements + +- Loading a remote nodes certificate into ones browser trust-store is not an + option, i.e. doesn't scale. + +- No dependency on central STUN and/or TURN servers. + +## Protocol + +### Setup + +1. [Generate a + certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate). + +2. [Get the certificate's + fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). + +3. Sign this fingerprint using the libp2p peer key to generate a "peer cert" + +### Connection Establishment + +1. Create a connection with the certificate. + +2. Open a data stream. + +3. Send the "peer cert". + +4. Wait for the other side to do the same. + +5. [Get the remote peer's TLS + certificate](https://www.w3.org/TR/webrtc/#dom-rtcdtlstransport-getremotecertificates). + +6. Check the remote endpoint's "peer cert". + +## Open Questions + +_Where _Browser_ is replaced with the major desktop browsers of today (Chrome, +Safari, Edge, Firefox)._ + +### Direct connections + +#### Browser to public server node + +- Can _Browser_ generate a _valid_ SDP packet for the remote node based on the + remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS + certificate fingerprint (e.g. + `/ip6/2001:db8::/udp/1234/webrtc/ Date: Tue, 17 May 2022 14:13:52 +0200 Subject: [PATCH 002/128] webrtc/: Document RTCCertificate#getFingerprints --- webrtc/README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index f2aa5fa0f..677a22f11 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -85,6 +85,15 @@ Safari, Edge, Firefox)._ While WebRTC offers confidentiality and integrity via TLS, one still needs to authenticate the remote peer by its libp2p identity. +- Can a _Browser_ access the fingerprint of its TLS certificate? + + Chrome allows you to access the fingerprint of any locally-created certificate + directly via `RTCCertificate#getFingerprints`. Firefox does not allow you to + do so. Browser compatibility can be found + [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In + practice, this is not an issue since the fingerprint is embedded in the local + SDP string. + - Is the above proposed #protocol secure? ### Multiplexing @@ -96,8 +105,10 @@ authenticate the remote peer by its libp2p identity. ## Previous, ongoing and related work -- Proof of concept for the server side in rust-libp2p: https://github.com/libp2p/rust-libp2p/pull/2622 +- Proof of concept for the server side in rust-libp2p: + https://github.com/libp2p/rust-libp2p/pull/2622 -- Proof of concept for the server side (native) and the client side (Rust in WASM): https://github.com/wngr/libp2p-webrtc +- Proof of concept for the server side (native) and the client side (Rust in + WASM): https://github.com/wngr/libp2p-webrtc - WebRTC using STUN and TURN: https://github.com/libp2p/js-libp2p-webrtc-star From 64a3dff2c0a40e296d78309d42febc98632ea52c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 17 May 2022 14:37:18 +0200 Subject: [PATCH 003/128] webrtc/: Extend protocol flow --- webrtc/README.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 677a22f11..fcdda3af1 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -27,7 +27,9 @@ Interest Group: [@marten-seemann] ## Protocol -### Setup +Scenario: Browser _A_ wants to connect to server node _B_. + +### Setup - Both _A_ and _B_ 1. [Generate a certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate). @@ -39,18 +41,27 @@ Interest Group: [@marten-seemann] ### Connection Establishment -1. Create a connection with the certificate. +1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP + port and TLS certificate fingerprint (e.g. + `/ip6/2001:db8::/udp/1234/webrtc/ Date: Tue, 17 May 2022 14:41:52 +0200 Subject: [PATCH 004/128] webrtc/: Mention SDP exchange through relay and DCUtR --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index fcdda3af1..78749f647 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -91,6 +91,11 @@ Safari, Edge, Firefox)._ - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? +- Can two _Browsers_ exchange their SDP packets via a third server node using + Circuit Relay v2 and DCUtR? Instead of exchanging the original SDP packets, + could they exchange their multiaddr and construct the remote's SDP packet + based on it? + ### Securing the connection While WebRTC offers confidentiality and integrity via TLS, one still needs to From 28e341b9480e10bf03b313758d58a76fe7949ba7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 18 May 2022 13:33:28 +0200 Subject: [PATCH 005/128] webrtc/: Stress that A can build B's SDP offer locally --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 78749f647..c88a95489 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -48,7 +48,7 @@ Scenario: Browser _A_ wants to connect to server node _B_. 2. _A_ create a connection with its local certificate. -3. _A_ constructs _B_'s SDP offer based on _B_'s multiaddr and sets it +3. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). From b3bd98121f456dc93f84d75bd07e2bf94cc62dba Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 18 May 2022 13:35:02 +0200 Subject: [PATCH 006/128] webrtc/: Add B's peer ID to B's multiaddr --- webrtc/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c88a95489..b2a0a8d0b 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -42,9 +42,9 @@ Scenario: Browser _A_ wants to connect to server node _B_. ### Connection Establishment 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP - port and TLS certificate fingerprint (e.g. - `/ip6/2001:db8::/udp/1234/webrtc/`), + through some external mechanism. 2. _A_ create a connection with its local certificate. From dc6fb4ecc985c03da3d01dad479f66e073f563a1 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 19 May 2022 21:50:21 +0200 Subject: [PATCH 007/128] webrtc/: Add FAQ section --- webrtc/README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index b2a0a8d0b..f32580156 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -128,3 +128,28 @@ authenticate the remote peer by its libp2p identity. WASM): https://github.com/wngr/libp2p-webrtc - WebRTC using STUN and TURN: https://github.com/libp2p/js-libp2p-webrtc-star + +# FAQ + +- _Why exchange the TLS certificate fingerprint in the multiaddr? Why not + base it on the libp2p public key?_ + + Browsers do not allow loading a custom certificate. One can only generate a + certificate via + [rtcpeerconnection-generatecertificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate). + +- _Why not embed the peer ID in the TLS certificate, thus rendering the + additional "peer certificate" exchange obsolete?_ + + Browsers do not allow editing the properties of the TLS certificate. + +- _How about distributing the multiaddr in a signed peer record, thus rendering + the additional "peer certificate" exchange obsolete?_ + + Signed peer records are not yet rolled out across the many libp2p protocols. + Making the libp2p WebRTC protocol dependent on the former is not deemed worth + it at this point in time. Later versions of the libp2p WebRTC protocol might + adopt this optimization. + + Note, one can role out a new version of the libp2p WebRTC protocol through a + new multiaddr protocol, e.g. `/webrtc-2`. From 9728e22b3120728d9ff8c5637efadbe2ef5f529b Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 24 May 2022 19:56:33 +0200 Subject: [PATCH 008/128] webrtc/: Do additional auth handshake to prevent replay attack Credit goes to @marten-seemann. --- webrtc/README.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index f32580156..f5149fdfc 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -37,8 +37,6 @@ Scenario: Browser _A_ wants to connect to server node _B_. 2. [Get the certificate's fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). -3. Sign this fingerprint using the libp2p peer key to generate a "peer cert" - ### Connection Establishment 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP @@ -54,14 +52,15 @@ Scenario: Browser _A_ wants to connect to server node _B_. 4. _A_ establishes the connection to _B_. -5. _A_ opens a data stream. - -6. _A_ and _B_ exchange the "peer certs". - -7. [Get the remote peer's TLS - certificate](https://www.w3.org/TR/webrtc/#dom-rtcdtlstransport-getremotecertificates). +5. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, + where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could + for example be Noise. See WebTransport specification as an example + https://github.com/libp2p/specs/pull/404. Still to be specified here for + WebRTC. -8. Check the remote endpoint's "peer cert". +6. On success of the authentication handshake _X_, the used datachannel is + closed and the plain WebRTC connection is used with its multiplexing + capabilities via datachannels. ## Open Questions @@ -153,3 +152,9 @@ authenticate the remote peer by its libp2p identity. Note, one can role out a new version of the libp2p WebRTC protocol through a new multiaddr protocol, e.g. `/webrtc-2`. + +- _Why do an authentication handshake on top of an established WebRTC + connection? Why not only exchange signatures of ones TLS fingerprint signed + with ones libp2p private key?_ + + This is prone to replay attacks. From 13f6aaa69cb52351304d64d4df0b3a04332e2d61 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:17:25 +0200 Subject: [PATCH 009/128] webrtc/: Differentiate in Browser->Server and Browser->Browser --- webrtc/README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index f5149fdfc..33e7a59cb 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -27,9 +27,11 @@ Interest Group: [@marten-seemann] ## Protocol +### Browser to Server + Scenario: Browser _A_ wants to connect to server node _B_. -### Setup - Both _A_ and _B_ +#### Setup - Both _A_ and _B_ 1. [Generate a certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate). @@ -37,7 +39,7 @@ Scenario: Browser _A_ wants to connect to server node _B_. 2. [Get the certificate's fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). -### Connection Establishment +#### Connection Establishment 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and libp2p peer ID (e.g. @@ -62,6 +64,17 @@ Scenario: Browser _A_ wants to connect to server node _B_. closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. +### Browser to Browser + +Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of +server node _R_. + +- Replace STUN with libp2p's identify and AutoNAT + - https://github.com/libp2p/specs/tree/master/identify + - https://github.com/libp2p/specs/blob/master/autonat/README.md +- Replace TURN with libp2p's Circuit Relay v2 + - https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md + ## Open Questions _Where _Browser_ is replaced with the major desktop browsers of today (Chrome, From 7ec96dbccc5bbdb0a905c82d50e97fd8946e0f53 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:21:21 +0200 Subject: [PATCH 010/128] webrtc/: Document open question of B learning A's fingerprint --- webrtc/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 33e7a59cb..da7faa2d0 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -95,6 +95,10 @@ Safari, Edge, Firefox)._ WebRTC connection from a remote node without previously receiving an SDP packet from such host? + How does the server learn the TLS certificate fingerprint of the browser? Is + embedding A's TLS certificate fingerprint in A's STUN message USERNAME + attribute a valid option? + #### Browser to browser or non-public server node - Can _Browser_ know upfront its UDP port which it is listening for incoming From 5f5fd60eb5cb828ac11b02d1a2af15be6758c72d Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:26:44 +0200 Subject: [PATCH 011/128] webrtc/: Detail generic RTCPeerConnection creation --- webrtc/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index da7faa2d0..6c6beecc2 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -46,7 +46,8 @@ Scenario: Browser _A_ wants to connect to server node _B_. `/ip6/2001:db8::/udp/1234/webrtc/`), through some external mechanism. -2. _A_ create a connection with its local certificate. +2. _A_ create a connection passing its local certificate as a parameter. See + [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). 3. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it via From 84d4c41ae1d9353fb6bec509837fe690b2299793 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:34:42 +0200 Subject: [PATCH 012/128] webrtc/: Describe address scheme --- webrtc/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 6c6beecc2..a876a4119 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -25,6 +25,15 @@ Interest Group: [@marten-seemann] - No dependency on central STUN and/or TURN servers. +## Addressing + +WebRTC multiaddresses are composed of an IP and UDP address component, followed +by `/webrtc` and a multihash of the certificate that the node uses. + +Examples: +- `/ip4/1.2.3.4/udp/1234/webrtc/certhash//p2p/` +- `/ip6/fe80::1ff:fe23:4567:890a/udp/1234/webrtc/certhash//p2p/` + ## Protocol ### Browser to Server From 9790d1ab8800571c7f679d0edbf92f46a69fca87 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:38:02 +0200 Subject: [PATCH 013/128] webrtc/: Document open question of B learning A's fingerprint --- webrtc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index a876a4119..1712c5261 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -62,7 +62,9 @@ Scenario: Browser _A_ wants to connect to server node _B_. via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). -4. _A_ establishes the connection to _B_. +4. _A_ establishes the connection to _B_. Yet to be determined how _B_ learns of + _A_ fingerprint. Potentially through A's STUN message USERNAME attribute. See + Open Questions below. 5. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could From 4c6320e14b6a46b115ca37ece34aa1bacf6f1438 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:41:32 +0200 Subject: [PATCH 014/128] webrtc/: Fix outdated multiaddrs --- webrtc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 1712c5261..29bde2210 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -52,7 +52,7 @@ Scenario: Browser _A_ wants to connect to server node _B_. 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and libp2p peer ID (e.g. - `/ip6/2001:db8::/udp/1234/webrtc/`), + `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), through some external mechanism. 2. _A_ create a connection passing its local certificate as a parameter. See @@ -99,7 +99,7 @@ Safari, Edge, Firefox)._ - Can _Browser_ generate a _valid_ SDP packet for the remote node based on the remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS certificate fingerprint (e.g. - `/ip6/2001:db8::/udp/1234/webrtc//p2p/`)? _Valid_ in the sense that this generated SDP packet can then be used to establish a WebRTC connection to the remote. From 449462bac68abfe953bd8edba520909ce89a10c7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 1 Jun 2022 18:53:22 +0200 Subject: [PATCH 015/128] webrtc/: Document open question of key derivation for TLS cert --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 29bde2210..4af124614 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -140,6 +140,11 @@ authenticate the remote peer by its libp2p identity. - Is the above proposed #protocol secure? +- On the server side, can one derive the TLS certificate in a deterministic way + based on a node's libp2p private key? Benefit would be that a node only needs + to persist the libp2p private key and not the TLS key material while still + maintaining a fixed TLS certificate fingerprint. + ### Multiplexing - Can we use WebRTC’s data channels in _Browser_ to multiplex a single From 3e9fb704f3793a8aa9651f817d70eb3252ee7b97 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 3 Jun 2022 14:55:30 +0200 Subject: [PATCH 016/128] webrtc/: Determine UDP port for browser-to-browser --- webrtc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 4af124614..85bb96b01 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -114,7 +114,9 @@ Safari, Edge, Firefox)._ #### Browser to browser or non-public server node - Can _Browser_ know upfront its UDP port which it is listening for incoming - connections on? + connections on? Does the browser reuse the UDP port across many WebRTC + connections? If that is the case one could connect to any public node, with + the remote telling the local node what port it is perceived on. - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? From 81249f3f103bbde165e78518e0d91139fbddb994 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 22 Jun 2022 12:59:20 +0900 Subject: [PATCH 017/128] webrtc/: Add open question on udp vs tcp --- webrtc/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 85bb96b01..93eb4f584 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -92,6 +92,9 @@ server node _R_. _Where _Browser_ is replaced with the major desktop browsers of today (Chrome, Safari, Edge, Firefox)._ +- Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC + on top of both UDP and TCP? + ### Direct connections #### Browser to public server node From ee09ed48b3a326bf563933a7bb58c0c9904de2ff Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 27 Jun 2022 15:30:58 +0900 Subject: [PATCH 018/128] webrtc/README: Update with reuse of certificates --- webrtc/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 93eb4f584..f24d4f40c 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -123,6 +123,10 @@ Safari, Edge, Firefox)._ - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? + + Yes. For the lifetime of the page, one can generate a certificate once and + reuse it across connections. See also + https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#using_certificates - Can two _Browsers_ exchange their SDP packets via a third server node using Circuit Relay v2 and DCUtR? Instead of exchanging the original SDP packets, From d451652affc2dd226dbaf41e9950e088237a7de7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 27 Jun 2022 15:35:00 +0900 Subject: [PATCH 019/128] webrtc/: Answer question no double muxing --- webrtc/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index f24d4f40c..19a1bb4f4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -161,6 +161,9 @@ authenticate the remote peer by its libp2p identity. of a WebRTC connection and WebRTC datachannel? In other words, does WebRTC provide all functionality of a libp2p muxer like Yamux (e.g. flow control)? + Yes, with WebRTC's datachannels running on top of SCTP, there is no need for + additional multiplexing. + ## Previous, ongoing and related work - Proof of concept for the server side in rust-libp2p: From b48534062ce48321a070872b37325355063d97cf Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 27 Jun 2022 15:39:52 +0900 Subject: [PATCH 020/128] webrtc/: Reword connecting to instantiating --- webrtc/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 19a1bb4f4..5178f4f20 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -55,7 +55,8 @@ Scenario: Browser _A_ wants to connect to server node _B_. `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), through some external mechanism. -2. _A_ create a connection passing its local certificate as a parameter. See +2. _A_ instantiates a `RTCPeerConnection`, passing its local certificate as a + parameter. See [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). 3. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it From b654f117e71e73c5a6f15a71441efd0ecb48e9f7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 27 Jun 2022 15:48:41 +0900 Subject: [PATCH 021/128] webrtc/: Document generating valid SDP packet --- webrtc/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 5178f4f20..470fe4f90 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -107,6 +107,8 @@ Safari, Edge, Firefox)._ the sense that this generated SDP packet can then be used to establish a WebRTC connection to the remote. + Yes. + - Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a WebRTC connection from a remote node without previously receiving an SDP packet from such host? From 9a90f0dc9b4940038a3c7ac8d251d7f4e213b923 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 14:10:43 +0900 Subject: [PATCH 022/128] webrtc/: Restructure sections with Open Questions section each --- webrtc/README.md | 96 ++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 39 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 470fe4f90..22a06c6a1 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -8,6 +8,28 @@ Authors: [@mxinden] Interest Group: [@marten-seemann] + +**Table of Contents** + +- [WebRTC](#webrtc) + - [Motivation](#motivation) + - [Requirements](#requirements) + - [Addressing](#addressing) + - [Connection Establishment](#connection-establishment) + - [Browser to public Server](#browser-to-public-server) + - [Open Questions](#open-questions) + - [Browser to Browser](#browser-to-browser) + - [Open Questions](#open-questions-1) + - [Connection Security](#connection-security) + - [Open Questions](#open-questions-2) + - [Multiplexing](#multiplexing) + - [General Open Questions](#general-open-questions) + - [Previous, ongoing and related work](#previous-ongoing-and-related-work) +- [FAQ](#faq) + + + + ## Motivation 1. **No need for valid TLS certificates.** Enable browsers to connect to public @@ -34,21 +56,17 @@ Examples: - `/ip4/1.2.3.4/udp/1234/webrtc/certhash//p2p/` - `/ip6/fe80::1ff:fe23:4567:890a/udp/1234/webrtc/certhash//p2p/` -## Protocol - -### Browser to Server +## Connection Establishment -Scenario: Browser _A_ wants to connect to server node _B_. +### Browser to public Server -#### Setup - Both _A_ and _B_ +Scenario: Browser _A_ wants to connect to server node _B_ where _B_ is publicly +reachable but _B_ does not have a TLS certificate trusted by _A_. -1. [Generate a - certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate). - -2. [Get the certificate's - fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). - -#### Connection Establishment +As a preparation browser _A_ [generates a +certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate) +and [gets the certificate's +fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and libp2p peer ID (e.g. @@ -77,28 +95,7 @@ Scenario: Browser _A_ wants to connect to server node _B_. closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. -### Browser to Browser - -Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of -server node _R_. - -- Replace STUN with libp2p's identify and AutoNAT - - https://github.com/libp2p/specs/tree/master/identify - - https://github.com/libp2p/specs/blob/master/autonat/README.md -- Replace TURN with libp2p's Circuit Relay v2 - - https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md - -## Open Questions - -_Where _Browser_ is replaced with the major desktop browsers of today (Chrome, -Safari, Edge, Firefox)._ - -- Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC - on top of both UDP and TCP? - -### Direct connections - -#### Browser to public server node +#### Open Questions - Can _Browser_ generate a _valid_ SDP packet for the remote node based on the remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS @@ -113,11 +110,22 @@ Safari, Edge, Firefox)._ WebRTC connection from a remote node without previously receiving an SDP packet from such host? - How does the server learn the TLS certificate fingerprint of the browser? Is +- How does the server learn the TLS certificate fingerprint of the browser? Is embedding A's TLS certificate fingerprint in A's STUN message USERNAME - attribute a valid option? + attribute the best option? + +### Browser to Browser -#### Browser to browser or non-public server node +Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of +server node _R_. + +- Replace STUN with libp2p's identify and AutoNAT + - https://github.com/libp2p/specs/tree/master/identify + - https://github.com/libp2p/specs/blob/master/autonat/README.md +- Replace TURN with libp2p's Circuit Relay v2 + - https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md + +#### Open Questions - Can _Browser_ know upfront its UDP port which it is listening for incoming connections on? Does the browser reuse the UDP port across many WebRTC @@ -136,11 +144,13 @@ Safari, Edge, Firefox)._ could they exchange their multiaddr and construct the remote's SDP packet based on it? -### Securing the connection +## Connection Security While WebRTC offers confidentiality and integrity via TLS, one still needs to authenticate the remote peer by its libp2p identity. +### Open Questions + - Can a _Browser_ access the fingerprint of its TLS certificate? Chrome allows you to access the fingerprint of any locally-created certificate @@ -157,7 +167,7 @@ authenticate the remote peer by its libp2p identity. to persist the libp2p private key and not the TLS key material while still maintaining a fixed TLS certificate fingerprint. -### Multiplexing +## Multiplexing - Can we use WebRTC’s data channels in _Browser_ to multiplex a single connection, or do we need to run an additional multiplexer (e.g. yamux) on top @@ -167,6 +177,14 @@ authenticate the remote peer by its libp2p identity. Yes, with WebRTC's datachannels running on top of SCTP, there is no need for additional multiplexing. +## General Open Questions + +_Where _Browser_ is replaced with the major desktop browsers of today (Chrome, +Safari, Edge, Firefox)._ + +- Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC + on top of both UDP and TCP? + ## Previous, ongoing and related work - Proof of concept for the server side in rust-libp2p: From baccb1dd2c6af97d1b79cb6ed0555344e9871a30 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 14:13:46 +0900 Subject: [PATCH 023/128] webrtc/: Document DCUtR in browser-to-browser use-case --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 22a06c6a1..3dda0c2e0 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -124,6 +124,11 @@ server node _R_. - https://github.com/libp2p/specs/blob/master/autonat/README.md - Replace TURN with libp2p's Circuit Relay v2 - https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md +- Use DCUtR over Circuit Relay v2 to transmit SDP information + 1. Transform ICE candidates in SDP to multiaddresses. + 2. Transmit the set of multiaddresses to the remote via DCUtR. + 3. Transform the set of multiaddresses back to the remotes SDP. + 4. https://github.com/libp2p/specs/blob/master/relay/DCUtR.md #### Open Questions From 83e7aa0bb81aaa28d513833a84bd0ecc208bcd46 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 14:15:51 +0900 Subject: [PATCH 024/128] webrtc/: Document client fingerprint in STUN username --- webrtc/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 3dda0c2e0..c8f213037 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -81,9 +81,9 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). -4. _A_ establishes the connection to _B_. Yet to be determined how _B_ learns of - _A_ fingerprint. Potentially through A's STUN message USERNAME attribute. See - Open Questions below. +4. _A_ establishes the connection to _B_. _B_ learns of _A_ TLS fingerprint + through A's STUN message USERNAME attribute. See Open Questions below for + potential better solutions. 5. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could From 766bb62fd0a98daec5301ebc4e1a4c2ba7d9f727 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 14:20:30 +0900 Subject: [PATCH 025/128] webrtc/: Detail Multiplexing and Security in separate section --- webrtc/README.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c8f213037..4e4b4a80c 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -85,15 +85,9 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). through A's STUN message USERNAME attribute. See Open Questions below for potential better solutions. -5. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, - where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could - for example be Noise. See WebTransport specification as an example - https://github.com/libp2p/specs/pull/404. Still to be specified here for - WebRTC. +5. See [Connection Security](#connection-security). -6. On success of the authentication handshake _X_, the used datachannel is - closed and the plain WebRTC connection is used with its multiplexing - capabilities via datachannels. +6. See [Multiplexing](#multiplexing). #### Open Questions @@ -129,7 +123,7 @@ server node _R_. 2. Transmit the set of multiaddresses to the remote via DCUtR. 3. Transform the set of multiaddresses back to the remotes SDP. 4. https://github.com/libp2p/specs/blob/master/relay/DCUtR.md - + #### Open Questions - Can _Browser_ know upfront its UDP port which it is listening for incoming @@ -139,7 +133,7 @@ server node _R_. - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? - + Yes. For the lifetime of the page, one can generate a certificate once and reuse it across connections. See also https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#using_certificates @@ -154,6 +148,14 @@ server node _R_. While WebRTC offers confidentiality and integrity via TLS, one still needs to authenticate the remote peer by its libp2p identity. +After [Connection Establishment](#connection-establishment): + +1. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, + where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could + for example be Noise. See WebTransport specification as an example + https://github.com/libp2p/specs/pull/404. Still to be specified here for + WebRTC. + ### Open Questions - Can a _Browser_ access the fingerprint of its TLS certificate? @@ -174,6 +176,14 @@ authenticate the remote peer by its libp2p identity. ## Multiplexing +After [Connection Security](#connection-security): + +1. On success of the authentication handshake _X_, the used datachannel is + closed and the plain WebRTC connection is used with its multiplexing + capabilities via datachannels. + +### Open Questions + - Can we use WebRTC’s data channels in _Browser_ to multiplex a single connection, or do we need to run an additional multiplexer (e.g. yamux) on top of a WebRTC connection and WebRTC datachannel? In other words, does WebRTC From 525bc9e801ee15a92736942a2f89674aa9daba57 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 16:23:05 +0900 Subject: [PATCH 026/128] webrtc/: Document UDP port multiplexing and ICE lite --- webrtc/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 4e4b4a80c..f3a746473 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -108,6 +108,14 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). embedding A's TLS certificate fingerprint in A's STUN message USERNAME attribute the best option? +- Do the major WebRTC server implementations support using the same UDP port for + multiple WebRTC connections, thus requiring multiplexing multiple WebRTC + connections on the same UDP port? In particular this came up for NodeJS. + + This is related to [ICE Lite](https://www.rfc-editor.org/rfc/rfc5245), having + a host only advertise a single address, namely the host address, which is + assumed to be public. + ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of From 3e9e6df48b95801948f08ca5d8b9ce9c8955b6a6 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 16:36:37 +0900 Subject: [PATCH 027/128] webrtc/: Document potential attack vectors using STUN --- webrtc/README.md | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index f3a746473..dfbc9193e 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -91,23 +91,25 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). #### Open Questions -- Can _Browser_ generate a _valid_ SDP packet for the remote node based on the - remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS - certificate fingerprint (e.g. - `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`)? _Valid_ in - the sense that this generated SDP packet can then be used to establish a - WebRTC connection to the remote. - - Yes. - -- Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a - WebRTC connection from a remote node without previously receiving an SDP - packet from such host? - - How does the server learn the TLS certificate fingerprint of the browser? Is embedding A's TLS certificate fingerprint in A's STUN message USERNAME attribute the best option? +- Is the fact that the server accepts STUN messages from the client prone to + attacks? + + - Can an attacker launch an **amplification attack** with the STUN endpoint + of the server? + + - Can a client run a **DOS attack** by sending many STUN messages with + different ufrags using different UDP source ports, forcing the server to + allocate a new peer connection for each? Would rate limiting suffice to + defend against this attack? + + See also: + - https://datatracker.ietf.org/doc/html/rfc5389#section-16.2.1 + - https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2 + - Do the major WebRTC server implementations support using the same UDP port for multiple WebRTC connections, thus requiring multiplexing multiple WebRTC connections on the same UDP port? In particular this came up for NodeJS. @@ -116,6 +118,19 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). a host only advertise a single address, namely the host address, which is assumed to be public. +- Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a + WebRTC connection from a remote node without previously receiving an SDP + packet from such host? + +- Can _Browser_ generate a _valid_ SDP packet for the remote node based on the + remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS + certificate fingerprint (e.g. + `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`)? _Valid_ in + the sense that this generated SDP packet can then be used to establish a + WebRTC connection to the remote. + + Yes. + ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of From a29cb4596108e3e8259259890c7a85e47665bee5 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 16:47:22 +0900 Subject: [PATCH 028/128] webrtc/: Write out additional Noise handshake --- webrtc/README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index dfbc9193e..717f15772 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -173,11 +173,15 @@ authenticate the remote peer by its libp2p identity. After [Connection Establishment](#connection-establishment): -1. _A_ initiates some authentication handshake _X_ to _B_ on a datachannel, - where _X_ allows _A_ and _B_ to authenticate each other's peer IDs. _X_ could - for example be Noise. See WebTransport specification as an example - https://github.com/libp2p/specs/pull/404. Still to be specified here for - WebRTC. +1. _A_ opens a WebRTC datachannel and starts a Noise handshake using _A_'s and + _B_'s libp2p identity. See + [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). + +2. _A_ and _B_ write their TLS certificate fingerprint on the negotiated Noise channel. + +3. _A_ and _B_ read the other sides TLS certificate fingerprint on the + negotiated Noise channel and compare it to the ones verified during the DTLS + handshake. ### Open Questions @@ -190,7 +194,9 @@ After [Connection Establishment](#connection-establishment): practice, this is not an issue since the fingerprint is embedded in the local SDP string. -- Is the above proposed #protocol secure? +- Is the above proposed additional handshake secure? See also alternative + proposed Handshake for + [WebTransport](https://github.com/libp2p/specs/pull/404). - On the server side, can one derive the TLS certificate in a deterministic way based on a node's libp2p private key? Benefit would be that a node only needs From 827def2fa0ba9a7022c40bd54701298d1921db8f Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 1 Jul 2022 16:49:06 +0900 Subject: [PATCH 029/128] webrtc/: Delete outdated comment on browsers --- webrtc/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 717f15772..a4774eed2 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -223,9 +223,6 @@ After [Connection Security](#connection-security): ## General Open Questions -_Where _Browser_ is replaced with the major desktop browsers of today (Chrome, -Safari, Edge, Firefox)._ - - Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC on top of both UDP and TCP? From e6c23e150fa2e996a8fc31eda593aff1aad91105 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 6 Jul 2022 12:59:58 +0900 Subject: [PATCH 030/128] webrtc/: Document Firefox not connecting on localhost --- webrtc/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index a4774eed2..a670c105f 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -226,6 +226,9 @@ After [Connection Security](#connection-security): - Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC on top of both UDP and TCP? +- Is the fact that Firefox does not allow a WebRTC to `localhost` an issue? See + https://bugzilla.mozilla.org/show_bug.cgi?id=831926. + ## Previous, ongoing and related work - Proof of concept for the server side in rust-libp2p: From 5f7ea61484e4e777048d84273693504ff51a88df Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 12 Jul 2022 21:26:05 +0900 Subject: [PATCH 031/128] webrtc/: Document random string in STUN username and password --- webrtc/README.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index a670c105f..5a508c13c 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -81,19 +81,23 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). -4. _A_ establishes the connection to _B_. _B_ learns of _A_ TLS fingerprint - through A's STUN message USERNAME attribute. See Open Questions below for - potential better solutions. +4. _A_ establishes the connection to _B_. _A_ generates a random string and uses + that string as the username (_ufrag_ or _username fragment_) and password in + the initial STUN message from _A_ to _B_. The random string can be used by + _B_ to identify the connection, i.e. demultiplex incoming UDP datagrams per + incoming connection. _B_ uses the same random string for the username and + password of the STUN message from _B_ to _A_. -5. See [Connection Security](#connection-security). +5. _B_ does not know the TLS fingerprint of _A_. _B_ upgrades the incoming + connection from _A_ as an _insecure_ connection, learning _A_'s TLS + fingerprint through the WebRTC DTLS handshake. At this point the DTLS + handshake provides confidentiality and integrity but not authenticity. -6. See [Multiplexing](#multiplexing). +6. See [Connection Security](#connection-security). -#### Open Questions +7. See [Multiplexing](#multiplexing). -- How does the server learn the TLS certificate fingerprint of the browser? Is - embedding A's TLS certificate fingerprint in A's STUN message USERNAME - attribute the best option? +#### Open Questions - Is the fact that the server accepts STUN messages from the client prone to attacks? From f5eb1b72b26f6e9909db30790655629499a3272e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 12 Jul 2022 21:35:47 +0900 Subject: [PATCH 032/128] webrtc/: Document potential amplification defense through large client STUN --- webrtc/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 5a508c13c..c5925ab12 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -105,6 +105,17 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). - Can an attacker launch an **amplification attack** with the STUN endpoint of the server? + The QUIC protocol defends against amplification attacks by requiring: + + > an endpoint MUST limit the amount of data it sends to the unvalidated + > address to three times the amount of data received from that address. + + https://datatracker.ietf.org/doc/html/rfc9000#section-8 + + For WebRTC in libp2p one could require the client (_A_) to add additional + bytes to its STUN message, e.g. in the STUN username and password, thus + making an amplification attack less attractive. + - Can a client run a **DOS attack** by sending many STUN messages with different ufrags using different UDP source ports, forcing the server to allocate a new peer connection for each? Would rate limiting suffice to From a8a42b533b783136984e9500d05d67746e1012e4 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 12 Jul 2022 21:39:21 +0900 Subject: [PATCH 033/128] webrtc/: Document certhash being a multibase encoded multihash --- webrtc/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index c5925ab12..f45d2f42d 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -56,6 +56,10 @@ Examples: - `/ip4/1.2.3.4/udp/1234/webrtc/certhash//p2p/` - `/ip6/fe80::1ff:fe23:4567:890a/udp/1234/webrtc/certhash//p2p/` +The TLS certificate fingerprint in `/certhash` is a +[multibase](https://github.com/multiformats/multibase) encoded +[multihash](https://github.com/multiformats/multihash). + ## Connection Establishment ### Browser to public Server From c8e725aa170d9b60a3b8fe6a2d4a2ef7fa4dade9 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 12 Jul 2022 21:45:55 +0900 Subject: [PATCH 034/128] webrtc/: Document hash function match on WebRTC and Noise --- webrtc/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index f45d2f42d..ad8e4df21 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -196,12 +196,22 @@ After [Connection Establishment](#connection-establishment): _B_'s libp2p identity. See [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). -2. _A_ and _B_ write their TLS certificate fingerprint on the negotiated Noise channel. +2. _A_ and _B_ write their TLS certificate fingerprint on the negotiated Noise + channel as multibase encoded multihashes (see [#addressing]). 3. _A_ and _B_ read the other sides TLS certificate fingerprint on the negotiated Noise channel and compare it to the ones verified during the DTLS handshake. + Note: WebRTC supports different hash functions to hash the TLS certificate + (see https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash + function used in WebRTC, the hash function used for the hash exchanged in the + additional Noise handshake and the hash function used in the multiaddr + `/certhash` component MUST be the same. On mismatch the final Noise handshake + MUST fail. + + + ### Open Questions - Can a _Browser_ access the fingerprint of its TLS certificate? From 7e601e755ccd400c1fb6ce0c806300819a81fc53 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 12 Jul 2022 21:57:22 +0900 Subject: [PATCH 035/128] webrtc/: Track open question on whether server should initiate Noise --- webrtc/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index ad8e4df21..babcfe0e4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -227,6 +227,10 @@ After [Connection Establishment](#connection-establishment): proposed Handshake for [WebTransport](https://github.com/libp2p/specs/pull/404). +- Would it be more efficient for _B_ to initiate the Noise handshake? In other + words, who is able to write on an established WebRTC connection first? _A_ or + _B_? + - On the server side, can one derive the TLS certificate in a deterministic way based on a node's libp2p private key? Benefit would be that a node only needs to persist the libp2p private key and not the TLS key material while still From 9e8ec875f1202dcbe58a2eebe873d3c4fb6dcd97 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 21 Jul 2022 10:57:29 +0900 Subject: [PATCH 036/128] webrtc/readme/faq: Write out the need for handshake over plain sigs --- webrtc/README.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index babcfe0e4..d69fc7857 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -210,8 +210,6 @@ After [Connection Establishment](#connection-establishment): `/certhash` component MUST be the same. On mismatch the final Noise handshake MUST fail. - - ### Open Questions - Can a _Browser_ access the fingerprint of its TLS certificate? @@ -297,8 +295,22 @@ After [Connection Security](#connection-security): Note, one can role out a new version of the libp2p WebRTC protocol through a new multiaddr protocol, e.g. `/webrtc-2`. -- _Why do an authentication handshake on top of an established WebRTC - connection? Why not only exchange signatures of ones TLS fingerprint signed - with ones libp2p private key?_ - - This is prone to replay attacks. +- _Why exchange fingerprints in an additional authentication handshake on top of + an established WebRTC connection? Why not only exchange signatures of ones TLS + fingerprints signed with ones libp2p private key on the plain WebRTC + connection?_ + + Once _A_ and _B_ established a WebRTC connection, _A_ sends + `signature_libp2p_a(fingerprint_a)` to _B_ and vice versa. While this has the + benefit of only requring two messages, thus one round trip, it is prone to a + key compromise and replay attack. Say that _E_ is able to attain + `signature_libp2p_a(fingerprint_a)` and somehow compromise _A_'s TLS private + key, _E_ can now impersonate _A_ without knowing _A_'s libp2p private key. + + If one requires the signatures to contain both fingerprints, e.g. + `signature_libp2p_a(fingerprint_a, fingerprint_b)`, the above attack still + works, just that _E_ can only impersonate _A_ when talking to _B_. + + Adding a cryptographic identifier of the unique connection (i.e. session) to + the fingerprint would protect against this attack. To the best of our + knowledge the browser does not give us access to such identifier. From cceed493cdafa0e5e1b9d2b1e7051927353aceba Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 21 Jul 2022 11:07:08 +0900 Subject: [PATCH 037/128] webrtc/: Fix typo fingerprint -> signature --- webrtc/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index d69fc7857..a1b6b3a36 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -312,5 +312,6 @@ After [Connection Security](#connection-security): works, just that _E_ can only impersonate _A_ when talking to _B_. Adding a cryptographic identifier of the unique connection (i.e. session) to - the fingerprint would protect against this attack. To the best of our + the signature (`signature_libp2p_a(fingerprint_a, fingerprint_b, + connection_identifier)`) would protect against this attack. To the best of our knowledge the browser does not give us access to such identifier. From c5522c4ac3ddb3aa1681ecbfdaa92d62141307c0 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 27 Jul 2022 12:16:33 +0900 Subject: [PATCH 038/128] webrtc/: Document open question on Noise optimization --- webrtc/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index a1b6b3a36..9962ceb6b 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -229,6 +229,12 @@ After [Connection Establishment](#connection-establishment): words, who is able to write on an established WebRTC connection first? _A_ or _B_? +- Instead of exchanging the TLS fingerprints once the Noise handshake finished, + could one instead attach the fingerprints to the Noise handshake messages as + additional payloads? That would reduce the overall connection establishment + latency by one round trip. Would this schema be secure using the Noise XX + handshake pattern? + - On the server side, can one derive the TLS certificate in a deterministic way based on a node's libp2p private key? Benefit would be that a node only needs to persist the libp2p private key and not the TLS key material while still From c89a72a600d730aad9c04a70ecc5a2691cee420e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 2 Aug 2022 16:20:30 +0900 Subject: [PATCH 039/128] webrtc/: Reword Motivation section --- webrtc/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 9962ceb6b..c396cd73e 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -32,13 +32,15 @@ Interest Group: [@marten-seemann] ## Motivation -1. **No need for valid TLS certificates.** Enable browsers to connect to public - server nodes without those server nodes providing a TLS certificate within - the browsers trustchain. Note that we can not do this today with our - Websocket transport. +1. **No need for trusted TLS certificates.** Enable browsers to connect to + public server nodes without those server nodes providing a TLS certificate + within the browsers trustchain. Note that we can not do this today with our + Websocket transport as the browser requires the remote to have a trusted TLS + certificate. Nor can we establish a plain TCP or QUIC connection from within + a browser. 2. **Hole punching in the browser**: Enable two browsers or a browser and a - non-public server node to connect. + server node to connect even though one or both are behind a NAT / firewall. ## Requirements From bc76a064eebacbc025b33d767265d94b3ac4f837 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 2 Aug 2022 16:27:59 +0900 Subject: [PATCH 040/128] webrtc/: Document UDP port per RTCPeerConnection --- webrtc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index c396cd73e..3fb45e91b 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -170,11 +170,13 @@ server node _R_. #### Open Questions -- Can _Browser_ know upfront its UDP port which it is listening for incoming +- Can a browser know upfront its UDP port which it is listening for incoming connections on? Does the browser reuse the UDP port across many WebRTC connections? If that is the case one could connect to any public node, with the remote telling the local node what port it is perceived on. + No, a browser uses a new UDP port for each `RTCPeerConnection`. + - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? From a0ae9b0991aeedc6327411afb028066ea30377ad Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 2 Aug 2022 16:32:54 +0900 Subject: [PATCH 041/128] webrtc/: Extend on UDP muxing support across implementations --- webrtc/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 3fb45e91b..ab8875e77 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -133,12 +133,16 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). - Do the major WebRTC server implementations support using the same UDP port for multiple WebRTC connections, thus requiring multiplexing multiple WebRTC - connections on the same UDP port? In particular this came up for NodeJS. + connections on the same UDP port? This is related to [ICE Lite](https://www.rfc-editor.org/rfc/rfc5245), having a host only advertise a single address, namely the host address, which is assumed to be public. + The [Go WebRTC](https://github.com/pion/webrtc/) implementation and the [Rust + WebRTC](https://github.com/webrtc-rs/webrtc) implementation support this. It + is unclear whether this is supported in any of the NodeJS implementations. + - Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a WebRTC connection from a remote node without previously receiving an SDP packet from such host? From 774cd52cf0e43b24f808a1cbd359d48b37a06024 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 2 Aug 2022 16:54:25 +0900 Subject: [PATCH 042/128] webrtc/: Document SDP munging --- webrtc/README.md | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index ab8875e77..e0cee2f70 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -87,21 +87,32 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). -4. _A_ establishes the connection to _B_. _A_ generates a random string and uses - that string as the username (_ufrag_ or _username fragment_) and password in - the initial STUN message from _A_ to _B_. The random string can be used by - _B_ to identify the connection, i.e. demultiplex incoming UDP datagrams per - incoming connection. _B_ uses the same random string for the username and - password of the STUN message from _B_ to _A_. - -5. _B_ does not know the TLS fingerprint of _A_. _B_ upgrades the incoming +4. _A_ creates a local offer via + [`RTCPeerConnection.createOffer()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer). + _A_ generates a random string and sets that string as the username (_ufrag_ + or _username fragment_) and password on the SDP of the local offer. Finally + _A_ sets the modified offer via + [`RTCPeerConnection.setLocalDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription). + + Note that this process, oftentimes referred to as "SDP munging" is disallowed + by the specification, but not enforced across the major browsers (Safari, + Firefox, Chrome) due to use-cases in the wild. See also + https://bugs.chromium.org/p/chromium/issues/detail?id=823036 + +5. _A_ establishes the connection to _B_. The random string used as a _username_ + and _password_ can be used by _B_ to identify the connection, i.e. + demultiplex incoming UDP datagrams per incoming connection. _B_ uses the same + random string for the username and password in the STUN message from _B_ to + _A_. + +6. _B_ does not know the TLS fingerprint of _A_. _B_ upgrades the incoming connection from _A_ as an _insecure_ connection, learning _A_'s TLS fingerprint through the WebRTC DTLS handshake. At this point the DTLS handshake provides confidentiality and integrity but not authenticity. -6. See [Connection Security](#connection-security). +7. See [Connection Security](#connection-security). -7. See [Multiplexing](#multiplexing). +8. See [Multiplexing](#multiplexing). #### Open Questions From ae1020bebf29eda369b8361911e729fa22bc30bd Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 2 Aug 2022 17:13:05 +0900 Subject: [PATCH 043/128] webrtc/: Document Noise Prologue mechanism --- webrtc/README.md | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index e0cee2f70..43a2c20b5 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -211,23 +211,27 @@ authenticate the remote peer by its libp2p identity. After [Connection Establishment](#connection-establishment): -1. _A_ opens a WebRTC datachannel and starts a Noise handshake using _A_'s and - _B_'s libp2p identity. See +1. _A_ opens a WebRTC datachannel. + +2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity. See [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). -2. _A_ and _B_ write their TLS certificate fingerprint on the negotiated Noise - channel as multibase encoded multihashes (see [#addressing]). + Instead of exchanging the TLS certificate fingerprints on the established + Noise channel once the Noise handshake succeeded, _A_ and _B_ use the [Noise + Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism, thus + saving one round trip. + + More specifically, _A_ and _B_ set + `` (_connection intiator_ + first, _connection responder_ second) as the Noise _Prologue_ before starting + the actual Noise handshake. -3. _A_ and _B_ read the other sides TLS certificate fingerprint on the - negotiated Noise channel and compare it to the ones verified during the DTLS - handshake. +3. See [Multiplexing](#multiplexing). - Note: WebRTC supports different hash functions to hash the TLS certificate - (see https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash - function used in WebRTC, the hash function used for the hash exchanged in the - additional Noise handshake and the hash function used in the multiaddr - `/certhash` component MUST be the same. On mismatch the final Noise handshake - MUST fail. +Note: WebRTC supports different hash functions to hash the TLS certificate (see +https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used +in WebRTC and the hash function used in the multiaddr `/certhash` component MUST +be the same. On mismatch the final Noise handshake MUST fail. ### Open Questions @@ -248,12 +252,6 @@ After [Connection Establishment](#connection-establishment): words, who is able to write on an established WebRTC connection first? _A_ or _B_? -- Instead of exchanging the TLS fingerprints once the Noise handshake finished, - could one instead attach the fingerprints to the Noise handshake messages as - additional payloads? That would reduce the overall connection establishment - latency by one round trip. Would this schema be secure using the Noise XX - handshake pattern? - - On the server side, can one derive the TLS certificate in a deterministic way based on a node's libp2p private key? Benefit would be that a node only needs to persist the libp2p private key and not the TLS key material while still From 4b8e890c49061eb62c9d16a9afd3aa0a738e6285 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 4 Aug 2022 13:01:30 +0900 Subject: [PATCH 044/128] webrtc/: Require signature tag and sorted fingerprints --- webrtc/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 43a2c20b5..4b1a33370 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -221,10 +221,11 @@ After [Connection Establishment](#connection-establishment): Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism, thus saving one round trip. - More specifically, _A_ and _B_ set - `` (_connection intiator_ - first, _connection responder_ second) as the Noise _Prologue_ before starting - the actual Noise handshake. + More specifically _A_ and _B_ set the Noise _Prologue_ to + `libp2p-webrtc-noise:` before starting the actual Noise + handshake. `` is the concatenation of the of the two TLS + fingerprints of _A_ and _B_ in their multihash byte representation, sorted in + ascending order. 3. See [Multiplexing](#multiplexing). From 285574d9e7a8618b8b3dc7f91584e32970e1914f Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 18 Aug 2022 15:38:23 +0900 Subject: [PATCH 045/128] webrtc/: Add message framing to support half-close and reset of stream The WebRTC browser APIs do not support half-closing nor resets of streams. This commit defines a message framing schema to support this functionality on top of the browser APIs. --- webrtc/README.md | 76 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 4b1a33370..b866298a4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -227,7 +227,9 @@ After [Connection Establishment](#connection-establishment): fingerprints of _A_ and _B_ in their multihash byte representation, sorted in ascending order. -3. See [Multiplexing](#multiplexing). +3. On success of the authentication handshake, the used datachannel is + closed and the plain WebRTC connection is used with its multiplexing + capabilities via datachannels. See [Multiplexing](#multiplexing). Note: WebRTC supports different hash functions to hash the TLS certificate (see https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used @@ -260,21 +262,50 @@ be the same. On mismatch the final Noise handshake MUST fail. ## Multiplexing -After [Connection Security](#connection-security): - -1. On success of the authentication handshake _X_, the used datachannel is - closed and the plain WebRTC connection is used with its multiplexing - capabilities via datachannels. - -### Open Questions - -- Can we use WebRTC’s data channels in _Browser_ to multiplex a single - connection, or do we need to run an additional multiplexer (e.g. yamux) on top - of a WebRTC connection and WebRTC datachannel? In other words, does WebRTC - provide all functionality of a libp2p muxer like Yamux (e.g. flow control)? - - Yes, with WebRTC's datachannels running on top of SCTP, there is no need for - additional multiplexing. +Following [Connection Security](#connection-security). + +The WebRTC browser APIs do not support half-closing nor resets of streams. +[`RTCDataChannel.close()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close) +flushes the remaining messages and closes the local write and read side. After +calling `RTCDataChannel.close()` one can no longer read from the channel. This +lack of functionality is problematic, given that libp2p protocols running on top +of transport protocols, like WebRTC, expect to be able to half-close or reset a +stream. See [Connection Establishment in +libp2p](https://github.com/libp2p/specs/blob/master/connections/README.md#definitions). + +To support half-closing and resets of streams, libp2p WebRTC uses message +framing. Messages on a `RTCDataChannel` are embedded into the Protobuf message +below and send on the `RTCDataChannel` prefixed with the message length in +bytes, encoded as an unsigned variable length integer as defined by the +[multiformats unsigned-varint spec][uvarint-spec]. + +``` proto +syntax = "proto2"; + +package webrtc.pb; + +message Message { + enum Flag { + // The local endpoint will no longer send messages. + CLOSE_WRITE = 0; + // The local endpoint will no longer read messages. + CLOSE_READ = 1; + // The local endpoint abruptly terminates the stream. The remote endpoint + // may discard any in-flight data. + RESET = 2; + } + + optional Flag flag=1; + + optional bytes message = 2; +} +``` + +Encoded messages including their length prefix MUST NOT exceed 16kiB to support +all major browsers. See ["Understanding message size +limits"](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_data_channels#understanding_message_size_limits). +Implementations MAY choose to send smaller messages, e.g. to reduce delays +sending _flagged_ messages. ## General Open Questions @@ -339,3 +370,16 @@ After [Connection Security](#connection-security): the signature (`signature_libp2p_a(fingerprint_a, fingerprint_b, connection_identifier)`) would protect against this attack. To the best of our knowledge the browser does not give us access to such identifier. + +- _Why use Protobuf for WebRTC message framing. Why not use our own, + potentially smaller encoding schema?_ + + The Protobuf framing adds an overhead of 5 bytes. The unsigned-varint prefix + adds another 2 bytes. On a large message the overhead is negligible (`(5 + bytes + 2 bytes) / (16384 bytes - 7 bytes) = 0.000427246`). On a small + message, e.g. a multistream-select message with ~40 bytes the overhead is high + (`(5 bytes + 2 bytes) / 40 bytes = 0.175`) but likely irrelevant. + + Using Protobuf allows us to evolve the protocol in a backwards compatibile way + going forward. Using Protobuf is consisten with the many other libp2p + protocols. These benefits outweigh the drawback of additional overhead. From 7009f943d5b9ee67cb7a19bbf8ca60549c1ad683 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 19 Aug 2022 11:39:21 +0900 Subject: [PATCH 046/128] webrtc/: Specify sha256 and base64url --- webrtc/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 4b1a33370..3fffbed2f 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -62,6 +62,12 @@ The TLS certificate fingerprint in `/certhash` is a [multibase](https://github.com/multiformats/multibase) encoded [multihash](https://github.com/multiformats/multihash). +For compatibility implementations MUST support hash algorithm +[`sha-256`](https://github.com/multiformats/multihash) and base encoding +[`base64url`](https://github.com/multiformats/multibase). Implementations MAY +support other hash algorithms and base encodings, but they may not be able to +connect to all other nodes. + ## Connection Establishment ### Browser to public Server From 373bafe204f94b1bfcc338fbe670680b5e19d9db Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 22 Aug 2022 17:55:05 +0900 Subject: [PATCH 047/128] webrtc/: Reword protobuf comment from local endpoint to sender --- webrtc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index b866298a4..c0c00166f 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -286,9 +286,9 @@ package webrtc.pb; message Message { enum Flag { - // The local endpoint will no longer send messages. + // The sender will no longer send messages. CLOSE_WRITE = 0; - // The local endpoint will no longer read messages. + // The sender will no longer read messages. CLOSE_READ = 1; // The local endpoint abruptly terminates the stream. The remote endpoint // may discard any in-flight data. From 93df7e397e7ba79962ed7bdfbf6d4da40985011c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 5 Sep 2022 10:59:00 +0900 Subject: [PATCH 048/128] webrtc/: Adapt enum variants to QUIC RFC --- webrtc/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c0c00166f..930400c14 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -287,9 +287,10 @@ package webrtc.pb; message Message { enum Flag { // The sender will no longer send messages. - CLOSE_WRITE = 0; - // The sender will no longer read messages. - CLOSE_READ = 1; + FIN = 0; + // The sender will no longer read messages. Incoming data is being + // discarded on receipt. + STOP_SENDING = 1; // The local endpoint abruptly terminates the stream. The remote endpoint // may discard any in-flight data. RESET = 2; From 027b539c3292d0d2bec2b04307a484d940d6b255 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 5 Sep 2022 10:59:32 +0900 Subject: [PATCH 049/128] webrtc/: Link QUIC RFC as reference --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 930400c14..848e89ba8 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -302,6 +302,9 @@ message Message { } ``` +The above is adapted from the [QUIC RFC]. When in doubt on the semantics of +these messages, consult the [QUIC RFC]. + Encoded messages including their length prefix MUST NOT exceed 16kiB to support all major browsers. See ["Understanding message size limits"](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_data_channels#understanding_message_size_limits). @@ -384,3 +387,5 @@ sending _flagged_ messages. Using Protobuf allows us to evolve the protocol in a backwards compatibile way going forward. Using Protobuf is consisten with the many other libp2p protocols. These benefits outweigh the drawback of additional overhead. + +[QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html From 865f4f2dea8872c8de301a16b59000ac4540f18d Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 5 Sep 2022 11:07:43 +0900 Subject: [PATCH 050/128] webrtc/: Redefine RESET semantics Instead of resetting both ends of a stream, RESET only resets the sending side of a stream. This is in line with the QUIC stream reset mechanism. --- webrtc/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 848e89ba8..5be597bdf 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -286,13 +286,13 @@ package webrtc.pb; message Message { enum Flag { - // The sender will no longer send messages. + // The sender will no longer send messages on the stream. FIN = 0; - // The sender will no longer read messages. Incoming data is being - // discarded on receipt. + // The sender will no longer read messages on the stream. Incoming data is + // being discarded on receipt. STOP_SENDING = 1; - // The local endpoint abruptly terminates the stream. The remote endpoint - // may discard any in-flight data. + // The sender abruptly terminates the sending part of the stream. The + // receiver can discard any data that it already received on that stream. RESET = 2; } From a60234cfb44fe060c8448d0de6e91958a57fedbc Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 5 Sep 2022 11:19:39 +0900 Subject: [PATCH 051/128] webrtc/: Rephrase missing mechanism in browser webrtc api --- webrtc/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 5be597bdf..e5d24d3e1 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -264,7 +264,8 @@ be the same. On mismatch the final Noise handshake MUST fail. Following [Connection Security](#connection-security). -The WebRTC browser APIs do not support half-closing nor resets of streams. +The WebRTC browser APIs do not support half-closing of streams nor resets of the +sending part of streams. [`RTCDataChannel.close()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close) flushes the remaining messages and closes the local write and read side. After calling `RTCDataChannel.close()` one can no longer read from the channel. This From 48f5fe767c73cebd0d751de87d8fe7a697db1884 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 8 Sep 2022 13:32:13 +0900 Subject: [PATCH 052/128] webrtc/: Add note on stream ordering --- webrtc/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 3fffbed2f..05ac09cc3 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -23,13 +23,14 @@ Interest Group: [@marten-seemann] - [Connection Security](#connection-security) - [Open Questions](#open-questions-2) - [Multiplexing](#multiplexing) + - [Ordering](#ordering) + - [Open Questions](#open-questions-3) - [General Open Questions](#general-open-questions) - [Previous, ongoing and related work](#previous-ongoing-and-related-work) - [FAQ](#faq) - ## Motivation 1. **No need for trusted TLS certificates.** Enable browsers to connect to @@ -272,6 +273,13 @@ After [Connection Security](#connection-security): closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. +### Ordering + +As of writing this specification, libp2p supports ordered streams only. +Implementations MUST NOT change the default value of `ordered` `true` when +creating a new data channel via +[`RTCPeerConnection.createDataChannel`](https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel). + ### Open Questions - Can we use WebRTC’s data channels in _Browser_ to multiplex a single From 7f404912eae8cf5beda3c50f4fdcb92afbf365ac Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 10 Sep 2022 11:13:30 +0200 Subject: [PATCH 053/128] Apply suggestions from code review Co-authored-by: Thomas Eizinger --- webrtc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index e5d24d3e1..e83e22f92 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -276,7 +276,7 @@ libp2p](https://github.com/libp2p/specs/blob/master/connections/README.md#defini To support half-closing and resets of streams, libp2p WebRTC uses message framing. Messages on a `RTCDataChannel` are embedded into the Protobuf message -below and send on the `RTCDataChannel` prefixed with the message length in +below and sent on the `RTCDataChannel` prefixed with the message length in bytes, encoded as an unsigned variable length integer as defined by the [multiformats unsigned-varint spec][uvarint-spec]. @@ -386,7 +386,7 @@ sending _flagged_ messages. (`(5 bytes + 2 bytes) / 40 bytes = 0.175`) but likely irrelevant. Using Protobuf allows us to evolve the protocol in a backwards compatibile way - going forward. Using Protobuf is consisten with the many other libp2p + going forward. Using Protobuf is consistent with the many other libp2p protocols. These benefits outweigh the drawback of additional overhead. [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html From 31ac65d6a78f621babd8d6c2845881b1128db4ad Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 10 Sep 2022 18:25:22 +0900 Subject: [PATCH 054/128] webrtc/: Require RESET after STOP_SENDING --- webrtc/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index e83e22f92..77bf0ad02 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -280,6 +280,9 @@ below and sent on the `RTCDataChannel` prefixed with the message length in bytes, encoded as an unsigned variable length integer as defined by the [multiformats unsigned-varint spec][uvarint-spec]. +It is an adaptation from the [QUIC RFC]. When in doubt on the semantics of +these messages, consult the [QUIC RFC]. + ``` proto syntax = "proto2"; @@ -303,8 +306,9 @@ message Message { } ``` -The above is adapted from the [QUIC RFC]. When in doubt on the semantics of -these messages, consult the [QUIC RFC]. +Note that "a STOP_SENDING frame requests that the receiving endpoint send a +RESET_STREAM frame.". See [QUIC RFC - 3.5 Solicited State +Transitions](https://www.rfc-editor.org/rfc/rfc9000.html#section-3.5). Encoded messages including their length prefix MUST NOT exceed 16kiB to support all major browsers. See ["Understanding message size From 85364f44d5b6d0461892ebcb2e5f2d13afe2df28 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 10 Sep 2022 18:27:37 +0900 Subject: [PATCH 055/128] webrtc/: Rename RESET to RESET_STREAM For the sake of consistency with the QUIC RFC, rename RESET to RESET_STREAM. --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 77bf0ad02..4281ebfc8 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -297,7 +297,7 @@ message Message { STOP_SENDING = 1; // The sender abruptly terminates the sending part of the stream. The // receiver can discard any data that it already received on that stream. - RESET = 2; + RESET_STREAM = 2; } optional Flag flag=1; From 9ce0d45e54f7e67a6ed4489901c8437a83687590 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 10 Sep 2022 18:51:19 +0900 Subject: [PATCH 056/128] webrtc/: Allow overriding ordering on a data channel --- webrtc/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 05ac09cc3..a020121e6 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -275,9 +275,9 @@ After [Connection Security](#connection-security): ### Ordering -As of writing this specification, libp2p supports ordered streams only. -Implementations MUST NOT change the default value of `ordered` `true` when -creating a new data channel via +Implementations MAY expose an unordered byte stream abstraction to the user by +overriding the default value of `ordered` `true` to `false` when creating a new +data channel via [`RTCPeerConnection.createDataChannel`](https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel). ### Open Questions From 7a8ebc03c1b514922adfbec6e6ac756c0c892599 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 11 Sep 2022 18:00:31 +0900 Subject: [PATCH 057/128] webrtc/: Use message framing for Noise handshake already Instead of executing the additional Noise handshake on a plain `RTCDataChannel`, frame the Noise messages with the proposed message framing mechanism already. Benefits: - The additional Noise handshake can already make use of the proper closing mechanism. Note that `RTCDataChannel.close` may drop any in-flight data. See https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close. - Simplifies implementations as there is only one way to write on an `RTCDataChannel`. - Allows us to role out new versions of the Noise handshake in the future by adding a version to the message framing Protobuf. --- webrtc/README.md | 127 ++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c592ef766..2b18bcbd9 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -20,10 +20,10 @@ Interest Group: [@marten-seemann] - [Open Questions](#open-questions) - [Browser to Browser](#browser-to-browser) - [Open Questions](#open-questions-1) - - [Connection Security](#connection-security) - - [Open Questions](#open-questions-2) - [Multiplexing](#multiplexing) - [Ordering](#ordering) + - [Connection Security](#connection-security) + - [Open Questions](#open-questions-2) - [General Open Questions](#general-open-questions) - [Previous, ongoing and related work](#previous-ongoing-and-related-work) - [FAQ](#faq) @@ -116,9 +116,11 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). fingerprint through the WebRTC DTLS handshake. At this point the DTLS handshake provides confidentiality and integrity but not authenticity. -7. See [Connection Security](#connection-security). +7. Messages on an `RTCDataChannel` are framed using the message framing + mechanism described in [Multiplexing](#multiplexing). -8. See [Multiplexing](#multiplexing). +7. The remote is authenticated via an additional Noise handshake. See + [Connection Security](#connection-security). #### Open Questions @@ -210,66 +212,8 @@ server node _R_. could they exchange their multiaddr and construct the remote's SDP packet based on it? -## Connection Security - -While WebRTC offers confidentiality and integrity via TLS, one still needs to -authenticate the remote peer by its libp2p identity. - -After [Connection Establishment](#connection-establishment): - -1. _A_ opens a WebRTC datachannel. - -2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity. See - [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). - - Instead of exchanging the TLS certificate fingerprints on the established - Noise channel once the Noise handshake succeeded, _A_ and _B_ use the [Noise - Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism, thus - saving one round trip. - - More specifically _A_ and _B_ set the Noise _Prologue_ to - `libp2p-webrtc-noise:` before starting the actual Noise - handshake. `` is the concatenation of the of the two TLS - fingerprints of _A_ and _B_ in their multihash byte representation, sorted in - ascending order. - -3. On success of the authentication handshake, the used datachannel is - closed and the plain WebRTC connection is used with its multiplexing - capabilities via datachannels. See [Multiplexing](#multiplexing). - -Note: WebRTC supports different hash functions to hash the TLS certificate (see -https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used -in WebRTC and the hash function used in the multiaddr `/certhash` component MUST -be the same. On mismatch the final Noise handshake MUST fail. - -### Open Questions - -- Can a _Browser_ access the fingerprint of its TLS certificate? - - Chrome allows you to access the fingerprint of any locally-created certificate - directly via `RTCCertificate#getFingerprints`. Firefox does not allow you to - do so. Browser compatibility can be found - [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In - practice, this is not an issue since the fingerprint is embedded in the local - SDP string. - -- Is the above proposed additional handshake secure? See also alternative - proposed Handshake for - [WebTransport](https://github.com/libp2p/specs/pull/404). - -- Would it be more efficient for _B_ to initiate the Noise handshake? In other - words, who is able to write on an established WebRTC connection first? _A_ or - _B_? - -- On the server side, can one derive the TLS certificate in a deterministic way - based on a node's libp2p private key? Benefit would be that a node only needs - to persist the libp2p private key and not the TLS key material while still - maintaining a fixed TLS certificate fingerprint. - ## Multiplexing -Following [Connection Security](#connection-security). - The WebRTC browser APIs do not support half-closing of streams nor resets of the sending part of streams. [`RTCDataChannel.close()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close) @@ -329,6 +273,65 @@ overriding the default value of `ordered` `true` to `false` when creating a new data channel via [`RTCPeerConnection.createDataChannel`](https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel). +## Connection Security + +Note that the below uses the message framing described in +[multiplexing](#multiplexing). + +While WebRTC offers confidentiality and integrity via TLS, one still needs to +authenticate the remote peer by its libp2p identity. + +After [Connection Establishment](#connection-establishment): + +1. _A_ opens a WebRTC datachannel. + +2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity. See + [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). + + Instead of exchanging the TLS certificate fingerprints on the established + Noise channel once the Noise handshake succeeded, _A_ and _B_ use the [Noise + Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism, thus + saving one round trip. + + More specifically _A_ and _B_ set the Noise _Prologue_ to + `libp2p-webrtc-noise:` before starting the actual Noise + handshake. `` is the concatenation of the of the two TLS + fingerprints of _A_ and _B_ in their multihash byte representation, sorted in + ascending order. + +3. On success of the authentication handshake, the used datachannel is + closed and the plain WebRTC connection is used with its multiplexing + capabilities via datachannels. See [Multiplexing](#multiplexing). + +Note: WebRTC supports different hash functions to hash the TLS certificate (see +https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used +in WebRTC and the hash function used in the multiaddr `/certhash` component MUST +be the same. On mismatch the final Noise handshake MUST fail. + +### Open Questions + +- Can a _Browser_ access the fingerprint of its TLS certificate? + + Chrome allows you to access the fingerprint of any locally-created certificate + directly via `RTCCertificate#getFingerprints`. Firefox does not allow you to + do so. Browser compatibility can be found + [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In + practice, this is not an issue since the fingerprint is embedded in the local + SDP string. + +- Is the above proposed additional handshake secure? See also alternative + proposed Handshake for + [WebTransport](https://github.com/libp2p/specs/pull/404). + +- Would it be more efficient for _B_ to initiate the Noise handshake? In other + words, who is able to write on an established WebRTC connection first? _A_ or + _B_? + +- On the server side, can one derive the TLS certificate in a deterministic way + based on a node's libp2p private key? Benefit would be that a node only needs + to persist the libp2p private key and not the TLS key material while still + maintaining a fixed TLS certificate fingerprint. + ## General Open Questions - Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC From f0acbb58302453e16df14cef84ccad23f18a307e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 13 Sep 2022 05:17:34 +0200 Subject: [PATCH 058/128] Update webrtc/README.md Co-authored-by: Thomas Eizinger --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 2b18bcbd9..f508ec589 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -119,7 +119,7 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). 7. Messages on an `RTCDataChannel` are framed using the message framing mechanism described in [Multiplexing](#multiplexing). -7. The remote is authenticated via an additional Noise handshake. See +8. The remote is authenticated via an additional Noise handshake. See [Connection Security](#connection-security). #### Open Questions From c19ba8af265da7b09895e93d2f23ab95c4772fca Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 16 Sep 2022 13:22:22 +0200 Subject: [PATCH 059/128] webrtc/README.md: Fix typo Co-authored-by: Thomas Eizinger --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index f508ec589..a6f537f08 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -295,7 +295,7 @@ After [Connection Establishment](#connection-establishment): More specifically _A_ and _B_ set the Noise _Prologue_ to `libp2p-webrtc-noise:` before starting the actual Noise - handshake. `` is the concatenation of the of the two TLS + handshake. `` is the concatenation of the two TLS fingerprints of _A_ and _B_ in their multihash byte representation, sorted in ascending order. From 65a894a0d2c57b37f639f4d68ae28d9ea03be481 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 22 Sep 2022 17:52:13 +0100 Subject: [PATCH 060/128] webrtc/: Don't require STREAM_RESET in response to STOP_SENDING See https://github.com/mxinden/specs/pull/1#issuecomment-1254770914. --- webrtc/README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index a6f537f08..1fdcaa4b2 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -256,9 +256,14 @@ message Message { } ``` -Note that "a STOP_SENDING frame requests that the receiving endpoint send a -RESET_STREAM frame.". See [QUIC RFC - 3.5 Solicited State -Transitions](https://www.rfc-editor.org/rfc/rfc9000.html#section-3.5). +Note that in contrast to QUIC (see [QUIC RFC - 3.5 Solicited State +Transitions](https://www.rfc-editor.org/rfc/rfc9000.html#section-3.5)) a libp2p +WebRTC endpoint receiving a `STOP_SENDING` frame SHOULD NOT send a +`RESET_STREAM` frame in reply. The `STOP_SENDING` frame is used for accurate +accounting of the number of bytes sent for connection-level flow control in +QUIC. The libp2p WebRTC message framing is not concerned with flow-control and +thus does not need the `RESET_STREAM` frame to be send in reply to a +`STOP_SENDING` frame. Encoded messages including their length prefix MUST NOT exceed 16kiB to support all major browsers. See ["Understanding message size From 6fb27507d06d66aeefabacaf8329b8f63c6b5ed8 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 23 Sep 2022 20:53:06 +1000 Subject: [PATCH 061/128] Add initial test vector for noise prologue --- webrtc/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index a6f537f08..5291d91ca 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -308,6 +308,27 @@ https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used in WebRTC and the hash function used in the multiaddr `/certhash` component MUST be the same. On mismatch the final Noise handshake MUST fail. +## Test vectors + +### Noise prologue + +#### 1. Both client and server use SHA-256 + +``` +client_fingerprint = "3e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" +server_fingerprint = "30fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b99" + +prologue = "6c69627032702d7765627274632d6e6f6973653a122030fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b9912203e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" +``` + +Flipped version (testing the sorting requirement): +``` +client_fingerprint = "30fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b99" +server_fingerprint = "3e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" + +prologue = "6c69627032702d7765627274632d6e6f6973653a122030fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b9912203e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" +``` + ### Open Questions - Can a _Browser_ access the fingerprint of its TLS certificate? From 73516b1d5af91cec4699478acc52e5faf5edc1de Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 23 Sep 2022 20:56:01 +1000 Subject: [PATCH 062/128] Add note about encoding --- webrtc/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 5291d91ca..2fda44e7a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -312,6 +312,8 @@ be the same. On mismatch the final Noise handshake MUST fail. ### Noise prologue +All of these test vectors represent hex-encoded bytes. + #### 1. Both client and server use SHA-256 ``` From 8208f02e5a2cc8a2b1f21715b5a7da44d773dc13 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 13:36:22 +0100 Subject: [PATCH 063/128] webrtc/: Document option for not using trickle ICE --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 1fdcaa4b2..44e25873f 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -212,6 +212,11 @@ server node _R_. could they exchange their multiaddr and construct the remote's SDP packet based on it? +- Instead of using trickle ICE, we could as well wait for the candidate + gathering. See + https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/examples/insertable-streams/main.go#L141-L142 + as one example. + ## Multiplexing The WebRTC browser APIs do not support half-closing of streams nor resets of the From 6c7f18e7cf44212d963fc5fb504df01f711220d3 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 13:40:16 +0100 Subject: [PATCH 064/128] webrtc/: Mention icegatheringstatechange event on the browser --- webrtc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 44e25873f..07696a5bd 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -215,7 +215,9 @@ server node _R_. - Instead of using trickle ICE, we could as well wait for the candidate gathering. See https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/examples/insertable-streams/main.go#L141-L142 - as one example. + as one example. In the browser, one can wait for the + [`icegatheringstatechange` + event](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icegatheringstatechange_event). ## Multiplexing From 666c9f4bbef9aac757f7ee9d8526301b630140a0 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 15:14:59 +0100 Subject: [PATCH 065/128] webrtc/: Use id 0 and negotiated true for Noise channel --- webrtc/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 07696a5bd..5c2557d55 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -295,9 +295,12 @@ authenticate the remote peer by its libp2p identity. After [Connection Establishment](#connection-establishment): -1. _A_ opens a WebRTC datachannel. +1. _A_ and _B_ open a WebRTC data channel with `id: 0` and `negotiated: true` + ([`pc.createDataChannel("", {negotiated: true, id: + 0});`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel)). -2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity. See +2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity on + the new channel. See [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). Instead of exchanging the TLS certificate fingerprints on the established From ae5b0d8c01b842f3ba2844b7d62b3f26b57bfde2 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 15:15:29 +0100 Subject: [PATCH 066/128] webrtc/: Document allowing streams before Noise finished --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 5c2557d55..8d095c8dd 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -323,6 +323,11 @@ https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used in WebRTC and the hash function used in the multiaddr `/certhash` component MUST be the same. On mismatch the final Noise handshake MUST fail. +Implementations MAY open streams before completion of the Noise handshake. +Applications MUST take special care what application data they send, since at +this point the peer is not yet authenticated. Similarly, the receiving side MAY +accept streams before completion of the handshake. + ### Open Questions - Can a _Browser_ access the fingerprint of its TLS certificate? From 7ce6213ee0998660032b853d7c64f3a3dae312b7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 15:37:04 +0100 Subject: [PATCH 067/128] webrtc/: Use IP + port + ufrag for multiplexing --- webrtc/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 8d095c8dd..158683316 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -106,10 +106,10 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). https://bugs.chromium.org/p/chromium/issues/detail?id=823036 5. _A_ establishes the connection to _B_. The random string used as a _username_ - and _password_ can be used by _B_ to identify the connection, i.e. - demultiplex incoming UDP datagrams per incoming connection. _B_ uses the same - random string for the username and password in the STUN message from _B_ to - _A_. + and _password_ in combination with the IP and port of _A_ can be used by _B_ + to identify the connection, i.e. demultiplex incoming UDP datagrams per + incoming connection. _B_ uses the same random string for the username and + password in the STUN message from _B_ to _A_. 6. _B_ does not know the TLS fingerprint of _A_. _B_ upgrades the incoming connection from _A_ as an _insecure_ connection, learning _A_'s TLS From a2d1547d880214a96ea0d659f51a8582767394e1 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sun, 25 Sep 2022 15:42:57 +0100 Subject: [PATCH 068/128] webrtc/: Remove open question on SDP munging --- webrtc/README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 158683316..ff0c0e93c 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -166,15 +166,6 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). WebRTC connection from a remote node without previously receiving an SDP packet from such host? -- Can _Browser_ generate a _valid_ SDP packet for the remote node based on the - remote's Multiaddr, where that Multiaddr contains the IP, UDP port and TLS - certificate fingerprint (e.g. - `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`)? _Valid_ in - the sense that this generated SDP packet can then be used to establish a - WebRTC connection to the remote. - - Yes. - ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of From ded63c59fddca87f5192a42a8ca023033aa1f400 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 12:28:55 +0100 Subject: [PATCH 069/128] webrtc/: Reword certificate verification section --- webrtc/README.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index ff0c0e93c..be1223c55 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -111,13 +111,21 @@ fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). incoming connection. _B_ uses the same random string for the username and password in the STUN message from _B_ to _A_. -6. _B_ does not know the TLS fingerprint of _A_. _B_ upgrades the incoming - connection from _A_ as an _insecure_ connection, learning _A_'s TLS - fingerprint through the WebRTC DTLS handshake. At this point the DTLS - handshake provides confidentiality and integrity but not authenticity. +6. _A_ and _B_ execute the DTLS handshake as part of the standard WebRTC + connection establishment. -7. Messages on an `RTCDataChannel` are framed using the message framing - mechanism described in [Multiplexing](#multiplexing). + At this point _B_ does not know the TLS certificate fingerprint of _A_. Thus + _B_ can not verify _A_'s TLS certificate fingerprint during the DTLS + handshake. Instead _B_ needs to _disable certificate fingerprint + verification_ (see e.g. [Pion's `disableCertificateFingerprintVerification` + option](https://github.com/pion/webrtc/blob/360b0f1745c7244850ed638f423cda716a81cedf/settingengine.go#L62)). + + On success of the DTLS handshake the connection provides confidentiality and + integrity but not authenticity. The latter is guaranteed through the + succeeding Noise handshake. + +7. Messages on the established `RTCDataChannel` are framed using the message + framing mechanism described in [Multiplexing](#multiplexing). 8. The remote is authenticated via an additional Noise handshake. See [Connection Security](#connection-security). From 54f82644c450a69b77cf4b7f6a8b179d5bc9166b Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 16:30:25 +0100 Subject: [PATCH 070/128] webrtc/: Recommend against reusing the TLS certificate --- webrtc/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index be1223c55..5b1434c98 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -75,20 +75,20 @@ connect to all other nodes. Scenario: Browser _A_ wants to connect to server node _B_ where _B_ is publicly reachable but _B_ does not have a TLS certificate trusted by _A_. -As a preparation browser _A_ [generates a -certificate](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-generatecertificate) -and [gets the certificate's -fingerprint](https://www.w3.org/TR/webrtc/#dom-rtccertificate-getfingerprints). - 1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and libp2p peer ID (e.g. `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), through some external mechanism. -2. _A_ instantiates a `RTCPeerConnection`, passing its local certificate as a - parameter. See +2. _A_ instantiates a `RTCPeerConnection`. See [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). + _A_ MAY reuse the same certificate across `RTCPeerConnection`s. Though one + should note that reusing the certificate can be used to identify _A_ across + connections by on-path observers given that WebRTC uses TLS 1.2. Thus this + specification RECOMMENDS that _A_, i.e. the browser, does not reuse the same + certificate across `RTCPeerConnection`. + 3. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). From 67e12daf61132fb56705f35ebd0104722d70c782 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 16:49:31 +0100 Subject: [PATCH 071/128] webrtc/: Document B listening via UDP socket --- webrtc/README.md | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 5b1434c98..a31d4e9d9 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -75,12 +75,21 @@ connect to all other nodes. Scenario: Browser _A_ wants to connect to server node _B_ where _B_ is publicly reachable but _B_ does not have a TLS certificate trusted by _A_. -1. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP +1. Server node _B_ generates a TLS certificate, listens on a UDP port and + advertises the corresponding multiaddress (see [#Addressing]) through some + external mechanism. + + Given that _B_ is publicly reachable, _B_ acts as a [ICE + Lite](https://www.rfc-editor.org/rfc/rfc5245) agent. It listens on a UDP port + for incoming STUN and SCTP packets and multiplexes based on source IP and + source port. + +2. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and libp2p peer ID (e.g. `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), through some external mechanism. -2. _A_ instantiates a `RTCPeerConnection`. See +3. _A_ instantiates a `RTCPeerConnection`. See [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). _A_ MAY reuse the same certificate across `RTCPeerConnection`s. Though one @@ -89,11 +98,11 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. specification RECOMMENDS that _A_, i.e. the browser, does not reuse the same certificate across `RTCPeerConnection`. -3. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it +4. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). -4. _A_ creates a local offer via +5. _A_ creates a local offer via [`RTCPeerConnection.createOffer()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer). _A_ generates a random string and sets that string as the username (_ufrag_ or _username fragment_) and password on the SDP of the local offer. Finally @@ -105,13 +114,13 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. Firefox, Chrome) due to use-cases in the wild. See also https://bugs.chromium.org/p/chromium/issues/detail?id=823036 -5. _A_ establishes the connection to _B_. The random string used as a _username_ +6. _A_ establishes the connection to _B_. The random string used as a _username_ and _password_ in combination with the IP and port of _A_ can be used by _B_ to identify the connection, i.e. demultiplex incoming UDP datagrams per incoming connection. _B_ uses the same random string for the username and password in the STUN message from _B_ to _A_. -6. _A_ and _B_ execute the DTLS handshake as part of the standard WebRTC +7. _A_ and _B_ execute the DTLS handshake as part of the standard WebRTC connection establishment. At this point _B_ does not know the TLS certificate fingerprint of _A_. Thus @@ -124,10 +133,10 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. integrity but not authenticity. The latter is guaranteed through the succeeding Noise handshake. -7. Messages on the established `RTCDataChannel` are framed using the message +8. Messages on the established `RTCDataChannel` are framed using the message framing mechanism described in [Multiplexing](#multiplexing). -8. The remote is authenticated via an additional Noise handshake. See +9. The remote is authenticated via an additional Noise handshake. See [Connection Security](#connection-security). #### Open Questions @@ -158,18 +167,6 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. - https://datatracker.ietf.org/doc/html/rfc5389#section-16.2.1 - https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2 -- Do the major WebRTC server implementations support using the same UDP port for - multiple WebRTC connections, thus requiring multiplexing multiple WebRTC - connections on the same UDP port? - - This is related to [ICE Lite](https://www.rfc-editor.org/rfc/rfc5245), having - a host only advertise a single address, namely the host address, which is - assumed to be public. - - The [Go WebRTC](https://github.com/pion/webrtc/) implementation and the [Rust - WebRTC](https://github.com/webrtc-rs/webrtc) implementation support this. It - is unclear whether this is supported in any of the NodeJS implementations. - - Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a WebRTC connection from a remote node without previously receiving an SDP packet from such host? From 4a52edcc48124f3982198910e61ee565ad61306e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 16:53:13 +0100 Subject: [PATCH 072/128] webrtc/: Add uvarint link --- webrtc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/webrtc/README.md b/webrtc/README.md index a31d4e9d9..b8b6352d4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -426,3 +426,4 @@ accept streams before completion of the handshake. protocols. These benefits outweigh the drawback of additional overhead. [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html +[uvarint-spec]: https://github.com/multiformats/unsigned-varint From 73804831b72d611b955cf20bd4a7aa85bccba9fa Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 16:58:22 +0100 Subject: [PATCH 073/128] webrtc/: Remove mention of saved round trip --- webrtc/README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index b8b6352d4..2544ce147 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -299,16 +299,13 @@ After [Connection Establishment](#connection-establishment): the new channel. See [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). - Instead of exchanging the TLS certificate fingerprints on the established - Noise channel once the Noise handshake succeeded, _A_ and _B_ use the [Noise - Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism, thus - saving one round trip. - - More specifically _A_ and _B_ set the Noise _Prologue_ to + _A_ and _B_ use the [Noise + Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism. More + specifically _A_ and _B_ set the Noise _Prologue_ to `libp2p-webrtc-noise:` before starting the actual Noise - handshake. `` is the concatenation of the two TLS - fingerprints of _A_ and _B_ in their multihash byte representation, sorted in - ascending order. + handshake. `` is the concatenation of the two TLS fingerprints + of _A_ and _B_ in their multihash byte representation, sorted in ascending + order. 3. On success of the authentication handshake, the used datachannel is closed and the plain WebRTC connection is used with its multiplexing From c063a81212addb78d479c15d1abb2d7e77beae9e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 17:03:42 +0100 Subject: [PATCH 074/128] webrtc/: Move fingerprint extraction to statement instead of question --- webrtc/README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 2544ce147..18d95e732 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -307,6 +307,13 @@ After [Connection Establishment](#connection-establishment): of _A_ and _B_ in their multihash byte representation, sorted in ascending order. + On Chrome _A_ can access its TLS certificate fingerprint directly via + `RTCCertificate#getFingerprints`. Firefox does not allow _A_ to do so. Browser + compatibility can be found + [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In + practice, this is not an issue since the fingerprint is embedded in the local + SDP string. + 3. On success of the authentication handshake, the used datachannel is closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. See [Multiplexing](#multiplexing). @@ -323,15 +330,6 @@ accept streams before completion of the handshake. ### Open Questions -- Can a _Browser_ access the fingerprint of its TLS certificate? - - Chrome allows you to access the fingerprint of any locally-created certificate - directly via `RTCCertificate#getFingerprints`. Firefox does not allow you to - do so. Browser compatibility can be found - [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In - practice, this is not an issue since the fingerprint is embedded in the local - SDP string. - - Is the above proposed additional handshake secure? See also alternative proposed Handshake for [WebTransport](https://github.com/libp2p/specs/pull/404). From 65590f97d867f40efc57396f345b2763a07895c8 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 17:05:31 +0100 Subject: [PATCH 075/128] webrtc/: Remove obsolete question on preceeding SDP packet --- webrtc/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 18d95e732..62b6be407 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -167,10 +167,6 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. - https://datatracker.ietf.org/doc/html/rfc5389#section-16.2.1 - https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2 -- Do the major (Go / Rust / ...) WebRTC implementations allow us to accept a - WebRTC connection from a remote node without previously receiving an SDP - packet from such host? - ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of From 8dc6465561897beee32ad18c561525235ad17778 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 17:06:51 +0100 Subject: [PATCH 076/128] webrtc/: Remove open question on handshake security --- webrtc/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 62b6be407..f50c40063 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -326,10 +326,6 @@ accept streams before completion of the handshake. ### Open Questions -- Is the above proposed additional handshake secure? See also alternative - proposed Handshake for - [WebTransport](https://github.com/libp2p/specs/pull/404). - - Would it be more efficient for _B_ to initiate the Noise handshake? In other words, who is able to write on an established WebRTC connection first? _A_ or _B_? From daecb5bc7001b2488ab5d2bf4353f4ff59de0ffb Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 17:09:54 +0100 Subject: [PATCH 077/128] README.md: Link to WebRTC specification --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cd0e93191..5a7e939a2 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ The protocols described below all use [protocol buffers](https://developers.goog peer discovery - [secio][spec_secio] - SECIO, a transport security protocol for libp2p - [tls][spec_tls] - The libp2p TLS Handshake (TLS 1.3+) +- [webrtc][spec_webrtc] - The libp2p WebRTC transport ## Contributions @@ -119,3 +120,4 @@ you feel an issue isn't the appropriate place for your topic, please join our [spec_connections]: ./connections/README.md [spec_plaintext]: ./plaintext/README.md [spec_addressing]: ./addressing/README.md +[spec_webrtc]: ./webrtc/README.md From 590c3dbb696dd6d927601a66f153654231ad62b2 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 28 Sep 2022 17:13:25 +0100 Subject: [PATCH 078/128] connections/hole-punching: Link to WebRTC specification --- connections/hole-punching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connections/hole-punching.md b/connections/hole-punching.md index f8898b9c7..44e08cff3 100644 --- a/connections/hole-punching.md +++ b/connections/hole-punching.md @@ -166,5 +166,5 @@ connections across the various permutations of the two dimensions. [ipfs-kademlia]: https://docs.ipfs.io/concepts/dht/ [Kademlia]: https://github.com/libp2p/specs/blob/master/kad-dht/README.md [Gossipsub]: ../pubsub/gossipsub/README.md -[WebRTC]: https://github.com/libp2p/specs/issues/220 +[WebRTC]: ../webrtc/README.md [WebTransport]: https://github.com/libp2p/specs/pull/404 From a207aa571702e687035dcf632f06507f205cc1d4 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 30 Sep 2022 17:03:40 +0100 Subject: [PATCH 079/128] webrtc/: Document open questions on data channel IDs --- webrtc/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index f50c40063..bc4d9f393 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -277,6 +277,29 @@ overriding the default value of `ordered` `true` to `false` when creating a new data channel via [`RTCPeerConnection.createDataChannel`](https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel). +### Open Questions + +- There are two ways to open a `RTCDataChannel`, either via `negotiated: true` + and thus out-of-band channel ID negotiation or `negotiated: false` and thus + in-band channel ID negotiation. + + Is the assumption correct that in-band stream ID negotiation requires an + additional round trip? If so how about using out-of-band channel id + negotiation only (thus no additional round trip) based on the DTLS role? + + > When one side wants to open a channel using out-of-band negotiation, it + > picks a stream. Unless otherwise defined or negotiated, the streams are + > picked based on the DTLS role (the client picks even stream identifiers, and + > the server picks odd stream identifiers). + + https://www.rfc-editor.org/rfc/rfc8831#name-opening-a-data-channel + +- Do browsers allow reuse of `RTCDataChannel` IDs? If so, should we allow libp2p + WebRTC implementations to reuse channel IDs of previously closed channels? + Motivation would be to have more than 2^16 channels throughout the lifetime of + a WebRTC connection. Note that this would still restrict a connection to at + most 2^16 concurrent channels. + ## Connection Security Note that the below uses the message framing described in From ed5c6413724afc9f017af34bc5c20e6363dd4f5c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 13:57:23 +0100 Subject: [PATCH 080/128] webrtc/: Document head-of-line blocking --- webrtc/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index bc4d9f393..11a0bc5eb 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -277,6 +277,23 @@ overriding the default value of `ordered` `true` to `false` when creating a new data channel via [`RTCPeerConnection.createDataChannel`](https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel). +### Head-of-line blocking + +WebRTC datachannels and the underlying SCTP is message-oriented and not +stream-oriented (e.g. see +[`RTCDataChannel.send()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/send) +and +[`RTCDataChannel.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel#example)). +libp2p streams on the other hand are byte oriented. Thus we run into the risk of +head-of-line blocking. + +Given that the browser does not give us access to the MTU on a given connection, +we can not make an informed decision on the optimal message size. For now +implementations SHOULD choose a small message size. See [QUIC's "Packet Size" +section](https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-29#section-14) +for recommendations. Long term we hope to be able to give better recommendations +based on real-world experiments. + ### Open Questions - There are two ways to open a `RTCDataChannel`, either via `negotiated: true` From 42e7a2083ec34d72fe0eb86503f9b72a1bca0658 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 14:24:40 +0100 Subject: [PATCH 081/128] webrtc/: Recommend concrete maximum message size --- webrtc/README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 11a0bc5eb..d8f2b1639 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -288,11 +288,15 @@ libp2p streams on the other hand are byte oriented. Thus we run into the risk of head-of-line blocking. Given that the browser does not give us access to the MTU on a given connection, -we can not make an informed decision on the optimal message size. For now -implementations SHOULD choose a small message size. See [QUIC's "Packet Size" -section](https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-29#section-14) -for recommendations. Long term we hope to be able to give better recommendations -based on real-world experiments. +we can not make an informed decision on the optimal message size. + +We follow the recommendation of QUIC, requiring ["a minimum IP packet size of at +least 1280 +bytes"](https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-29#section-14). +An SCTP packet common header is 12 bytes long. An SCTP data chunk header size is +16 bytes. Thus implementations SHOULD choose a message size equal or below 1252 +bytes. Long term we hope to be able to give better recommendations based on +real-world experiments. ### Open Questions From 3315b5c716d69e29c215a28343a5b4fbd21b9ea8 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 14:49:51 +0100 Subject: [PATCH 082/128] webrtc/: Document stream negotiation and ids --- webrtc/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index d8f2b1639..dbcb7db22 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -298,6 +298,27 @@ An SCTP packet common header is 12 bytes long. An SCTP data chunk header size is bytes. Long term we hope to be able to give better recommendations based on real-world experiments. +### `RTCDataChannel` negotiation + +`RTCDataChannel`s are negotiated out-of-band by setting `negotiated: true` when +creating a `RTCDataChannel` via `RTCPeerConnection.createDataChannel`. + +The 16-bit numeric `RTCDataChannel` `id` space is split between _A_ and _B_ as +recommended by the [WebRTC +RFC](https://www.rfc-editor.org/rfc/rfc8831#section-6.5): + +> the stream [ids] are picked based on the DTLS role (the client picks even +> stream identifiers, and the server picks odd stream identifiers). + +Note that `id` `0` is reserved for the additional connection security handshake. +See [Connection Security](#connection-security). + +Given the small `id` space, implementations SHOULD reuse `RTCDataChannel` `id`s +of previously closed `RTCDataChannel`s once they used up the maximum `id` +assigned to them (via their DTLS role). Thus instead of a maximum of `~2^16` +streams throughout the lifetime of a WebRTC connection, `~2^16` is the maximum +number of *concurrent* streams of a WebRTC connection. + ### Open Questions - There are two ways to open a `RTCDataChannel`, either via `negotiated: true` From 2dddfdc2792cbdabc95566bc195d3b576b4f2687 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 14:52:01 +0100 Subject: [PATCH 083/128] webrtc/: Remove open questions on data channel negotiation and ids --- webrtc/README.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index dbcb7db22..1de7fdc82 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -319,29 +319,6 @@ assigned to them (via their DTLS role). Thus instead of a maximum of `~2^16` streams throughout the lifetime of a WebRTC connection, `~2^16` is the maximum number of *concurrent* streams of a WebRTC connection. -### Open Questions - -- There are two ways to open a `RTCDataChannel`, either via `negotiated: true` - and thus out-of-band channel ID negotiation or `negotiated: false` and thus - in-band channel ID negotiation. - - Is the assumption correct that in-band stream ID negotiation requires an - additional round trip? If so how about using out-of-band channel id - negotiation only (thus no additional round trip) based on the DTLS role? - - > When one side wants to open a channel using out-of-band negotiation, it - > picks a stream. Unless otherwise defined or negotiated, the streams are - > picked based on the DTLS role (the client picks even stream identifiers, and - > the server picks odd stream identifiers). - - https://www.rfc-editor.org/rfc/rfc8831#name-opening-a-data-channel - -- Do browsers allow reuse of `RTCDataChannel` IDs? If so, should we allow libp2p - WebRTC implementations to reuse channel IDs of previously closed channels? - Motivation would be to have more than 2^16 channels throughout the lifetime of - a WebRTC connection. Note that this would still restrict a connection to at - most 2^16 concurrent channels. - ## Connection Security Note that the below uses the message framing described in From 0deaa30ab8b6457d0b6450e938f22a676142dd1f Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 15:23:52 +0100 Subject: [PATCH 084/128] webrtc/: Make certificate reuse a SHOULD NOT --- webrtc/README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 1de7fdc82..6f5610fb4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -92,11 +92,9 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 3. _A_ instantiates a `RTCPeerConnection`. See [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). - _A_ MAY reuse the same certificate across `RTCPeerConnection`s. Though one - should note that reusing the certificate can be used to identify _A_ across - connections by on-path observers given that WebRTC uses TLS 1.2. Thus this - specification RECOMMENDS that _A_, i.e. the browser, does not reuse the same - certificate across `RTCPeerConnection`. + _A_ (i.e. the browser) SHOULD NOT reuse the same certificate across + `RTCPeerConnection`s. Reusing the certificate can be used to identify _A_ + across connections by on-path observers given that WebRTC uses TLS 1.2. 4. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it via From 7ac21aa8031e57ecfd1e84591a2afc1497ca7430 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 15:26:16 +0100 Subject: [PATCH 085/128] webrtc/: Fix typo --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 6f5610fb4..6de630a77 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -44,7 +44,7 @@ Interest Group: [@marten-seemann] ## Requirements -- Loading a remote nodes certificate into ones browser trust-store is not an +- Loading a remote node's certificate into one's browser trust-store is not an option, i.e. doesn't scale. - No dependency on central STUN and/or TURN servers. From 88036826703881e4c6cf2ae4088a207e3f9fef48 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 5 Oct 2022 16:03:42 +0100 Subject: [PATCH 086/128] webrtc/: Draft the browser-to-browser section Note that this will only be fully specified in the second iteration of the libp2p WebRTC effort. --- webrtc/README.md | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 6de630a77..d263f5c52 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -170,16 +170,34 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of server node _R_. -- Replace STUN with libp2p's identify and AutoNAT - - https://github.com/libp2p/specs/tree/master/identify - - https://github.com/libp2p/specs/blob/master/autonat/README.md -- Replace TURN with libp2p's Circuit Relay v2 - - https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md -- Use DCUtR over Circuit Relay v2 to transmit SDP information - 1. Transform ICE candidates in SDP to multiaddresses. - 2. Transmit the set of multiaddresses to the remote via DCUtR. - 3. Transform the set of multiaddresses back to the remotes SDP. - 4. https://github.com/libp2p/specs/blob/master/relay/DCUtR.md +_Note that this section is a draft only for now, will be removed before merging +the first iteration of the specification (browser-to-server) and reintroduced in +the second iteration i.e. sufficiently specifying browser-to-server._ + +1. _B_ runs inside a browser and can thus not listen for incoming connections. + _B_ connects to a public server node _R_ and uses the Circuit Relay v2 + protocol to make a reservation. + +2. _B_ advertises its relayed address through some external mechanism. + +3. _A_ discovers _B_'s relayed address. _A_ connects to _R_ and establishes a + relayed connection to _B_ via the Circtui Relay v2 protocol. + +4. _A_ and _B_ both create a `RTCPeerConnection` and generate an _offer_ and an + _answer_ respectively. See `icegatheringstatechange` below on how these may + already contain the addresses of the loca node. + +5. _A_ and _B_ exchange the generated _offer_ and _answer_ through some protocol + (e.g. an altered DCUtR) via the relayed connection. + +6. _A_ and _B_ set the exchanged _offer_ and _answer_ and thus initiate the + connection establishment. + +7. Messages on the established `RTCDataChannel` are framed using the message + framing mechanism described in [Multiplexing](#multiplexing). + +8. The remote is authenticated via an additional Noise handshake. See + [Connection Security](#connection-security). #### Open Questions From b5466fd1c4aeaf958fe1c942b29dbc91d66dc68a Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 10:22:55 +0100 Subject: [PATCH 087/128] webrtc/: Have B start Noise handshake --- webrtc/README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index d263f5c52..5262a5ad0 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -349,8 +349,7 @@ After [Connection Establishment](#connection-establishment): ([`pc.createDataChannel("", {negotiated: true, id: 0});`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel)). -2. _A_ starts a Noise `XX` handshake using _A_'s and _B_'s libp2p identity on - the new channel. See +2. _B_ starts a Noise `XX` handshake on the new channel. See [noise-libp2p](https://github.com/libp2p/specs/tree/master/noise). _A_ and _B_ use the [Noise @@ -384,10 +383,6 @@ accept streams before completion of the handshake. ### Open Questions -- Would it be more efficient for _B_ to initiate the Noise handshake? In other - words, who is able to write on an established WebRTC connection first? _A_ or - _B_? - - On the server side, can one derive the TLS certificate in a deterministic way based on a node's libp2p private key? Benefit would be that a node only needs to persist the libp2p private key and not the TLS key material while still From 4931f87f0d9b86fcb8c5d08ba3a5e296729924ae Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 10:34:56 +0100 Subject: [PATCH 088/128] webrtc/: Fix fingerprint hash algorithm to sha-256 --- webrtc/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 5262a5ad0..de999ccbe 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -376,6 +376,13 @@ https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used in WebRTC and the hash function used in the multiaddr `/certhash` component MUST be the same. On mismatch the final Noise handshake MUST fail. +_A_ knows _B_'s fingerprint hash algorithm through _B_'s multiaddr. _B_ could +infer _A_'s fingerprint hash algorithm through _A_'s TLS certificate signature. +Or _B_ could assume _A_ to use the same hash algorithm it discovers through +_B_'s multiaddr. For now implementations MAY assume both _A_ and _B_ to use +sha-256. Future iterations of this specification may add support for other hash +algorithms in a backwards compatible way. + Implementations MAY open streams before completion of the Noise handshake. Applications MUST take special care what application data they send, since at this point the peer is not yet authenticated. Similarly, the receiving side MAY From d5d164b3fe62220b44f4ba51690fe07acd64d82a Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 11:13:00 +0100 Subject: [PATCH 089/128] webrtc/: Document replacement of webrtc direct and star --- webrtc/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index de999ccbe..e6fb23f98 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -199,6 +199,11 @@ the second iteration i.e. sufficiently specifying browser-to-server._ 8. The remote is authenticated via an additional Noise handshake. See [Connection Security](#connection-security). +The above browser-to-browser WebRTC connection establishment replaces the +existing [libp2p WebRTC star](https://github.com/libp2p/js-libp2p-webrtc-star) +and [libp2p WebRTC direct](https://github.com/libp2p/js-libp2p-webrtc-direct) +protocols. + #### Open Questions - Can a browser know upfront its UDP port which it is listening for incoming From 6775d103cd9ddf47274b97b998f57c8cb5de1689 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 13:26:17 +0100 Subject: [PATCH 090/128] webrtc/: Document setting ondatachannel callback before noise Taken from @melekes from https://github.com/mxinden/specs/pull/5. --- webrtc/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index e6fb23f98..7472be62a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -388,6 +388,13 @@ _B_'s multiaddr. For now implementations MAY assume both _A_ and _B_ to use sha-256. Future iterations of this specification may add support for other hash algorithms in a backwards compatible way. +Implementations SHOULD setup all the necessary callbacks (e.g. +[`ondatachannel`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event)) +before starting the Noise handshake. This is to avoid scenarios like one where +_A_ initiates a stream before _B_ got a chance to set the `ondatachannel` +callback. This would result in _B_ ignoring all the messages coming from _A_ +targeting that stream. + Implementations MAY open streams before completion of the Noise handshake. Applications MUST take special care what application data they send, since at this point the peer is not yet authenticated. Similarly, the receiving side MAY From 730dca0ffd8bc31fe8e683c90e1b4e2242bec1d4 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 17:57:49 +0100 Subject: [PATCH 091/128] webrtc/: Order Protologue fingerprints by role not by sorting --- webrtc/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 7472be62a..c500be0fe 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -360,10 +360,10 @@ After [Connection Establishment](#connection-establishment): _A_ and _B_ use the [Noise Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism. More specifically _A_ and _B_ set the Noise _Prologue_ to - `libp2p-webrtc-noise:` before starting the actual Noise - handshake. `` is the concatenation of the two TLS fingerprints - of _A_ and _B_ in their multihash byte representation, sorted in ascending - order. + `libp2p-webrtc-noise:` before starting the + actual Noise handshake. `` is the concatenation + of the two TLS fingerprints of _A_ (Noise handshake responder) and then _B_ + (Noise handshake initiator), in their multihash byte representation. On Chrome _A_ can access its TLS certificate fingerprint directly via `RTCCertificate#getFingerprints`. Firefox does not allow _A_ to do so. Browser From faf641d89abe0e49285e744aa5e3ed50ba9fff9f Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 18:44:28 +0100 Subject: [PATCH 092/128] webrtc/: Use RTCDataChannel `negotiated: false` --- webrtc/README.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c500be0fe..242525299 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -321,24 +321,22 @@ real-world experiments. ### `RTCDataChannel` negotiation -`RTCDataChannel`s are negotiated out-of-band by setting `negotiated: true` when -creating a `RTCDataChannel` via `RTCPeerConnection.createDataChannel`. - -The 16-bit numeric `RTCDataChannel` `id` space is split between _A_ and _B_ as -recommended by the [WebRTC -RFC](https://www.rfc-editor.org/rfc/rfc8831#section-6.5): - -> the stream [ids] are picked based on the DTLS role (the client picks even -> stream identifiers, and the server picks odd stream identifiers). - -Note that `id` `0` is reserved for the additional connection security handshake. -See [Connection Security](#connection-security). - -Given the small `id` space, implementations SHOULD reuse `RTCDataChannel` `id`s -of previously closed `RTCDataChannel`s once they used up the maximum `id` -assigned to them (via their DTLS role). Thus instead of a maximum of `~2^16` -streams throughout the lifetime of a WebRTC connection, `~2^16` is the maximum -number of *concurrent* streams of a WebRTC connection. +`RTCDataChannel`s are negotiated in-band by the WebRTC user agent (e.g. Firefox, +Pion, ...). In other words libp2p WebRTC implementations MUST NOT change the +default value `negotiated: false` when creating a `RTCDataChannel` via +`RTCPeerConnection.createDataChannel`. + +The WebRTC user agent (i.e. not the application) decides on the `RTCDataChannel` +ID based on the local node's connection role. For the interested reader see +[RF8832 Protocol +Overview](https://www.rfc-editor.org/rfc/rfc8832.html#section-4). User agents +can reuse IDs once their `RTCDataChannel` closes. E.g. see [Chromium +implementation](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/pc/sctp_data_channel.cc;drc=9eb3b57e381e6c525ca8bd1494de5eb20fac58c7;l=104) + +According to RFC 8832 a `RTCDataChannel` initiator "MAY start sending messages +containing user data without waiting for the reception of the corresponding +DATA_CHANNEL_ACK message", thus using `negotiated: false` does not imply an +additional round trip for each new `RTCDataChannel`. ## Connection Security From e2df94c77882a19bc29062ab88c092ad57a753f3 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 12 Oct 2022 18:57:10 +0100 Subject: [PATCH 093/128] webrtc/: Link to RFC and not Chromium codebase for stream reuse Thanks @melekes for the reference. --- webrtc/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 242525299..fad62e5df 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -330,8 +330,9 @@ The WebRTC user agent (i.e. not the application) decides on the `RTCDataChannel` ID based on the local node's connection role. For the interested reader see [RF8832 Protocol Overview](https://www.rfc-editor.org/rfc/rfc8832.html#section-4). User agents -can reuse IDs once their `RTCDataChannel` closes. E.g. see [Chromium -implementation](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/pc/sctp_data_channel.cc;drc=9eb3b57e381e6c525ca8bd1494de5eb20fac58c7;l=104) +can reuse IDs once their `RTCDataChannel` closes: "Streams are available for +reuse after a reset has been performed". See [RFC 8831 6.7 Closing a Data +Channel ](https://datatracker.ietf.org/doc/html/rfc8831#section-6.7) According to RFC 8832 a `RTCDataChannel` initiator "MAY start sending messages containing user data without waiting for the reception of the corresponding From b268693ccda30635a88b23bb0000c9e580ee1292 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:09:53 +0100 Subject: [PATCH 094/128] webrtc/: Rephrase stream reuse and mention concurrent limit --- webrtc/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index fad62e5df..3ae4fd8be 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -329,10 +329,12 @@ default value `negotiated: false` when creating a `RTCDataChannel` via The WebRTC user agent (i.e. not the application) decides on the `RTCDataChannel` ID based on the local node's connection role. For the interested reader see [RF8832 Protocol -Overview](https://www.rfc-editor.org/rfc/rfc8832.html#section-4). User agents -can reuse IDs once their `RTCDataChannel` closes: "Streams are available for -reuse after a reset has been performed". See [RFC 8831 6.7 Closing a Data -Channel ](https://datatracker.ietf.org/doc/html/rfc8831#section-6.7) +Overview](https://www.rfc-editor.org/rfc/rfc8832.html#section-4). It is +RECOMMENDED that user agents reuse IDs once their `RTCDataChannel` closes. IDs +MAY be reused according to RFC 8831: "Streams are available for reuse after a +reset has been performed", see [RFC 8831 6.7 Closing a Data Channel +](https://datatracker.ietf.org/doc/html/rfc8831#section-6.7). Up to 65535 +(`2^16`) concurrent data channels can be opened at any given time. According to RFC 8832 a `RTCDataChannel` initiator "MAY start sending messages containing user data without waiting for the reception of the corresponding From 3aebc6855e543bd6e33b0a9e81434903a0bfc6ac Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:13:19 +0100 Subject: [PATCH 095/128] webrtc/: Drop hope for not having to use STUN --- webrtc/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 3ae4fd8be..22871caf4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -47,7 +47,7 @@ Interest Group: [@marten-seemann] - Loading a remote node's certificate into one's browser trust-store is not an option, i.e. doesn't scale. -- No dependency on central STUN and/or TURN servers. +- No dependency on central TURN servers. ## Addressing @@ -206,13 +206,6 @@ protocols. #### Open Questions -- Can a browser know upfront its UDP port which it is listening for incoming - connections on? Does the browser reuse the UDP port across many WebRTC - connections? If that is the case one could connect to any public node, with - the remote telling the local node what port it is perceived on. - - No, a browser uses a new UDP port for each `RTCPeerConnection`. - - Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can _Browser_ use the same TLS certificate for multiple WebRTC connections? @@ -485,5 +478,13 @@ accept streams before completion of the handshake. going forward. Using Protobuf is consistent with the many other libp2p protocols. These benefits outweigh the drawback of additional overhead. +- _Can a browser know upfront its UDP port which it is listening for incoming + connections on? Does the browser reuse the UDP port across many WebRTC + connections? If that is the case one could connect to any public node, with + the remote telling the local node what port it is perceived on. Thus one could + use libp2p's identify and AutoNAT protocol instead of relying on STUN._ + + No, a browser uses a new UDP port for each `RTCPeerConnection`. + [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html [uvarint-spec]: https://github.com/multiformats/unsigned-varint From 50b4e1254e5cdc095432c4a9a230321e8cc3054c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:19:22 +0100 Subject: [PATCH 096/128] webrtc/: Rephrase requirements as FAQs --- webrtc/README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 22871caf4..7d0025fb2 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -42,13 +42,6 @@ Interest Group: [@marten-seemann] 2. **Hole punching in the browser**: Enable two browsers or a browser and a server node to connect even though one or both are behind a NAT / firewall. -## Requirements - -- Loading a remote node's certificate into one's browser trust-store is not an - option, i.e. doesn't scale. - -- No dependency on central TURN servers. - ## Addressing WebRTC multiaddresses are composed of an IP and UDP address component, followed @@ -486,5 +479,18 @@ accept streams before completion of the handshake. No, a browser uses a new UDP port for each `RTCPeerConnection`. +- _Why not load a remote node's certificate into one's browser trust-store and + then connect e.g. via WebSocket._ + + This would require a mechanism to discover remote node's certificates upfront. + More importantly, this does not scale with the number of connections a typical + peer-to-peer application establishes. + +- _Why not use a central TURN servers? Why rely on libp2p's Circuit Relay v2 + instead?_ + + As a peer-to-peer networking library, libp2p should rely as little as possible + on central infrastructure. + [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html [uvarint-spec]: https://github.com/multiformats/unsigned-varint From c8df617892fe2e2cabad4605e62fa08cfd681b38 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:28:56 +0100 Subject: [PATCH 097/128] webrtc/: Document setting username and password on local and remote SDP --- webrtc/README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 7d0025fb2..debbf37f9 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -13,7 +13,6 @@ Interest Group: [@marten-seemann] - [WebRTC](#webrtc) - [Motivation](#motivation) - - [Requirements](#requirements) - [Addressing](#addressing) - [Connection Establishment](#connection-establishment) - [Browser to public Server](#browser-to-public-server) @@ -22,6 +21,8 @@ Interest Group: [@marten-seemann] - [Open Questions](#open-questions-1) - [Multiplexing](#multiplexing) - [Ordering](#ordering) + - [Head-of-line blocking](#head-of-line-blocking) + - [`RTCDataChannel` negotiation](#rtcdatachannel-negotiation) - [Connection Security](#connection-security) - [Open Questions](#open-questions-2) - [General Open Questions](#general-open-questions) @@ -89,15 +90,16 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. `RTCPeerConnection`s. Reusing the certificate can be used to identify _A_ across connections by on-path observers given that WebRTC uses TLS 1.2. -4. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr and sets it - via +4. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr. _A_ + generates a random string and sets that string as the username (_ufrag_ or + _username fragment_) and password on the SDP of the remote offer. Finally _A_ + sets the remote offer via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). 5. _A_ creates a local offer via [`RTCPeerConnection.createOffer()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer). - _A_ generates a random string and sets that string as the username (_ufrag_ - or _username fragment_) and password on the SDP of the local offer. Finally - _A_ sets the modified offer via + _A_ sets the same username as password on the local offer as done in (4) on + the remote offer. Finally _A_ sets the modified offer via [`RTCPeerConnection.setLocalDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription). Note that this process, oftentimes referred to as "SDP munging" is disallowed @@ -122,13 +124,14 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. On success of the DTLS handshake the connection provides confidentiality and integrity but not authenticity. The latter is guaranteed through the - succeeding Noise handshake. + succeeding Noise handshake. See [Connection Security + section](#connection-security). 8. Messages on the established `RTCDataChannel` are framed using the message framing mechanism described in [Multiplexing](#multiplexing). 9. The remote is authenticated via an additional Noise handshake. See - [Connection Security](#connection-security). + [Connection Security section](#connection-security). #### Open Questions From 4de8f96c05edc8d25a26862c93ed36ea6a0e98c2 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:38:38 +0100 Subject: [PATCH 098/128] webrtc/: Document amplification and DOS attack defense --- webrtc/README.md | 51 ++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index debbf37f9..642a98dfe 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -113,6 +113,13 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. incoming connection. _B_ uses the same random string for the username and password in the STUN message from _B_ to _A_. + Note that this step requires _B_ to allocate memory for each incoming STUN + message from _A_. This could be leveraged for a **DOS attack** where _A_ is + sending many STUN messages with different ufrags using different UDP source + ports, forcing _B_ to allocate a new peer connection for each. _B_ SHOULD + have a rate limiting mechanism in place as a defense measure. See also + https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2. + 7. _A_ and _B_ execute the DTLS handshake as part of the standard WebRTC connection establishment. @@ -133,34 +140,6 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 9. The remote is authenticated via an additional Noise handshake. See [Connection Security section](#connection-security). -#### Open Questions - -- Is the fact that the server accepts STUN messages from the client prone to - attacks? - - - Can an attacker launch an **amplification attack** with the STUN endpoint - of the server? - - The QUIC protocol defends against amplification attacks by requiring: - - > an endpoint MUST limit the amount of data it sends to the unvalidated - > address to three times the amount of data received from that address. - - https://datatracker.ietf.org/doc/html/rfc9000#section-8 - - For WebRTC in libp2p one could require the client (_A_) to add additional - bytes to its STUN message, e.g. in the STUN username and password, thus - making an amplification attack less attractive. - - - Can a client run a **DOS attack** by sending many STUN messages with - different ufrags using different UDP source ports, forcing the server to - allocate a new peer connection for each? Would rate limiting suffice to - defend against this attack? - - See also: - - https://datatracker.ietf.org/doc/html/rfc5389#section-16.2.1 - - https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2 - ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of @@ -495,5 +474,21 @@ accept streams before completion of the handshake. As a peer-to-peer networking library, libp2p should rely as little as possible on central infrastructure. +- _Can an attacker launch an amplification attack with the STUN endpoint of + the server?_ + + We follow the reasoning of the QUIC protocol, namely requiring: + + > an endpoint MUST limit the amount of data it sends to the unvalidated + > address to three times the amount of data received from that address. + + https://datatracker.ietf.org/doc/html/rfc9000#section-8 + + This is the case for STUN response messages which are only slight larger than + the request messages. See also + https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2. + + + [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html [uvarint-spec]: https://github.com/multiformats/unsigned-varint From 4dcf801b459764b2da14247859f56d988d40b9bf Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:44:28 +0100 Subject: [PATCH 099/128] webrtc/: Document reason for B starting noise handshake --- webrtc/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 642a98dfe..3620d3756 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -114,7 +114,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. password in the STUN message from _B_ to _A_. Note that this step requires _B_ to allocate memory for each incoming STUN - message from _A_. This could be leveraged for a **DOS attack** where _A_ is + message from _A_. This could be leveraged for a DOS attack where _A_ is sending many STUN messages with different ufrags using different UDP source ports, forcing _B_ to allocate a new peer connection for each. _B_ SHOULD have a rate limiting mechanism in place as a defense measure. See also @@ -334,12 +334,12 @@ After [Connection Establishment](#connection-establishment): of the two TLS fingerprints of _A_ (Noise handshake responder) and then _B_ (Noise handshake initiator), in their multihash byte representation. - On Chrome _A_ can access its TLS certificate fingerprint directly via - `RTCCertificate#getFingerprints`. Firefox does not allow _A_ to do so. Browser - compatibility can be found - [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In - practice, this is not an issue since the fingerprint is embedded in the local - SDP string. + On Chrome _A_ can access its TLS certificate fingerprint directly via + `RTCCertificate#getFingerprints`. Firefox does not allow _A_ to do so. Browser + compatibility can be found + [here](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate). In + practice, this is not an issue since the fingerprint is embedded in the local + SDP string. 3. On success of the authentication handshake, the used datachannel is closed and the plain WebRTC connection is used with its multiplexing @@ -488,7 +488,9 @@ accept streams before completion of the handshake. the request messages. See also https://datatracker.ietf.org/doc/html/rfc5389#section-16.1.2. +- _Why does B start the Noise handshake and not A?_ + Given that WebRTC uses DTLS 1.2, _B_ is the one that can send data first. [QUIC RFC]: https://www.rfc-editor.org/rfc/rfc9000.html [uvarint-spec]: https://github.com/multiformats/unsigned-varint From 16e38fbb1646e9c97d0a169a946a6e7126cd7421 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:45:01 +0100 Subject: [PATCH 100/128] webrtc/: Remove derivation of TLS certificate --- webrtc/README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 3620d3756..2e8506794 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -369,13 +369,6 @@ Applications MUST take special care what application data they send, since at this point the peer is not yet authenticated. Similarly, the receiving side MAY accept streams before completion of the handshake. -### Open Questions - -- On the server side, can one derive the TLS certificate in a deterministic way - based on a node's libp2p private key? Benefit would be that a node only needs - to persist the libp2p private key and not the TLS key material while still - maintaining a fixed TLS certificate fingerprint. - ## General Open Questions - Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC From f635466a3e61cc29c761c01be0242ebfaef415ae Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 13 Oct 2022 10:49:53 +0100 Subject: [PATCH 101/128] webrtc: Document MUST for UDP and MAY for TCP --- webrtc/README.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 2e8506794..4ce904f2d 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -16,16 +16,13 @@ Interest Group: [@marten-seemann] - [Addressing](#addressing) - [Connection Establishment](#connection-establishment) - [Browser to public Server](#browser-to-public-server) - - [Open Questions](#open-questions) - [Browser to Browser](#browser-to-browser) - - [Open Questions](#open-questions-1) + - [Open Questions](#open-questions) - [Multiplexing](#multiplexing) - [Ordering](#ordering) - [Head-of-line blocking](#head-of-line-blocking) - [`RTCDataChannel` negotiation](#rtcdatachannel-negotiation) - [Connection Security](#connection-security) - - [Open Questions](#open-questions-2) - - [General Open Questions](#general-open-questions) - [Previous, ongoing and related work](#previous-ongoing-and-related-work) - [FAQ](#faq) @@ -140,6 +137,9 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 9. The remote is authenticated via an additional Noise handshake. See [Connection Security section](#connection-security). +WebRTC can run both on UDP and TCP. libp2p WebRTC implementations MUST support +UDP and MAY support TCP. + ### Browser to Browser Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of @@ -369,14 +369,6 @@ Applications MUST take special care what application data they send, since at this point the peer is not yet authenticated. Similarly, the receiving side MAY accept streams before completion of the handshake. -## General Open Questions - -- Should libp2p's WebRTC stack limit itself to using UDP only, or support WebRTC - on top of both UDP and TCP? - -- Is the fact that Firefox does not allow a WebRTC to `localhost` an issue? See - https://bugzilla.mozilla.org/show_bug.cgi?id=831926. - ## Previous, ongoing and related work - Proof of concept for the server side in rust-libp2p: From 75c3b5cf69aa414faabe7f6bce6666fa0ae349e2 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 14 Oct 2022 22:33:53 +1100 Subject: [PATCH 102/128] Update test vector to remove sorting requirement --- webrtc/README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 963768c46..997184d34 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -391,15 +391,7 @@ All of these test vectors represent hex-encoded bytes. client_fingerprint = "3e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" server_fingerprint = "30fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b99" -prologue = "6c69627032702d7765627274632d6e6f6973653a122030fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b9912203e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" -``` - -Flipped version (testing the sorting requirement): -``` -client_fingerprint = "30fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b99" -server_fingerprint = "3e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" - -prologue = "6c69627032702d7765627274632d6e6f6973653a122030fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b9912203e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" +prologue = "6c69627032702d7765627274632d6e6f6973653a12203e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870122030fc9f469c207419dfdd0aab5f27a86c973c94e40548db9375cca2e915973b99" ``` # FAQ From 9abf63875920200c10e1656a19d64d5aea648a34 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:18:11 +0100 Subject: [PATCH 103/128] webrtc/: Document RTCDataChannel label to be an empty string --- webrtc/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index 4ce904f2d..ec9e0944a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -309,6 +309,15 @@ containing user data without waiting for the reception of the corresponding DATA_CHANNEL_ACK message", thus using `negotiated: false` does not imply an additional round trip for each new `RTCDataChannel`. +### `RTCDataChannel` label + +`RTCPeerConnection.createDataChannel()` requires passing a `label` for the +to-be-created `RTCDataChannel`. When calling `createDataChannel` implementations +MUST pass an empty string. When receiving an `RTCDataChannel` via +`RTCPeerConnection.ondatachannel` implementations MUST NOT require `label` to be +an empty string. This allows future versions of this specification to make use +of the `RTCDataChannel` `label` property. + ## Connection Security Note that the below uses the message framing described in From 1cb40937b74d229c1ff44bf3d28ce82e1f329950 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:24:26 +0100 Subject: [PATCH 104/128] webrtc/: Track RTCDatachannel label in TOC --- webrtc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/webrtc/README.md b/webrtc/README.md index ec9e0944a..7278b1545 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -22,6 +22,7 @@ Interest Group: [@marten-seemann] - [Ordering](#ordering) - [Head-of-line blocking](#head-of-line-blocking) - [`RTCDataChannel` negotiation](#rtcdatachannel-negotiation) + - [`RTCDataChannel` label](#rtcdatachannel-label) - [Connection Security](#connection-security) - [Previous, ongoing and related work](#previous-ongoing-and-related-work) - [FAQ](#faq) From a46919c557aa4501afb285ffbec8261a7a7e595b Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:24:55 +0100 Subject: [PATCH 105/128] webrtc/: Remove browser-to-browser use-case This will be specified in a second iteration of this specification. --- webrtc/README.md | 65 ------------------------------------------------ 1 file changed, 65 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 7278b1545..52f2b4c8b 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -16,8 +16,6 @@ Interest Group: [@marten-seemann] - [Addressing](#addressing) - [Connection Establishment](#connection-establishment) - [Browser to public Server](#browser-to-public-server) - - [Browser to Browser](#browser-to-browser) - - [Open Questions](#open-questions) - [Multiplexing](#multiplexing) - [Ordering](#ordering) - [Head-of-line blocking](#head-of-line-blocking) @@ -38,9 +36,6 @@ Interest Group: [@marten-seemann] certificate. Nor can we establish a plain TCP or QUIC connection from within a browser. -2. **Hole punching in the browser**: Enable two browsers or a browser and a - server node to connect even though one or both are behind a NAT / firewall. - ## Addressing WebRTC multiaddresses are composed of an IP and UDP address component, followed @@ -141,66 +136,6 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. WebRTC can run both on UDP and TCP. libp2p WebRTC implementations MUST support UDP and MAY support TCP. -### Browser to Browser - -Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of -server node _R_. - -_Note that this section is a draft only for now, will be removed before merging -the first iteration of the specification (browser-to-server) and reintroduced in -the second iteration i.e. sufficiently specifying browser-to-server._ - -1. _B_ runs inside a browser and can thus not listen for incoming connections. - _B_ connects to a public server node _R_ and uses the Circuit Relay v2 - protocol to make a reservation. - -2. _B_ advertises its relayed address through some external mechanism. - -3. _A_ discovers _B_'s relayed address. _A_ connects to _R_ and establishes a - relayed connection to _B_ via the Circtui Relay v2 protocol. - -4. _A_ and _B_ both create a `RTCPeerConnection` and generate an _offer_ and an - _answer_ respectively. See `icegatheringstatechange` below on how these may - already contain the addresses of the loca node. - -5. _A_ and _B_ exchange the generated _offer_ and _answer_ through some protocol - (e.g. an altered DCUtR) via the relayed connection. - -6. _A_ and _B_ set the exchanged _offer_ and _answer_ and thus initiate the - connection establishment. - -7. Messages on the established `RTCDataChannel` are framed using the message - framing mechanism described in [Multiplexing](#multiplexing). - -8. The remote is authenticated via an additional Noise handshake. See - [Connection Security](#connection-security). - -The above browser-to-browser WebRTC connection establishment replaces the -existing [libp2p WebRTC star](https://github.com/libp2p/js-libp2p-webrtc-star) -and [libp2p WebRTC direct](https://github.com/libp2p/js-libp2p-webrtc-direct) -protocols. - -#### Open Questions - -- Can _Browser_ control the lifecycle of its local TLS certificate, i.e. can - _Browser_ use the same TLS certificate for multiple WebRTC connections? - - Yes. For the lifetime of the page, one can generate a certificate once and - reuse it across connections. See also - https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#using_certificates - -- Can two _Browsers_ exchange their SDP packets via a third server node using - Circuit Relay v2 and DCUtR? Instead of exchanging the original SDP packets, - could they exchange their multiaddr and construct the remote's SDP packet - based on it? - -- Instead of using trickle ICE, we could as well wait for the candidate - gathering. See - https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/examples/insertable-streams/main.go#L141-L142 - as one example. In the browser, one can wait for the - [`icegatheringstatechange` - event](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icegatheringstatechange_event). - ## Multiplexing The WebRTC browser APIs do not support half-closing of streams nor resets of the From 3058fb9e3519edc4a2615bd7fd97c097d96cbf73 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:28:27 +0100 Subject: [PATCH 106/128] webrtc/: Update "Previous, ongoing and related work" section --- webrtc/README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 52f2b4c8b..b3db21771 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -316,13 +316,14 @@ accept streams before completion of the handshake. ## Previous, ongoing and related work -- Proof of concept for the server side in rust-libp2p: - https://github.com/libp2p/rust-libp2p/pull/2622 - -- Proof of concept for the server side (native) and the client side (Rust in - WASM): https://github.com/wngr/libp2p-webrtc - -- WebRTC using STUN and TURN: https://github.com/libp2p/js-libp2p-webrtc-star +- Work in progress implementations of this specification: + - https://github.com/little-bear-labs/js-libp2p-webrtc/ + - https://github.com/libp2p/go-libp2p/pull/1655 + - https://github.com/libp2p/rust-libp2p/pull/2622 +- Past related work: + - Proof of concept for the server side (native) and the client side (Rust in + WASM): https://github.com/wngr/libp2p-webrtc + - WebRTC using STUN and TURN: https://github.com/libp2p/js-libp2p-webrtc-star # FAQ From a382f18c3ed2c34e04fac6a4f30e082f4b8b33de Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:30:10 +0100 Subject: [PATCH 107/128] webrtc/: Add revision --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index b3db21771..e477859a2 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -2,7 +2,7 @@ | Lifecycle Stage | Maturity | Status | Latest Revision | |-----------------|---------------|--------|-----------------| -| 1A | Working Draft | Active | | +| 1A | Working Draft | Active | r0, 2022-10-14 | Authors: [@mxinden] From 44fd0826f09fb00a5b315d3cb5304da4e84fb79a Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 14 Oct 2022 16:30:40 +0100 Subject: [PATCH 108/128] webrtc/: Fix interest group links --- webrtc/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webrtc/README.md b/webrtc/README.md index e477859a2..29d51432a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -8,6 +8,9 @@ Authors: [@mxinden] Interest Group: [@marten-seemann] +[@marten-seemann]: https://github.com/marten-seemann +[@mxinden]: https://github.com/mxinden/ + **Table of Contents** From 1ddc3171ded1cd9e7b56d958dfb397f8f8a72897 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:26:44 +0100 Subject: [PATCH 109/128] webrtc/: Document role on test vectors --- webrtc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 724dd6ed3..df011292f 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -334,7 +334,9 @@ accept streams before completion of the handshake. All of these test vectors represent hex-encoded bytes. -#### 1. Both client and server use SHA-256 +#### Both client and server use SHA-256 + +Here client is _A_ and server is _B_. ``` client_fingerprint = "3e79af40d6059617a0d83b83a52ce73b0c1f37a72c6043ad2969e2351bdca870" From 1e3ca5946883728f99c992db47b1ea1ebfc0300e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:28:44 +0100 Subject: [PATCH 110/128] webrtc/: Fix typo generating an offer for B --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index df011292f..efe085566 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -86,7 +86,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. `RTCPeerConnection`s. Reusing the certificate can be used to identify _A_ across connections by on-path observers given that WebRTC uses TLS 1.2. -4. _A_ constructs _B_'s SDP offer locally based on _B_'s multiaddr. _A_ +4. _A_ constructs _B_'s SDP answer locally based on _B_'s multiaddr. _A_ generates a random string and sets that string as the username (_ufrag_ or _username fragment_) and password on the SDP of the remote offer. Finally _A_ sets the remote offer via From b1f629a29494b401a53e696ab9a4036b3f2cc6e7 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:34:15 +0100 Subject: [PATCH 111/128] webrtc/: Fix more offer answer confusions --- webrtc/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index efe085566..a26d4e8ab 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -88,14 +88,14 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 4. _A_ constructs _B_'s SDP answer locally based on _B_'s multiaddr. _A_ generates a random string and sets that string as the username (_ufrag_ or - _username fragment_) and password on the SDP of the remote offer. Finally _A_ - sets the remote offer via + _username fragment_) and password on the SDP of the remote's answer. Finally _A_ + sets the remote answer via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). 5. _A_ creates a local offer via [`RTCPeerConnection.createOffer()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer). - _A_ sets the same username as password on the local offer as done in (4) on - the remote offer. Finally _A_ sets the modified offer via + _A_ sets the same username and password on the local offer as done in (4) on + the remote answer. Finally _A_ sets the modified offer via [`RTCPeerConnection.setLocalDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription). Note that this process, oftentimes referred to as "SDP munging" is disallowed From 070ebead030ac65ee54cc6e9e7e19d2aef9101db Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:39:35 +0100 Subject: [PATCH 112/128] webrtc/: Reword server generating SDP offer --- webrtc/README.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index a26d4e8ab..54d505edb 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -103,11 +103,26 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. Firefox, Chrome) due to use-cases in the wild. See also https://bugs.chromium.org/p/chromium/issues/detail?id=823036 -6. _A_ establishes the connection to _B_. The random string used as a _username_ - and _password_ in combination with the IP and port of _A_ can be used by _B_ +6. Once _A_ sets the SDP offer and answer, it will start sending STUN requests + to _B_. _B_ reads the _ufrag_ from the incoming STUN request's _username_ + field. _B_ then infers _A_'s SDP offer using the IP, port, and _ufrag_ of the + request as follows: + + 1. _B_ sets the the `ice-ufrag` and `ice-pwd` equal to the value read from + the `username` field. + + 2. _B_ sets an arbitrary sha-256 digest as the remote fingerprint as it does + not verify fingerprints at this point. + + 3. _B_ sets the connection field (`c`) to the IP and port of the incoming + request `c=IN `. + + _B_ sets this offer as the remote description. _B_ generates an answer and + sets it as the local description. + + The _ufrag_ in combination with the IP and port of _A_ can be used by _B_ to identify the connection, i.e. demultiplex incoming UDP datagrams per - incoming connection. _B_ uses the same random string for the username and - password in the STUN message from _B_ to _A_. + incoming connection. Note that this step requires _B_ to allocate memory for each incoming STUN message from _A_. This could be leveraged for a DOS attack where _A_ is From 072c317c1e290ef9ad3bb5c1a647cce99eddceff Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:41:13 +0100 Subject: [PATCH 113/128] Update webrtc/README.md Co-authored-by: Thomas Eizinger --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 54d505edb..2aff15389 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -66,7 +66,7 @@ Scenario: Browser _A_ wants to connect to server node _B_ where _B_ is publicly reachable but _B_ does not have a TLS certificate trusted by _A_. 1. Server node _B_ generates a TLS certificate, listens on a UDP port and - advertises the corresponding multiaddress (see [#Addressing]) through some + advertises the corresponding multiaddress (see [#addressing]) through some external mechanism. Given that _B_ is publicly reachable, _B_ acts as a [ICE From b8dc6fdac7079c1beddf7e99382aea147e409bb3 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:44:42 +0100 Subject: [PATCH 114/128] webrtc/: Mark server's peer ID as optional --- webrtc/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 2aff15389..dacc1398c 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -75,9 +75,9 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. source port. 2. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP - port, TLS certificate fingerprint and libp2p peer ID (e.g. - `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), - through some external mechanism. + port, TLS certificate fingerprint and optionally libp2p peer ID (e.g. + `/ip6/2001:db8::/udp/1234/webrtc/certhash//p2p/`), through some + external mechanism. 3. _A_ instantiates a `RTCPeerConnection`. See [`RTCPeerConnection()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection). From a62fdd2da092d04fc5220d7dfbcd716128c4163d Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 20 Oct 2022 20:49:27 +0100 Subject: [PATCH 115/128] Update webrtc/README.md Co-authored-by: Marten Seemann --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index dacc1398c..95797a0db 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -34,7 +34,7 @@ Interest Group: [@marten-seemann] 1. **No need for trusted TLS certificates.** Enable browsers to connect to public server nodes without those server nodes providing a TLS certificate - within the browsers trustchain. Note that we can not do this today with our + within the browser's trustchain. Note that we can not do this today with our Websocket transport as the browser requires the remote to have a trusted TLS certificate. Nor can we establish a plain TCP or QUIC connection from within a browser. From 60ac97a261fb9f9c91c3c71c62fe6216b43bfa81 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 12:55:29 +0100 Subject: [PATCH 116/128] webrtc/: Mention WebTransport specification --- webrtc/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 95797a0db..cb2b41db5 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -37,7 +37,8 @@ Interest Group: [@marten-seemann] within the browser's trustchain. Note that we can not do this today with our Websocket transport as the browser requires the remote to have a trusted TLS certificate. Nor can we establish a plain TCP or QUIC connection from within - a browser. + a browser. We can establish a WebTransport connection from the browser (see + [WebTransport specification](../webtransport)). ## Addressing From 6846d348a8d83160d1a0e4f6b3682a05f81d6541 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 12:56:57 +0100 Subject: [PATCH 117/128] webrtc/: s/listen/bind for UDP socket --- webrtc/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index cb2b41db5..8816a86b7 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -71,9 +71,9 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. external mechanism. Given that _B_ is publicly reachable, _B_ acts as a [ICE - Lite](https://www.rfc-editor.org/rfc/rfc5245) agent. It listens on a UDP port - for incoming STUN and SCTP packets and multiplexes based on source IP and - source port. + Lite](https://www.rfc-editor.org/rfc/rfc5245) agent. It binds to a UDP port + waiting for incoming STUN and SCTP packets and multiplexes based on source IP + and source port. 2. Browser _A_ discovers server node _B_'s multiaddr, containing _B_'s IP, UDP port, TLS certificate fingerprint and optionally libp2p peer ID (e.g. From c369f2b85aa00bf00971cb26616731dba50ae0c6 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:00:03 +0100 Subject: [PATCH 118/128] Update webrtc/README.md Co-authored-by: Marten Seemann --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 8816a86b7..ef70658ae 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -161,7 +161,7 @@ The WebRTC browser APIs do not support half-closing of streams nor resets of the sending part of streams. [`RTCDataChannel.close()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close) flushes the remaining messages and closes the local write and read side. After -calling `RTCDataChannel.close()` one can no longer read from the channel. This +calling `RTCDataChannel.close()` one can no longer read from nor write to the channel. This lack of functionality is problematic, given that libp2p protocols running on top of transport protocols, like WebRTC, expect to be able to half-close or reset a stream. See [Connection Establishment in From 0c4e836b772da59a31885aa642fae8d3352c88d0 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:04:51 +0100 Subject: [PATCH 119/128] Update webrtc/README.md Co-authored-by: Marten Seemann --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index ef70658ae..c4ae83629 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -189,7 +189,7 @@ message Message { // being discarded on receipt. STOP_SENDING = 1; // The sender abruptly terminates the sending part of the stream. The - // receiver can discard any data that it already received on that stream. + // receiver MAY discard any data that it already received on that stream. RESET_STREAM = 2; } From dd9756ba5e0b9856cdb8e5826370440c698f5339 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:19:47 +0100 Subject: [PATCH 120/128] webrtc/: Fix maximum packet size calculation --- webrtc/README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index c4ae83629..2f57303cb 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -237,9 +237,18 @@ we can not make an informed decision on the optimal message size. We follow the recommendation of QUIC, requiring ["a minimum IP packet size of at least 1280 bytes"](https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-29#section-14). -An SCTP packet common header is 12 bytes long. An SCTP data chunk header size is -16 bytes. Thus implementations SHOULD choose a message size equal or below 1252 -bytes. Long term we hope to be able to give better recommendations based on +We calculate with an IPv4 minimum header size of 20 bytes and an IPv6 header +size of 40 bytes. We calculate with a UDP header size of 8 bytes. An SCTP packet +common header is 12 bytes long. An SCTP data chunk header size is 16 bytes. + +- IPv4: `1280 bytes - 20 bytes - 8 bytes - 12 bytes - 16 bytes = 1224 bytes` +- IPv6: `1280 bytes - 40 bytes - 8 bytes - 12 bytes - 16 bytes = 1204 bytes` + +Thus implementations SHOULD choose a message size equal or below 1204 bytes. Or, +in case the implementation can differentiate by IP version, equal or below 1224 +bytes on IPv4 and 1224 bytes on IPv6. + +Long term we hope to be able to give better recommendations based on real-world experiments. ### `RTCDataChannel` negotiation From 249ebd2f24b94adb134afa4569ab434e578dbcc6 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:21:02 +0100 Subject: [PATCH 121/128] webrtc/: Mention head-of-line-blocking on packet size recommendation --- webrtc/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 2f57303cb..122952229 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -244,9 +244,10 @@ common header is 12 bytes long. An SCTP data chunk header size is 16 bytes. - IPv4: `1280 bytes - 20 bytes - 8 bytes - 12 bytes - 16 bytes = 1224 bytes` - IPv6: `1280 bytes - 40 bytes - 8 bytes - 12 bytes - 16 bytes = 1204 bytes` -Thus implementations SHOULD choose a message size equal or below 1204 bytes. Or, -in case the implementation can differentiate by IP version, equal or below 1224 -bytes on IPv4 and 1224 bytes on IPv6. +Thus for payloads that would suffer from head-of-line blocking, implementations +SHOULD choose a message size equal or below 1204 bytes. Or, in case the +implementation can differentiate by IP version, equal or below 1224 bytes on +IPv4 and 1224 bytes on IPv6. Long term we hope to be able to give better recommendations based on real-world experiments. From be5cfeb62b6c82c1c1da281761d6dc47197b974a Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:25:53 +0100 Subject: [PATCH 122/128] webrtc/: Emphasize prologue prefix representation in bytes --- webrtc/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 122952229..8947ae8ac 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -303,8 +303,9 @@ After [Connection Establishment](#connection-establishment): _A_ and _B_ use the [Noise Prologue](https://noiseprotocol.org/noise.html#prologue) mechanism. More specifically _A_ and _B_ set the Noise _Prologue_ to - `libp2p-webrtc-noise:` before starting the - actual Noise handshake. `` is the concatenation + `` before starting the actual Noise + handshake. `` is the UTF-8 byte representation of the string + `libp2p-webrtc-noise:`. `` is the concatenation of the two TLS fingerprints of _A_ (Noise handshake responder) and then _B_ (Noise handshake initiator), in their multihash byte representation. From 602f49291780ff4f73ddff6aaedaf795606bb23f Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:32:39 +0100 Subject: [PATCH 123/128] webrtc/: Require A to use same hash alg as B and REQUIRE sha-256 support --- webrtc/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 8947ae8ac..1c28c521a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -325,12 +325,11 @@ https://datatracker.ietf.org/doc/html/rfc8122#section-5). The hash function used in WebRTC and the hash function used in the multiaddr `/certhash` component MUST be the same. On mismatch the final Noise handshake MUST fail. -_A_ knows _B_'s fingerprint hash algorithm through _B_'s multiaddr. _B_ could -infer _A_'s fingerprint hash algorithm through _A_'s TLS certificate signature. -Or _B_ could assume _A_ to use the same hash algorithm it discovers through -_B_'s multiaddr. For now implementations MAY assume both _A_ and _B_ to use -sha-256. Future iterations of this specification may add support for other hash -algorithms in a backwards compatible way. +_A_ knows _B_'s fingerprint hash algorithm through _B_'s multiaddr. _A_ MUST use +the same hash algorithm to calculate the fingerprint of its (i.e. _A_'s) TLS +certificate. _B_ assumes _A_ to use the same hash algorithm it discovers through +_B_'s multiaddr. For now implementations MUST support sha-256. Future iterations +of this specification may add support for other hash algorithms. Implementations SHOULD setup all the necessary callbacks (e.g. [`ondatachannel`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event)) From 1c7956c4f5a7b86e1228c1fa84232a2450100213 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 22 Oct 2022 13:41:43 +0100 Subject: [PATCH 124/128] webrtc/: Prefix random ufrag string for future upgrades --- webrtc/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 1c28c521a..6308ae87a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -87,10 +87,16 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. `RTCPeerConnection`s. Reusing the certificate can be used to identify _A_ across connections by on-path observers given that WebRTC uses TLS 1.2. -4. _A_ constructs _B_'s SDP answer locally based on _B_'s multiaddr. _A_ - generates a random string and sets that string as the username (_ufrag_ or - _username fragment_) and password on the SDP of the remote's answer. Finally _A_ - sets the remote answer via +4. _A_ constructs _B_'s SDP answer locally based on _B_'s multiaddr. + + _A_ generates a random string prefixed with "libp2p-webrtc-v1:". The prefix + allows us to use the ufrag as an upgrade mechanism to role out a new version + of the libp2p WebRTC protocol on a live network. While a hack, this might be + very useful in the future. + + _A_ sets the above string as the username (_ufrag_ or _username fragment_) + and password on the SDP of the remote's answer. Finally _A_ sets the remote + answer via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). 5. _A_ creates a local offer via From b5ac74b66b037ff01554105b462316f69db7f8da Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 26 Oct 2022 22:10:45 +0100 Subject: [PATCH 125/128] webrtc/README.md: Refer to plural RTCDataChannel Co-authored-by: Marten Seemann --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 6308ae87a..9191b0740 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -152,7 +152,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. succeeding Noise handshake. See [Connection Security section](#connection-security). -8. Messages on the established `RTCDataChannel` are framed using the message +8. Messages on each `RTCDataChannel` are framed using the message framing mechanism described in [Multiplexing](#multiplexing). 9. The remote is authenticated via an additional Noise handshake. See From b6e7eb1962affe70eaff02096adc8cc2445d203b Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 2 Nov 2022 15:11:55 +0000 Subject: [PATCH 126/128] webrtc/README.md: Use valid ufrag prefix Co-authored-by: Thomas Eizinger --- webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc/README.md b/webrtc/README.md index 9191b0740..5e3368206 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -89,7 +89,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 4. _A_ constructs _B_'s SDP answer locally based on _B_'s multiaddr. - _A_ generates a random string prefixed with "libp2p-webrtc-v1:". The prefix + _A_ generates a random string prefixed with "libp2p+webrtc+v1/". The prefix allows us to use the ufrag as an upgrade mechanism to role out a new version of the libp2p WebRTC protocol on a live network. While a hack, this might be very useful in the future. From 2d0478cad56edf9c20292749b4a1f33de23ce148 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 2 Nov 2022 15:31:02 +0000 Subject: [PATCH 127/128] webrtc/: Add max-message-size SDP attribute --- webrtc/README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 5e3368206..22e0d94a4 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -92,17 +92,24 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. _A_ generates a random string prefixed with "libp2p+webrtc+v1/". The prefix allows us to use the ufrag as an upgrade mechanism to role out a new version of the libp2p WebRTC protocol on a live network. While a hack, this might be - very useful in the future. + very useful in the future. _A_ sets the string as the username (_ufrag_ or _username fragment_) + and password on the SDP of the remote's answer. - _A_ sets the above string as the username (_ufrag_ or _username fragment_) - and password on the SDP of the remote's answer. Finally _A_ sets the remote - answer via + _A_ MUST sets the `a=max-message-size:16384` SDP attribute. See reasoning + [multiplexing](#multiplexing) for rational. + + Finally _A_ sets the remote answer via [`RTCPeerConnection.setRemoteDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription). 5. _A_ creates a local offer via [`RTCPeerConnection.createOffer()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer). _A_ sets the same username and password on the local offer as done in (4) on - the remote answer. Finally _A_ sets the modified offer via + the remote answer. + + _A_ MUST sets the `a=max-message-size:16384` SDP attribute. See reasoning + [multiplexing](#multiplexing) for rational. + + Finally _A_ sets the modified offer via [`RTCPeerConnection.setLocalDescription()`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription). Note that this process, oftentimes referred to as "SDP munging" is disallowed @@ -124,6 +131,9 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. 3. _B_ sets the connection field (`c`) to the IP and port of the incoming request `c=IN `. + 4. _B_ sets the `a=max-message-size:16384` SDP attribute. See reasoning + [multiplexing](#multiplexing) for rational. + _B_ sets this offer as the remote description. _B_ generates an answer and sets it as the local description. From 4dc788c3f2c433d03ed6c5f2b32b044b7412c483 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 2 Nov 2022 15:35:45 +0000 Subject: [PATCH 128/128] webrtc/: Fix typo --- webrtc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webrtc/README.md b/webrtc/README.md index 22e0d94a4..f03c7b21a 100644 --- a/webrtc/README.md +++ b/webrtc/README.md @@ -95,7 +95,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. very useful in the future. _A_ sets the string as the username (_ufrag_ or _username fragment_) and password on the SDP of the remote's answer. - _A_ MUST sets the `a=max-message-size:16384` SDP attribute. See reasoning + _A_ MUST set the `a=max-message-size:16384` SDP attribute. See reasoning [multiplexing](#multiplexing) for rational. Finally _A_ sets the remote answer via @@ -106,7 +106,7 @@ reachable but _B_ does not have a TLS certificate trusted by _A_. _A_ sets the same username and password on the local offer as done in (4) on the remote answer. - _A_ MUST sets the `a=max-message-size:16384` SDP attribute. See reasoning + _A_ MUST set the `a=max-message-size:16384` SDP attribute. See reasoning [multiplexing](#multiplexing) for rational. Finally _A_ sets the modified offer via