Closed marten-seemann closed 2 years ago
One case just popped up in my mind where I am not sure how to handle it for rust-autonat:
Let's assume Peer A
wants to know from Peer B
whether they (A
) can be dialed directly. At the moment A
is listening via a relay and A
and B
have already established a connection where B
is the Dialer, therefore B
observes A
with a relay address.
If I understand the Golang implementation correctly, B
would reject the DialRequest
, and A
would have to establish a new one to B
where A
is the dialer. Would it make sense that a DialRequest
in general should only be sent on connections where the sender is also the dialer, so that the receiver observes the correct address?
And what should happen if B
can not be dialed directly either?
Would it make sense that a DialRequest in general should only be sent on connections where the sender is also the dialer
In my eyes one should be able to send DialRequest
s both via a connection where one is the dialer and via a connection where one is the listener. Given that connection establishment is expensive, reusing existing connections, whether one is a dialer or listener, sounds reasonable.
so that the receiver observes the correct address?
I am not sure I follow. Both as a dialer and as a listener of a connection one knows the address of the remote peer. One might not observe the right port, though the AutoNAT protocol does not discriminate on the port, only on the IP. Am I missing something?
And what should happen if B can not be dialed directly either?
Off the top of my head, I don't think the overhead of establishing a new relayed connection is worth it, i.e. in case B can not be dialed directly, but only via a relay, I don't think they are a valid AutoNAT partner. I do think it is worth trying on an already established relayed connection.
And what should happen if B can not be dialed directly either?
Off the top of my head, I don't think the overhead of establishing a new relayed connection is worth it, i.e. in case B can not be dialed directly, but only via a relay, I don't think they are a valid AutoNAT partner. I do think it is worth trying on an already established relayed connection.
Sorry. This obviously conflicts with https://github.com/libp2p/specs/pull/362/commits/048bdbfe2439058c355db612eac717fc8a46acbb. My bad. One should not send nor accept DialRequest
s via relayed connections.
I am not sure I follow. Both as a dialer and as a listener of a connection one knows the address of the remote peer. One might not observe the right port, though the AutoNAT protocol does not discriminate on the port, only on the IP. Am I missing something?
Maybe I understand the relay protocol wrong.
I assumed that if a peer A
is listening via a relay, a remote observe them:
A
is the Listener -> remote would reject the autonat requestA
is a Dialer, because then the connection is not relayed -> remote would do the autonat requestIs this the case, or does the remote observe them at a relayed address in both cases?
I assumed that if a peer
A
is listening via a relay, a remote observe them:
- at the relayed address if
A
is the Listener -> remote would reject the autonat request
Correct. The remote would observe A
at /<relay-address>/p2p-circuit/p2p/<peer-id-of-A>
.
- at a "direct"/ non-relayed address if
A
is a Dialer, because then the connection is not relayed -> remote would do the autonat request
In the case where the remote is public and A
can dial the remote directly, the remote would observe A
as /<address-of-A>
. The remote should then not reject the autonat request.
In the case where the remote is not publicly reachable and is as well listening via some relay, A
would dial the remote via that relay. I don't think we defined how the remote would observe A
. The remote would only learn the peer ID and not the address of A
through the circuit relay v2 protocol:
the peer field contains a Peer struct with the peer ID of the connection initiator.
https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md#stop-protocol
The remote could infer the address of A
through some other means, e.g. retrieved via an identify protocol exchange. I would argue that the remote can not trust such address and thus should again reject the autonat request via the relayed address.
Does the above answer the question? Unfortunately this is not clearly defined. Thanks for raising it.
Discussed out of band that this is ready to merge.
On address prioritization
I read quite a bunch of NAT traversal related RFCs (4787, 5128, 4614, 5382, 7604, 7857, 5389, 8445)
At the current state of Project Flare, I think the only thing useful would be RFC8445, more specifically section 5 on (address) candidate selection.
https://datatracker.ietf.org/doc/html/rfc8445#section-5
They differentiate in 4 candidate types, depending on the mechanism the address was discovered through:
Section 5.1.2.1 then follows with a formula to prioritize among the many addresses depending on their type.
Would (a) the candidate type differentiation and (b) the proposed prioritization formula be something worth adopting in this specification or our implementations? What do you think @marten-seemann?