Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a WebTransport spec #404

Merged
merged 25 commits into from
Oct 12, 2022
Merged
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fba76c4
add a draft for the WebTransport spec
marten-seemann Apr 4, 2022
fc10260
describe the HTTP endpoint
marten-seemann Apr 4, 2022
48dda39
improve introduction
marten-seemann Apr 6, 2022
1e927c4
use Noise to check end-to-end encryption of the WebTransport connection
marten-seemann Apr 17, 2022
0882c03
define protobuf to encode certificate hashes
marten-seemann Apr 17, 2022
72f6c15
use a separate multiaddr component for certificate hashes
marten-seemann Apr 17, 2022
599b3f4
remove server mode using CA signed certificates
marten-seemann Apr 17, 2022
243fd04
apply suggestions from code review
marten-seemann Jun 27, 2022
2cec2b3
webtransport: move certhash verification to the client (#455)
marten-seemann Sep 20, 2022
3601074
webtransport: remove confusion around Noise handshake completion
marten-seemann Sep 28, 2022
ee95b87
webtransport: update certificate generation logic
marten-seemann Sep 28, 2022
df56a5f
webtransport: link to Noise Extensions spec
marten-seemann Sep 28, 2022
92e4635
webtransport: move spec to Candidate Recommendation
marten-seemann Sep 28, 2022
76d7217
webtransport: remove misleading mention of hole punching
marten-seemann Sep 28, 2022
afa554d
webtransport: fix typos
marten-seemann Sep 28, 2022
1942361
webtransport: add interest group
marten-seemann Sep 28, 2022
f968d72
webtransport: add link to Firefox meta-issue
marten-seemann Sep 28, 2022
5ab529d
webtransport: soften language around URL multiaddr encoding
marten-seemann Sep 30, 2022
1219d07
webtransport: clarify that WebTransport over HTTP/3 is meant
marten-seemann Sep 30, 2022
4f498a1
webtransport: fix typo
marten-seemann Sep 30, 2022
53d98bd
webtransport: clarify certificate regeneration logic
marten-seemann Sep 30, 2022
5271135
webtransport: fix typos
marten-seemann Sep 30, 2022
bb90d58
webtransport: allow use of CA-signed certificates
marten-seemann Sep 30, 2022
f9f8613
address minor issues raised in code review
marten-seemann Oct 12, 2022
0a9a7bb
clarify that servers with a CA-signed certificate don't use /certhash
marten-seemann Oct 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions webtransport/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# libp2p WebTransport

| Lifecycle Stage | Maturity | Status | Latest Revision |
|-----------------|--------------------------|--------|-----------------|
| 1A | Candidate Recommendation | Active | r0, 2022-09-28 |

Authors: [@marten-seemann]

Interest Group: [@MarcoPolo], [@mxinden]

See the [lifecycle document](../00-framework-01-spec-lifecycle.md) for context about maturity level
and spec status.

## Introduction

WebTransport is a way for browsers to establish a stream-multiplexed and bidirectional connection to servers using QUIC.

The WebTransport protocol is currently under development at the IETF. Chrome has implemented and shipped support for [draft-02](https://datatracker.ietf.org/doc/draft-ietf-webtrans-http3/), and Firefox [is working](https://bugzilla.mozilla.org/show_bug.cgi?id=1709355) on WebTransport support.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand it correctly, when we talk about the WebTransport protocol in this doc, we actually mean the WebTransport over HTTP-3 protocol as described in draft-ietf-webtrans-http3.
WebTransport as specified in draft-ietf-webtrans-overview is a protocol framework and not a single protocol. I think we should add a note/ sentence on that. At least for me it was a bit confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Not the best naming from the IETF's side here...
Everybody thinks of WebTransport over HTTP/3 when WebTransport, but then there's the HTTP/2 fallback that not a lot of people care about to begin with...

I've added some text (and links) to clarify things. Let me know if that's less confusing now.


The most exciting feature for libp2p (other than the numberous performance benefits that QUIC gives us) is that the W3C added a browser API allowing browsers to establish connections to nodes with self-signed certificates, provided they know the hash of the certificate in advance: [`serverCertificateHashes`](https://www.w3.org/TR/webtransport/#dom-webtransportoptions-servercertificatehashes). This API is already [implemented in Chrome](https://chromestatus.com/feature/5690646332440576). Firefox is working on a WebTransport implementation and is [likely to implement](https://github.com/mozilla/standards-positions/issues/167#issuecomment-1015951396) `serverCertificateHashes` as well.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved

## Certificates

Since most libp2p nodes don't possess a TLS certificate signed by a Certificate Authority, servers use a self-signed certificates. According to the [w3c WebTransport certification](https://www.w3.org/TR/webtransport/), the validity of the certificate MUST be at most 14 days, and must not use an RSA key. Nodes then include the hash of one (or more) certificates in their multiaddr (see [Addressing](#addressing)).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MUST, it's part of the webtransport spec: https://www.w3.org/TR/webtransport/#web-transport-configuration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's "MUST NOT", not "MUST not" ;)

This entire section needs a rewrite though. It is possible to use a CA-signed certificate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rewrote this section. Please take another look.


Servers need to take care to regularly renew their certificate. In the following, the RECOMMENDED logic for rolling certificates is described. At first boot of the node, it creates one self-signed certificate with a validity of 14 days, starting immediately, and another certificate with the 14 day valididity period starting on the expiry date of the first certificate. The node advertises a multiaddr containing the certificate hashes of these two certificates.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
Once the first certificate has expired, the node prepares the next certificate, and updates the multiaddr it advertises.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved

## Addressing

Webtransport multiaddresses are composed of a QUIC multiaddr, followed by `/webtransport` and a list of multihashes of the certificates that the server uses.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
Examples:
* `/ip4/1.2.3.4/udp/443/quic/webtransport/certhash/<hash1>`
* `/ip6/fe80::1ff:fe23:4567:890a/udp/1234/quic/webtransport/certhash/<hash1>/certhash/<hash2>/certhash/<hash3>`
Copy link
Contributor

@elenaf9 elenaf9 Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we call it /certhash, instead of just adding a more general /multihash? The latter could then also be used in the future by other protocols that need to include a multihash in the adress for whatever reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some discussion here: multiformats/multiaddr#130. But I think the important part is that we can be a bit more specific here to highlight that this is a certificate hash rather than a hash for some other (?) thing. We also don't have a use case for a generic hash, but do have this use case for the certificate hash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vote for more specific field name too. it consumes less encoding space and allows easier extension.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that being specific pays off here, by making us more future-proof.
Imagine we want to add another hash-like component to a multiaddr in the future. We'd now use /hash for the certificate hash and for that new thing. How would we know which of these is a certificate hash and which of them the new thing?


## WebTransport HTTP endpoint

WebTransport needs a HTTPS URL to establish a WebTransport session, e.g. `https://example.com/webtransport`. As multiaddrs don't allow the encoding of URLs, this spec standardizes the endpoint. The HTTP endpoint of a libp2p WebTransport server MUST be located at `/.well-known/libp2p-webtransport`.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved

To allow future evolution of the way we run the libp2p handshake over WebTransport, we use a URL parameter. The handshake described in this document MUST be signaled by setting the `type` URL parameter to `noise`.

Example: The WebTransport URL of a WebTransport server advertising `/ip4/1.2.3.4/udp/1443/quic/webtransport/` would be `https://1.2.3.4:1443/.well-known/libp2p-webtransport?type=noise`.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved

## Security Handshake

Unfortunately, the self-signed certificate doesn't allow the nodes to authenticate each others' peer IDs. It is therefore necessary to run an additional libp2p handshake on a newly established WebTransport connection.
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
The first stream that the client opens on a new WebTransport session is used to perform a libp2p handshake using Noise (https://github.com/libp2p/specs/tree/master/noise). The client SHOULD start the handshake right after sending the CONNECT request, without waiting for the server's response.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a curious question regarding handshake starting right after Connect. Is connect referring to establishing a socket level connection?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is WebTransport CONNECT request as described in https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3-03#section-3.2.


In order to verify end-to-end encryption of the connection, the peers need to establish that no MITM intercepted the connection. To do so, the server MUST include the certificate hash of the currently used certificate as well as the certificate hashes of all future certificates it has already advertised to the network in the `webtransport_certhashes` Noise extension (see Noise Extension section of the [Noise spec](/noise/README.md)). The hash of recently used, but expired certificates SHOULD also be included.

On receipt of the `webtransport_certhashes` extension, the client MUST verify that the certificate hash of the certificate that was used on the connection is contained in the server's list. If the client was willing to accept multiple certificate hashes, but cannot determine which certificate was actually used to establish the connection (this will commonly be the case for browser clients), it MUST verify that all certificate hashes are contained in the server's list. If verification fails, it MUST abort the handshake.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to specify how the peer should detect and retire expired certificate? or is it true that the webtransport connections are shortlived so that the expiration is usually not an issue?


For the client, the libp2p connection is fully established once it has sent the last Noise handshake message. For the server, processing of that message completes the handshake.