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

Multiaddr duplicated p2p protocol in relay reservation #2696

Closed
stormshield-pj50 opened this issue Jun 7, 2022 · 5 comments
Closed

Multiaddr duplicated p2p protocol in relay reservation #2696

stormshield-pj50 opened this issue Jun 7, 2022 · 5 comments

Comments

@stormshield-pj50
Copy link
Contributor

Summary

P2p protocol is duplicated in Multiaddr when a relay, using TCP transport with port reuse enabled, accepts a reservation request. This leads to an invalid Multiaddr.

In order to reproduce the bug, just turn on port reuse when creating TcpConfig in relay_v2 example:

let tcp_transport = TcpConfig::new();

Please find some of the logs dumped on the listening client showing the duplicated P2p protocol:

[2022-06-07T08:38:16Z INFO  client] Relay accepted our reservation request.
[2022-06-07T08:38:16Z INFO  client] Listening on "/ip4/$RELAY_SERVER_IP/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN/p2p-circuit/p2p/12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"

Expected behavior

The relayed Multiaddr should not contain a duplicated P2p protocol.

Possible Solution

Thought about 3 possibilities:

  1. In Identify: when building the observed response in Identify, do not include P2p protocol in the Multiaddr.
  2. In transports/tcp:
    fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
    the address_translation function should return the same kind of Multiaddr whether port reuse is enabled or not. So maybe patch the function in the match case when port reuse is on, and pop the P2p protocol if present.
  3. In relay_v2:
    .external_addresses()
    don't append P2p protocol if already present.

Also wondering if external and observed addresses need to contain the P2p protocol ?

Version

libp2p version 0.45

Would you like to work on fixing this bug?

Yes

@mxinden
Copy link
Member

mxinden commented Jun 8, 2022

3. In relay_v2:

.external_addresses()

I think this is the best way to tackle the issue. Thanks for debugging. Would you mind proposing a patch?

Also wondering if external and observed addresses need to contain the P2p protocol ?

I haven't put enough thoughts into this, though I think you are right.

@mxinden
Copy link
Member

mxinden commented Jun 10, 2022

Thanks for preparing #2701.

I have been thinking about this some more. Sorry for not doing so earlier.

The process of a client requesting a reservation with a relay:

  1. When accepting the reservation the relay tells the client its external addresses.
  2. The client needs to tell everyone else which relays it is listening via, i.e. needs to tell everyone else the addresses of the relay.

We need the /p2p/xxx component with the relay PeerId in the Multiaddr in step (2) in order to secure consecutive connections. Conceptually it does not matter whether the relay adds it to the Multiaddr before sending it in step (1) or the client adds it before step (2).

I wonder why I added the /p2p/xxx protocol before step (1) and not step (2). Off the top of my head the client should do it before (2), among other things to support relays that don't do so before (1).

I still need to research what the Go implementation does. As far as I can tell the Golang client implementation does not require the /p2p/xxx component.

https://github.com/libp2p/go-libp2p/blob/master/p2p/protocol/circuitv2/client/reservation.go#L94-L103

@marten-seemann in the Go implementation, does the relay add its PeerId to its Multiaddr when accepting a reservation, or does the client add the relay's PeerId to the relay's Multiaddr before advertising the final /p2p-circuit address to other peers?

Let me know if the above makes sense @Pj50. Again, sorry for not raising this earlier.

@stormshield-pj50
Copy link
Contributor Author

@mxinden Don't worry for your post being late, you summed up well the mechanism that adds the P2p protocol during relay reservation. Honestly I don't know which one between adding it before step(1) or before step (2) is the best.

@mxinden
Copy link
Member

mxinden commented Jun 14, 2022

Turns out, we actually settled on (1) in the past:

the addrs field contains all the public relay addrs, including the peer ID of the relay node but not the trailing p2p-circuit part;

https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md

Sorry for the noise here. Will review #2701 next.

@marten-seemann in the Go implementation, does the relay add its PeerId to its Multiaddr when accepting a reservation,

For the record, yes it does.

stormshield-pj50 added a commit to stormshield-pj50/rust-libp2p that referenced this issue Jun 15, 2022
stormshield-pj50 added a commit to stormshield-pj50/rust-libp2p that referenced this issue Jun 15, 2022
- Minor fixes after review
- Bump libp2p-relay Cargo.toml version to 0.9.2
- Add entry in Changelog for upcoming 0.9.2 version
@mxinden
Copy link
Member

mxinden commented Jun 27, 2022

Closing here with #2701 merged.

@mxinden mxinden closed this as completed Jun 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants