Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Event for user's NAT Device Type: Tell user if the node is behind an Easy or Hard NAT #173

Merged
merged 10 commits into from
Feb 18, 2021

Conversation

aarshkshah1992
Copy link
Contributor

@aarshkshah1992 aarshkshah1992 commented Jan 27, 2021

For libp2p/go-libp2p#1039.

Emit event to inform user of the NAT Device Type wrt BAT traversal i.e. Easy NAT(supports consistent endpoint translation) or Hard NAT(does NOT support consistent endpoint translation).

// NATDeviceTypeUnknown indicates that the type of the NAT device is unknown.
NATDeviceTypeUnknown NATDeviceType = iota

// NATDeviceTypeEasy indicates that the NAT device is an Easy NAT i.e. it supports consistent endpoint translation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we provide the precise definitions of
(a) the heuristic used to determine this
and
(b) what we mean by 'consistent endpoint translation' - do you mean that the externally bound host:port is the same for all remote hosts, stable for different ports of a single remote host, or once mapped allows inbound from a specifically negotiated remote host?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the docs to use the terms used in scientific literature and explain consistent endpoint translation in relation to those terms.

package network

// NATDeviceType indicates the type of the NAT device i.e. whether it is a Hard or an Easy NAT.
type NATDeviceType int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to have this definition of nat type be merged with the existing network.Reachability

this seems to be a sub-division of what's currently used for network.ReachabilityPrivate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@willscott

Considering that we need this event on a per transport protocol basis, it'll be extremely tricky to combine this with the Reachability event. I've updated the docs to inform the users that they should ALSO consume the Reachability event and use this NAT type event ONLY if Reachability=Private.

Copy link
Contributor

@marten-seemann marten-seemann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does "consistent endpoint translation" mean the following: For connection originating from IP:port A, the NAT will always use B as the source 2-tuple on outgoing packets?
That would also mean that if you dial form A', you'd get a different address B', i.e. users have to use SO_REUSEPORT / SO_REUSEADDR in TCP / multiplex connections in QUIC, right?

event/nattype.go Outdated
NATDeviceUDP NATDeviceProtocol = iota
// NATDeviceTCP means that the NAT Device Type has been determined for the TCP Protocol.
NATDeviceTCP
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this in package event, but NATDeviceType is in network?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because event. NATDeviceType dosen't make sense. We might have references to just the NATDeviceType in the code elsewhere and storing it as network.NATDeviceType is more readable.

We do something similar with network.Reachability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. But what about network.NATTransportProtocol?
Not sure about our package structure here tbh, just asking.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marten-seemann

On further thought, I agree with you. Have fixed this by moving the Transport Protocol to the network package as well.

)

func (r NATDeviceType) String() string {
str := [...]string{"Unknown", "Easy", "Hard"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allocates, doesn't it? A switch statement would be free in terms of memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@marten-seemann
Copy link
Contributor

Are "Hard NAT" and "Easy NAT" the terms used in the scientific literature regarding NATs?

@aarshkshah1992
Copy link
Contributor Author

aarshkshah1992 commented Jan 28, 2021

@marten-seemann @willscott

I've updated the PR to use the NAT terms used in scientific literature and have made the documentation juicier to explain what those NATs mean and how they relate to hole punching. Please let me know what you think.

Copy link
Contributor

@marten-seemann marten-seemann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation is A LOT better now!

network/nattype.go Outdated Show resolved Hide resolved
// to the same IP address and port irrespective of the destination address.
// With Regards to Internet Society RFC 3489, this could be either a Full Cone NAT, a Restricted Cone NAT or a
// Port Restricted Cone NAT. However, we do NOT differentiate between them here and simply classify all such NATs as a Cone NAT.
// NAT traversal with hole punching is possible with a Cone NAT if the remote peer is ALSO behind a Cone NAT.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// NAT traversal with hole punching is possible with a Cone NAT if the remote peer is ALSO behind a Cone NAT.
// NAT traversal with hole punching is possible with a Cone NAT, even if the remote peer is also behind a Cone NAT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marten-seemann

I've updated the comment to reflect that hole punching will work ONLY if the remote peer is also behind a Cone NAT and fail if the remote peer is behind a Symmetric NAT.

network/nattype.go Outdated Show resolved Hide resolved
network/nattype.go Outdated Show resolved Hide resolved
@aarshkshah1992
Copy link
Contributor Author

@marten-seemann

I've addressed all your comments. Thanks !

@aarshkshah1992
Copy link
Contributor Author

Hey @marten-seemann

Please approve if happy !

@aarshkshah1992
Copy link
Contributor Author

cc @vyzo for review.

Copy link
Contributor

@vyzo vyzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a small objection on the name of the event.

event/nattype.go Show resolved Hide resolved
@aarshkshah1992
Copy link
Contributor Author

@vyzo Please can you approve the PR ?

@aarshkshah1992 aarshkshah1992 merged commit 412dbb3 into master Feb 18, 2021
@aarshkshah1992 aarshkshah1992 deleted the feat/nat-type-evt branch February 18, 2021 08:47
@Stebalien Stebalien mentioned this pull request May 11, 2021
27 tasks
@aschmahmann aschmahmann mentioned this pull request May 14, 2021
71 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants