From 2d9612997494b9c4aed3eefa6043a9e97f748716 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 5 Aug 2021 11:55:14 +0200 Subject: [PATCH 1/2] *: Address security-protocol-in-multiaddr and relay conflict This patch addresses the problems below by detailing the solution below in the corresponding specifications. > Taxonomy: > > * `A`: The destination node. > > * `B`: The source node. > > * `R`: The relay node. > > * outer connection: The connection from `R` to `A`. > > * relayed (inner) connection: The relayed (inner) connection from `B` to > `A`. > > > Problems we need to solve: > > 1. `B` and `A` need to know which security protocol to use to upgrade the > relayed (inner) connection. > > 2. In the case of active relaying, `R` needs to know which security > protocol to use to upgrade the outer connection to the destination. > > 3. `A` should be able to offer different security protocols for the > relayed (inner) connection. `A` can use different layer 4 ports to > demultiplex security protocols for the outer connection. `A` has no > demultiplexing mechanism for the security protocols used for the > relayed (inner) connection. Thus if `A` advertises different > multiaddresses with different security protocols for the relayed > (inner) connection, it has no way to determine which one to use on > incoming relayed (inner) connections. > > > We propose two mechanisms to solve the issues above: > > 1. We have to somehow embed both outer and inner security protocol in the > multiaddr. What we could do is introduce another separator, e.g. > `p2p-circuit-inner` (name yet to be determined). > > * **Solving (1)**: A multiaddr for a passive relayed connection could > then look like: > `/ip4/../tcp/../tls/p2p/QmRelay/p2p-circuit/p2p/QmA/p2p-circuit-inner/noise`, > with `noise` being used to secure the relayed (inner) connection. * > * **Solving (2)**: A multiaddr for an active relayed connection could > then look like: > `/ip4/../tcp/../tls/p2p/QmRelay/p2p-circuit/ip6/::1/tls/p2p/QmA/p2p-circuit-inner/noise`, > with `tls` being used to secure the outer connection and `noise` > being used to secure the relayed (inner) connection. > > 2. **Solving (3)**: In order for `A` to be able to advertise different > multiaddresses with different security protocols for the relayed > (inner) connection, while still being able to choose the right security > protocol on incoming relayed (inner) connections, we need to include > the security protocol for the relayed (inner) connection in the circuit > relay v2 CONNECT message from `B` to `A`. See https://github.com/libp2p/specs/pull/349#discussion_r677541548 for details. --- addressing/README.md | 56 +++++++++++++++++++++++++++++++++++++++----- relay/circuit-v2.md | 51 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/addressing/README.md b/addressing/README.md index abc6bc51a..68aa91df0 100644 --- a/addressing/README.md +++ b/addressing/README.md @@ -202,7 +202,7 @@ within](#encapsulation) another multiaddr. For example, the above `p2p` address can be combined with the transport address on which the node is listening: -``` +``` /ip4/7.7.7.7/tcp/1234/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N ``` @@ -235,7 +235,7 @@ appreciated. Most libp2p transports use the IP protocol as a foundational layer, and as a result, most transport multiaddrs will begin with a component that represents an -IPv4 or IPv6 address. +IPv4 or IPv6 address. This may be an actual address, such as `/ip4/7.7.7.7` or `/ip6/fe80::883:a581:fff1:833`, or it could be something that resolves to an IP @@ -255,7 +255,7 @@ resolvable or "name-based" protocols: When the `/dns` protocol is used, the lookup may result in both IPv4 and IPv6 addresses, in which case IPv6 will be preferred. To explicitly resolve to IPv4 -or IPv6 addresses, use the `/dns4` or `/dns6` protocols, respectively. +or IPv6 addresses, use the `/dns4` or `/dns6` protocols, respectively. Note that in some restricted environments, such as inside a web browser, libp2p may not have access to the resolved IP addresses at all, in which case the @@ -305,7 +305,7 @@ wherever TCP/IP sockets are accessible. Addresses for the TCP transport are of the form `/tcp/`, where `` is a multiaddr that resolves to an IP address, as -described in the [IP and Name Resolution section](#ip-and-name-resolution). +described in the [IP and Name Resolution section](#ip-and-name-resolution). The `` argument must be a 16-bit unsigned integer. ### WebSockets @@ -324,7 +324,7 @@ multiaddr format mirrors this arrangement. A libp2p QUIC multiaddr is of the form `/udp//quic`, where `` is a multiaddr that resolves to an IP address, as -described in the [IP and Name Resolution section](#ip-and-name-resolution). +described in the [IP and Name Resolution section](#ip-and-name-resolution). The `` argument must be a 16-bit unsigned integer in network byte order. @@ -354,7 +354,7 @@ destination peer. A full example would be: -``` +``` /ip4/127.0.0.1/tcp/5002/p2p/QmdPU7PfRyKehdrP5A3WqmjyD6bhVpU1mLGKppa2FjGDjZ/p2p-circuit/p2p/QmVT6GYwjeeAF5TR485Yc58S3xRF5EFsZ5YAF4VcP3URHt ``` @@ -363,6 +363,50 @@ Here, the destination peer has the peer id relay node with peer id `QmdPU7PfRyKehdrP5A3WqmjyD6bhVpU1mLGKppa2FjGDjZ` running on TCP port 5002 of the IPv4 loopback interface. +#### Relay addresses and multiaddr security component + +Instead of negotiating the security protocol in-band, security protocols should +be encapsulated in the multiaddr (see [The multiaddr security component +section](#the-multiaddr-security-component)). Establishing a single relayed +connection involves 3 security protocol upgrades: + +1. Upgrading the connection from the source to the relay. + + The security protocol is specified in the relay multiaddr (before + `p2p-circuit`). + + Example: `/ip4/6.6.6.6/tcp/1234/tls/p2p/QmRelay/p2p-circuit/` + +2. Upgrading the connection from the relay to the destination. + + The security protocol is specified in the destination multiaddr (after + `p2p-circuit`). + + Note: Specifying this security protocol is only necessary for active + relaying. In the case of passive relaying the connection established by the + destination to the relay will be used to relay the connection. + + Example: + - Passive relaying: `/p2p-circuit/p2p/QmDestination` + - Active relaying: `/p2p-circuit/ip4/6.6.6.6/tcp/1234/tls/p2p/QmDestination` + +3. Upgrading the relayed connection from the source to the destination. + + The security protocol is specified by appending + `/p2p-circuit-inner/` to the full + address. + + + + Example: `/p2p-circuit//p2p-circuit-inner/tls` + + Note: One might be tempted to not specify (3) and simply use the security + protocol in (2). This would break if the security protocol used for (2) can + not be used for (3), e.g. in the case where the relay establishes a QUIC + connection to the destination secured via TLS and the source only supports + Noise. + [peer-id-spec]: ../peer-ids/peer-ids.md [identify-spec]: ../identify/README.md diff --git a/relay/circuit-v2.md b/relay/circuit-v2.md index 90c7f8510..5db889689 100644 --- a/relay/circuit-v2.md +++ b/relay/circuit-v2.md @@ -294,6 +294,38 @@ Common failure status codes are: ***Note: implementations _should not_ accept connection initiations over already relayed connections*** +##### Security protocol selection for the relayed connection + +Instead of negotiating the security protocol in-band, security protocols should +be encapsulated in the multiaddr (see [The multiaddr security component +section](../addressing/README.md#the-multiaddr-security-component)). A relayed +connection is not an exception. A target advertises the support for a security +protocol for relayed connections by appending +`/p2p-circuit-inner/` to its relayed multiaddresses. An +initiator may include any set of relayed multiaddr in the `peer` field of +`HopMessage` on type `CONNECT` in which all addresses end with the same +`/p2p-circuit-inner/`. The initiator is thus signaling to the +target which security protocol, out of all advertised security protocols +by the target, the initiator chose to use on the relayed connection. + +As an example, let's say the target listens for incoming relayed connections via +relay `R1` and relay `R2`. In addition it supports both TLS Noise as security +protocols. It would then advertise the following relayed multiaddresses: + +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/tls` +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/tls` +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` + +Once the initiator received the above multiaddresses and decides to initiate a +relayed connection to the target, it needs to decide whether it wants to secure +the relayed connection via TLS or Noise. Say it decides for Noise it would then +include the multiaddresses below in it `HopMessage` with type `Connect` in the +`peer` field: + +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` +- `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` + ### Stop Protocol The Stop protocol governs connection termination between the relay and the target peer; @@ -309,11 +341,13 @@ The relay sends a `StopMessage` with `type = CONNECT` and the following form: ``` StopMessage { type = CONNECT - peer = Peer { ID = ...} + initiator = Peer { ID = ...} + target = Peer { addrs = ...} limit = Limit { ...} } ``` -- the `peer` field contains a `Peer` struct with the peer `ID` of the connection initiator. +- the `initiator` field contains a `Peer` struct with the peer `ID` of the connection initiator. +- the `target` field contains a `Peer` struct with the peer `addrs` of the target that the initiator included in its `HopMessage`. - the `limit` field, if present, conveys the limits applied to the relayed connection with the semantics described [above](#reservation). If the target peer accepts the connection it responds to the relay with a `StopMessage` of `type = STATUS` and `status = OK`: @@ -330,6 +364,16 @@ If the target fails to terminate the connection for some reason, then it respond Common failure status codes are: - `CONNECTION_FAILED` if the target internally failed to create the relayed connection for some reason. +#### Security protocol selection for the relayed connection + +A target may advertise support for different security protocols by advertising +multiple multiaddresses with different `/p2p-circuit-inner/` +suffixes. A target needs some mechanism to determine which of the advertised +security protocols the initiator intends to use to secure an incoming relayed +connection. The target can use the addresses included in the `target` field of +the `StopMessage` to determine which security protocol the initiator chose to +secure the relayed connection. + ### Reservation Vouchers Successful relay slot reservations should come with _Reservation Vouchers_. @@ -383,7 +427,8 @@ message StopMessage { required Type type = 1; - optional Peer peer = 2; + optional Peer initiator = 2; + optional Peer target = 5; optional Limit limit = 3; optional Status status = 4; From 78444214d77ecbfad409eef84a6ad2400eec9c87 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 12 Aug 2021 10:48:01 +0200 Subject: [PATCH 2/2] relay/circuit-v2: Stress that relay security protocols have to match --- relay/circuit-v2.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/relay/circuit-v2.md b/relay/circuit-v2.md index 5db889689..cd173dbb7 100644 --- a/relay/circuit-v2.md +++ b/relay/circuit-v2.md @@ -326,6 +326,10 @@ include the multiaddresses below in it `HopMessage` with type `Connect` in the - `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` - `/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise` +Note that all addresses sent by the initiator in the `peer` field MUST share the +same security protocol for the relayed connection +(`/p2p-circuit-inner/`). + ### Stop Protocol The Stop protocol governs connection termination between the relay and the target peer; @@ -374,6 +378,11 @@ connection. The target can use the addresses included in the `target` field of the `StopMessage` to determine which security protocol the initiator chose to secure the relayed connection. +Note that all addresses sent by the initiator MUST share the same security +protocol for the relayed connection (`/p2p-circuit-inner/`). +Thus a target MUST abort the connection attempt (i.e. reset the stream) if it +receives a `CONNECT` with varying security protocols for the relay connection. + ### Reservation Vouchers Successful relay slot reservations should come with _Reservation Vouchers_.