-
Notifications
You must be signed in to change notification settings - Fork 280
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
Implementation considerations for dialing interface #562
Comments
Currently, in nim-libp2p, we have a transport-level flag for port-reuse which is set to true if we detect that we are private I didn't follow the evolution of AutoNATv2, but I think we assumed that when you are private, you won't be used as a AutoNAT server, since the peer would have to hole-punch with you to reach you anyway |
The problem arises that when you are using port-reuse and you try to detect whether or not you are private, you might be accidentally setting up a hole-punch with the AutoNAT server and thus wrongly assume that you are public when you are not. |
Wouldn't it be the AutoNat server responsibility to use a random source port for the dial-back? |
@Menduist, to elaborate on @thomaseizinger's point. From RFC 4787
And on the filtering behaviour
|
This still results in the same conclusion I wrote in the PR description, right? That reusing ports is a per-connection setting and not a transport-level setting. |
No, because if you are private, you disable AutoNat server, and enable port binding globally
I see, I wasn't aware of this NAT configuration. But this seem impractical, it means we have to setup special connections to autonat servers? (Sorry, maybe I need to look more into autonatv2 before commenting, please let me know if I'm asking dumb questions) Not sure how it works in other libp2ps, but in nim we connect to random nodes, not knowing what their capabilities are, and then we might ask them to dial-back if we find that they support autonat. We currently don't know at time of dialing if we are going to use them as AutoNat server. |
Yeah, I realised this 10 minutes after writing the comment 😅. What you've described for nim is the same behaviour in go. I think we need to change the recommendation to not reuse port on the server side as opposed to the current recommendation of not reusing port on client side. |
Does nim-libp2p support hole-punching? If you are trying to hole punch to a node behind NAT, you want to reuse your port, even if you are publicly reachable, or am I missing something? |
I second this, I'd actually say we have to change the spec to say the dial back request MUST use a new port binding. In rust-libp2p we were planning to reuse ports by default for new connections. This ensures that the observed address by identify has a stable port and we can use that information for hole punching. For a dial back request, we would then explicitly make a connection with a new port binding. |
Yes
The private node can just dial back, no need for hole-punching (even if he just tries to hole-punch, we don't have to create an outgoing connection for it to succeed, it will just work) |
But for the hole-punch to succeed, the outgoing connection of the private node needs to have the public node's port as the destination right? If the incoming connection from the public node has a different source port (i.e. not reusing the binding), that won't work, will it? What am I missing? |
If public node P wants to connect to private node N He connects to N via relay, sends his public address via dcutr or identify, and N can connect to P directly, no need for P to establish a direct connection towards N |
Thanks! This conversation was very insightful. I've updated the issue in |
I'll close this as resolved, thanks everyone for the fruitful conversation :) |
Inspired by #559 (comment) and libp2p/rust-libp2p#4226, I'd be interested in having a discussion between the various implementations around what a "good" dialing interface looks like.
At the moment,
rust-libp2p
has:Transport::dial
Transport::dial_as_listener
(for hole-punching)For AutoNATv2, we'd need something like
Transport::dial_with_new_port
to avoid accidental hole-punching during the dial-back. Additionally, we currently have a transport-level setting for TCP to enable port-reuse. That applies to all dials.After thinking about how to implement this, I concluded that a better interface would be to remove the transport-level setting for port-reuse and instead allow protocols to choose on a per-connection basis, whether the connection should reuse a port.
That allows modules like dcutr to say that they definitely want port-reuse and the autonat module would do the opposite and always request a connection with an ephemeral port.
Knowing whether a particular connection reuses a port or not also allows identify to decide whether to report the observed address as an address candidate. (If we used an ephemeral port for the dial, there is no point in reporting the address observed by the remote because the port will be wrong.)
How are other implementations solving these issues? Did you come up with a similar abstraction?
cc @Menduist @marten-seemann
The text was updated successfully, but these errors were encountered: