-
Notifications
You must be signed in to change notification settings - Fork 1k
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
protocols/: Add basic AutoNAT implementation #2262
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that was quick! Thanks.
As an aside, great to see libp2p-request-response
being useful here.
Can you reference the new crate in src/lib.rs
? Similar to:
Lines 58 to 61 in c7abb6f
#[cfg(feature = "floodsub")] | |
#[cfg_attr(docsrs, doc(cfg(feature = "floodsub")))] | |
#[doc(inline)] | |
pub use libp2p_floodsub as floodsub; |
Listing a couple of things needed beyond a basic version. Unfortunately the current draft of the specification is still very basic, thus many of these likely need design work as well.
- Expose whether the local node is publicly reachable or not. (e.g. needed for
libp2p-kad
to decide to run in client or server mode Support client mode in kademlia #2184). - Implement various rate limiting to prevent attacks.
- Continuously trigger probes for local external addresses.
- ...
Ok so I would propose some additional logic:
It will then send a
If we are in I think this is also a bit more aligned with what is described in the specs PR. Wdyt @mxinden? |
Thanks for the follow-up @elenaf9!
Is that a strict requirement? It would be great for
Sounds good to me. We can likely learn a bunch from the Golang implementation, which is set to assume it is public on 3 successes.
Reporting through
Sounds good to me. We can likely use the Golang defaults at the beginning, right?
👍 good idea.
How about keeping track of all the peers we are connected to. On an interval, we chose one of them at random and ask them to dial us. Results of those dials then influence whether we assume we are publicly reachable or not. |
Crossreferencing libp2p/specs#369 here which we will very much need in an initial version. Don't want libp2p to become the next amplification attack network 😨 |
7400ab0
to
9f63141
Compare
9f63141
to
066c7cf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay here.
I have now refactored a majority of the behaviour logic according to the above comments. It is now also more aligned with the go-autonat implementation, which btw helped a lot thanks! There is still quite a lot missing, especially regarding config parameters and the calculation of the retry-nat-status frequency, and tests of course.
I hope I'll find more time towards this weekend / next week to invest into this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clean and comprehensible code!
From a features perspective, I think this is sufficient for a first version.
I haven't had a chance to test this out, which I would like to do before merging and releasing it.
Have you had a chance to test this (a) in the wild and (b) with the Golang implementation?
@elenaf9 could you provide some basic example to use it ? |
@canewsin I will definitely add some test & code-docs that will exemplify how this can be used. But I currently don't have the capacity to add a full example, though I agree that it would be great to have one that combines AutoNAT with e.g. Kademlia and the Relay protocol. But imo that would be an issue on its own. Btw if you are generally interested in AutoNAT, it would also be great to have your review on it. Since @mxinden stated that the features are sufficient for a first version, the only thing left for this for this PR is to resolve the review and add docs & tests. If you feel like there's anything else missing, feel free to comment on it. |
Add `AsClient` and `AsServer` views for the Behaviour to separate the logic of the two roles. Instead of adding permanent (sub-)structs to the Behaviour, the two new structures only hold temporary references to the parent fields. This allows shared access to fields that are used by both structures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One small suggestion. Otherwise code looks good to me. Thank you for the continuous work here.
My public server identifies itself as private which is odd (StatusChanged { old: Unknown, new: Private }
), though that might be on my end. Still need to investigate further.
Never mind, this has been a mistake on my end. Public server successfully reports being public ( 🚀 |
Track all non-relayed addresses of the remote. On inbound dial-back request select one of these addresses as observed one, reject dial-back if there are none (i.g. all connections are relayed).
One more note regarding the changed specs for autonat in libp2p/specs#386:
The request-response protocol does not bubble up the info on via what specific connection a request was received (if we have multiple active connections), so we can not check if that specific connection is relayed or not. |
Agreed that this fulfills the requirement. Thanks for double-checking. |
protocols/autonat/src/protocol: Use ResponseStatus::from_i32
That was fast. Thanks! I was about to comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Ready to merge from my side.
Unless there are any further comments I will merge tomorrow.
🚀 Again, thanks @elenaf9 for the continuous work here. A very important piece of libp2p's hole punching story. |
This commit adds a behaviour protocol that implements the AutoNAT specification. It enables users to detect whether they are behind a NAT. The Autonat Protocol implements a Codec for the Request-Response protocol, and wraps it in a new Network Behaviour with some additional functionality. Co-authored-by: David Craven <[email protected]> Co-authored-by: Max Inden <[email protected]>
This commit adds a behaviour protocol that implements the AutoNAT specification. It enables users to detect whether they are behind a NAT. The Autonat Protocol implements a Codec for the Request-Response protocol, and wraps it in a new Network Behaviour with some additional functionality. Co-authored-by: David Craven <[email protected]> Co-authored-by: Max Inden <[email protected]>
This PR drafts a behaviour protocol that implements basic AutoNAT. It is based on #1672 (minus #1667) from @dvc94ch .
The Autonat Protocol implements a Codec for the Request-Response protocol, and wraps it in a new Network Behaviour with some additional functionality. The basic idea is:
See #2262 (comment) description of the most recent implementation.
0
), or external addresses observed by other peers (initial Score:1
).DialRequest
to B, with all addresses from the above list (ordered by Address Score, descending)Ok(address)
it increases the address score of this address by1
Contrary to Autonat #1672, this implementation of the AutoNAT Protocol has noOutEvent
. Instead, when increasing a peer's score aNetworkBehaviourAction::ReportObservedAddr
with the current score is reported to to the Swarm.