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

Improving how headscale handles the client startup process #31

Merged
merged 2 commits into from
May 29, 2021

Conversation

juanfont
Copy link
Owner

@juanfont juanfont commented May 24, 2021

As discussed in Gitter (https://gitter.im/headscale-dev/community?at=60a9618c801b07264e631b7f), there is some weirdness in how the tailscale clients first interact with the control server in the /map endpoint.

The client uses tailcfg.MapRequest to indicate the different stages of its startup process. At the beginning of the interaction, the client just expects an updated tailcfg.DERPMap - not the full list of its peers. It will close the connection as soon as it receives the first tailcfg.MapResponse.

With this PR headscale closes the connection when the client is expecting so, in these initial interactions to /map. In these stages it does not start the keepAlives either.

I don't think this is completely solved, so I added a few more logging messages to track this.

Copy link
Contributor

@cure cure left a comment

Choose a reason for hiding this comment

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

I tried the code, and it seems to work, so that's good! With the tweaks below it should be good to merge.

Judging by the tailscale source, we should be getting three requests in quick succession on startup:

  • ReadOnly=true, OmitPeers=true, Stream=false (aka "give me the DERP map, ignore my endpoint update, it is empty/meaningless")
  • ReadOnly=false, OmitPeers=true, Stream=false (aka "here's my endpoint update, don't stream to me")
  • ReadOnly=false, OmitPeers=false, Stream=true (aka the HTTP Long Poll connection)

It seems that the client sometimes remembers the DERP map from a previous invocation, which means it skips the first request.

api.go Outdated
return
}
if req.OmitPeers {
log.Printf("[%s] Client is starting up. Ready to receive the peers", m.Name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on the comments from the tailscale source, this log line isn't quite right. How about something like this instead:

log.Printf("[%s] Client sent endpoint update and is ok with a response without peer list.", m.Name)

Arguably this log messing is kind of meaningless in day to day operation; this would be a good candidate for a debug level log message I think.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fully agree. This messages should be disabled once we are confident with our interpretation of the protocol.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fully agree. This messages should be disabled once we are confident with our interpretation of the protocol.

api.go Outdated
c.Data(200, "application/json; charset=utf-8", *data)
return
}
if req.OmitPeers {
Copy link
Contributor

@cure cure May 26, 2021

Choose a reason for hiding this comment

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

I think that the tailscale client currently only uses the combination of OmitPeers == true and Stream == false, and logically that seems to be the intention, but we should probably be explicit about that expectation How about we change this if to

  if req.OmitPeers && ! req.Stream {
     ...
  } else if req.OmitPeers && req.Stream {
    log.Printf("[%s] Warning, ignoring request, don't know how to handle it", m.Name)
    // send 400 error code back with empty json response

    return
  } 

Copy link
Owner Author

Choose a reason for hiding this comment

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

Implemented!

Copy link
Contributor

@cure cure left a comment

Choose a reason for hiding this comment

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

LGTM thanks!

@juanfont
Copy link
Owner Author

Let's merge then!

@juanfont juanfont merged commit 094fde3 into main May 29, 2021
@juanfont juanfont deleted the improving-client-startup branch September 27, 2021 09:58
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