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

wgengine/magicsock: allow passing region dialer to derp client #13

Merged
merged 1 commit into from Mar 14, 2023

Conversation

kylecarbs
Copy link
Member

@kylecarbs kylecarbs commented Mar 13, 2023

Coder pods using the embedded relay would dial the access URL to dial DERP. This is unnecessary and led to oddities in deployments with restricted networking.

This will allow us to directly dial the DERP server, eliminating the external network path entirely.

See tailscale#7557

@kylecarbs kylecarbs requested a review from mafredri March 13, 2023 18:11
@kylecarbs kylecarbs self-assigned this Mar 13, 2023
if c.nodeDialer != nil {
conn, err := c.nodeDialer(ctx, n)
// If both conn and err are nil, fallback to default behavior.
if conn != nil || err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this mean we never return conn since we return nil, err below?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ahh, oops! I intended to return both.

@@ -513,6 +517,11 @@ func (c *Client) SetURLDialer(dialer func(ctx context.Context, network, addr str
c.dialer = dialer
}

// SetNodeDialer sets the dialer to use for dialing DERP nodes.
func (c *Client) SetNodeDialer(dialer func(ctx context.Context, node *tailcfg.DERPNode) (net.Conn, error)) {
c.nodeDialer = dialer
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to protect via mutex or is this invoked synchronously at a safe time?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's invoked synchronously, but I'll add a mutex to be safe.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!

@kylecarbs kylecarbs force-pushed the derpurldialer branch 4 times, most recently from e281f64 to c653484 Compare March 13, 2023 19:51
c.derpRegionDialer.Store(&dialer)
c.mu.Lock()
defer c.mu.Unlock()
for _, d := range c.activeDerp {
Copy link
Member

Choose a reason for hiding this comment

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

Is there any chance c.activeDerp could contain a result where d.c is the c *Conn itself? Thus leading to a mutex deadlock?

Copy link
Member

Choose a reason for hiding this comment

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

Or maybe d.c refers to client, in which case there should be no issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

d.c refers to client, so should be good I believe!

derp.IsProber(c.IsProber),
)
if err != nil {
return nil, 0, err
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return nil, 0, err
go conn.Close()
return nil, 0, err

Copy link
Member Author

Choose a reason for hiding this comment

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

It doesn't do this below, so I don't think it's necessary here.

Somewhat related tailscale#7557

Copy link
Member

@mafredri mafredri Mar 14, 2023

Choose a reason for hiding this comment

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

The reason it's OK below is that a defer func is created that checks the return error and closes tcpConn if there was an error. Here, however, regionDialer could have allocated resources/goroutines that need to be torn down or otherwise they will leak. That's why we need the close here.

Edit: Granted, I didn't verify that it's actually OK below. As long as the TLS client doesn't need to be torn down, should be fine.

As for the websocket dial, it's unclear if we should do a close there as well or if that'll be guaranteed by the context (it'd definitely be safer to close there as well).

Coder pods using the embedded relay would dial the access URL to dial
DERP. This is unnecessary and led to oddities in deployments with restricted
networking.

This will allow us to directly dial the DERP server, eliminating the
external network path entirely.
@kylecarbs kylecarbs changed the title wgengine/magicsock: allow passing url dialer to derp client wgengine/magicsock: allow passing region dialer to derp client Mar 14, 2023
@kylecarbs kylecarbs merged commit d9efcc0 into main Mar 14, 2023
21 of 25 checks passed
@kylecarbs kylecarbs deleted the derpurldialer branch March 14, 2023 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants