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

reject hole punching attempts when we don't have any public addresses #1214

Merged
merged 3 commits into from
Nov 16, 2021

Conversation

marten-seemann
Copy link
Contributor

@marten-seemann marten-seemann commented Sep 30, 2021

If we don't have any public addresses, the hole punch attempt is bound to fail - there's no address that can be used to dial us.

Question: Any idea how to fix the tests? IDService.OwnObservedAddrs() always returns an empty set of addresses, as we're not really running the ID protocol (and we're only listening on localhost anyway). The obvious solution would be to mock the IDService, but it's not an interface.

@marten-seemann marten-seemann force-pushed the dont-holepunch-if-no-addresses branch 2 times, most recently from e24daa6 to 2c760aa Compare October 2, 2021 17:50
@@ -219,6 +221,10 @@ func (hs *Service) directConnect(rp peer.ID) error {
}
}

if len(hs.ids.OwnObservedAddrs()) == 0 {
return errors.New("can't initiate hole punch, as we don't have any public addresses")
Copy link
Contributor

Choose a reason for hiding this comment

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

let's make this a named error, we use it in a few places.

Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't have to be public.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's keep them different for now. This will make debugging easier.

obsDial := addrsFromBytes(msg.ObsAddrs)
obsDial := removeRelayAddrs(addrsFromBytes(msg.ObsAddrs))
if len(obsDial) == 0 {
return 0, nil, fmt.Errorf("expected CONNECT message to contain at least one message")
Copy link
Contributor

Choose a reason for hiding this comment

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

why fmt.Errorf? There is no interpolation here.

Copy link
Contributor

Choose a reason for hiding this comment

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

also, named error as well would be nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Converted to errors.New.

@Stebalien Stebalien removed their request for review October 8, 2021 16:47
@Stebalien Stebalien requested a review from vyzo October 21, 2021 15:07
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, but can we address the (minor) comments?

@marten-seemann
Copy link
Contributor Author

I'm working on an update to this PR: We should wait until we actually have a public address, before we:

  1. initiate hole punch attempts (direct connection attempts are ok)
  2. install the hole punch protocol

The problem I'm running into is mostly how to test this.

@marten-seemann
Copy link
Contributor Author

@vyzo I made the changes to the coordination protocol: We now only start the hole punching service once we have a public address (without a publicly dialable address, there’s no way a hole punch can succeed: the peer wouldn’t even know who to dial). I think that the code is correct as it is right now.

Even after a long time of playing around with this code, I can’t find a way to make the tests work. The problem is that

  1. we only start the hole punch service once we have a public address
  2. we try a direct dial if a node has a public address (note that a direct dial always succeeds in the setup, since we don't have an actual NAT implementation)

Any idea how to proceed here?

@vyzo
Copy link
Contributor

vyzo commented Oct 26, 2021 via email

@marten-seemann
Copy link
Contributor Author

can we clobber manet's private address ranges so that IsPublicAddr returns true?

We can, and that would allow us to start the holepunch service. But that would also mean that the check if any of the peer's addresses are public in

if manet.IsPublicAddr(a) && !isRelayAddress(a) {

would succeed, and we wouldn't holepunch, but do a direct connect instead.

@vyzo
Copy link
Contributor

vyzo commented Oct 26, 2021

it is even worse: when we enable autotelay, we install an address factory that will rewrite Addrs and end up nevwr having a public address.
We need access to observed addresses.

@marten-seemann
Copy link
Contributor Author

I updated this PR, using the observed addresses to determine if we have a public address. Also, we can't listen for the EvtLocalAddressesUpdated event, since it's not emitted when identify gives us a new public address. Unfortunately, we don't have any event for this, so we'll have to run the check repeatedly on a timer.

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.

looks good, can we also fix the two small nits?

@marten-seemann marten-seemann merged commit 8df3600 into master Nov 16, 2021
@marten-seemann marten-seemann deleted the dont-holepunch-if-no-addresses branch November 16, 2021 11:06
@aschmahmann aschmahmann mentioned this pull request Dec 1, 2021
80 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants