Skip to content

Commit

Permalink
*: Address security-protocol-in-multiaddr and relay conflict (#359)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxinden authored Aug 12, 2021
1 parent 85f80ca commit c01af99
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 9 deletions.
56 changes: 50 additions & 6 deletions addressing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -305,7 +305,7 @@ wherever TCP/IP sockets are accessible.

Addresses for the TCP transport are of the form `<ip-multiaddr>/tcp/<tcp-port>`,
where `<ip-multiaddr>` 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 `<tcp-port>` argument must be a 16-bit unsigned integer.

### WebSockets
Expand All @@ -324,7 +324,7 @@ multiaddr format mirrors this arrangement.

A libp2p QUIC multiaddr is of the form `<ip-multiaddr>/udp/<udp-port>/quic`,
where `<ip-multiaddr>` 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 `<udp-port>` argument must be a 16-bit unsigned integer in network byte order.


Expand Down Expand Up @@ -354,7 +354,7 @@ destination peer.

A full example would be:

```
```
/ip4/127.0.0.1/tcp/5002/p2p/QmdPU7PfRyKehdrP5A3WqmjyD6bhVpU1mLGKppa2FjGDjZ/p2p-circuit/p2p/QmVT6GYwjeeAF5TR485Yc58S3xRF5EFsZ5YAF4VcP3URHt
```

Expand All @@ -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/<destination-multiaddr>`

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: `<relay-multiaddr>/p2p-circuit/p2p/QmDestination`
- Active relaying: `<relay-multiaddr>/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/<relayed-connection-security-protocol>` to the full
address.

<!-- TODO: Is `p2p-circuit-inner` the ideal name? Up for alternative
suggestions. -->

Example: `<relay-mulitaddr>/p2p-circuit/<destination-multiaddr>/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
Expand Down
60 changes: 57 additions & 3 deletions relay/circuit-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,42 @@ 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/<security-protocol>` 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/<security-protocol>`. 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:

- `<relay-R1-multiaddr>/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/tls`
- `<relay-R1-multiaddr>/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise`
- `<relay-R2-multiaddr>/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/tls`
- `<relay-R2-multiaddr>/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:

- `<relay-R1-multiaddr>/p2p-circuit/p2p/QmTarget/p2p-circuit-inner/noise`
- `<relay-R2-multiaddr>/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/<security-protocol>`).

### Stop Protocol

The Stop protocol governs connection termination between the relay and the target peer;
Expand All @@ -309,11 +345,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`:
Expand All @@ -330,6 +368,21 @@ 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/<security-protocol>`
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.

Note that all addresses sent by the initiator MUST share the same security
protocol for the relayed connection (`/p2p-circuit-inner/<security-protocol>`).
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_.
Expand Down Expand Up @@ -383,7 +436,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;
Expand Down

0 comments on commit c01af99

Please sign in to comment.