Skip to content

Commit

Permalink
wgengine/magicsock: allow passing url dialer to derp client
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kylecarbs committed Mar 13, 2023
1 parent e2ae516 commit c653484
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
37 changes: 37 additions & 0 deletions derp/derphttp/derphttp_client.go
Expand Up @@ -61,6 +61,10 @@ type Client struct {
logf logger.Logf
dialer func(ctx context.Context, network, addr string) (net.Conn, error)

// regionDialer allows the caller to override the dialer used to
// connect to DERP regions. If nil, the default dialer is used.
regionDialer func(ctx context.Context, r *tailcfg.DERPRegion) net.Conn

// Either url or getRegion is non-nil:
url *url.URL
getRegion func() *tailcfg.DERPRegion
Expand Down Expand Up @@ -313,6 +317,32 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
}
}()

if c.regionDialer != nil {
conn := c.regionDialer(ctx, reg)
if conn != nil {
brw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
derpClient, err := derp.NewClient(c.privateKey, conn, brw, c.logf,
derp.MeshKey(c.MeshKey),
derp.CanAckPings(c.canAckPings),
derp.IsProber(c.IsProber),
)
if err != nil {
return nil, 0, err
}
if c.preferred {
if err := derpClient.NotePreferred(true); err != nil {
go conn.Close()
return nil, 0, err
}
}
c.serverPubKey = derpClient.ServerPublicKey()
c.client = derpClient
c.netConn = conn
c.connGen++
return c.client, c.connGen, nil
}
}

var node *tailcfg.DERPNode // nil when using c.url to dial
switch {
case c.useWebsockets():
Expand Down Expand Up @@ -513,6 +543,13 @@ func (c *Client) SetURLDialer(dialer func(ctx context.Context, network, addr str
c.dialer = dialer
}

// SetRegionDialer sets the dialer to use for dialing DERP regions.
func (c *Client) SetRegionDialer(dialer func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn) {
c.mu.Lock()
c.regionDialer = dialer
c.mu.Unlock()
}

// SetForcedWebsocketCallback is a callback that is called when the client
// decides to force WebSockets on the next connection attempt.
func (c *Client) SetForcedWebsocketCallback(callback func(region int, reason string)) {
Expand Down
16 changes: 16 additions & 0 deletions wgengine/magicsock/magicsock.go
Expand Up @@ -349,6 +349,9 @@ type Conn struct {
// headers that are passed to the DERP HTTP client
derpHeader atomic.Pointer[http.Header]

// derpRegionDialer is passed to the DERP client
derpRegionDialer atomic.Pointer[func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn]

// stats maintains per-connection counters.
stats atomic.Pointer[connstats.Statistics]

Expand Down Expand Up @@ -1514,6 +1517,10 @@ func (c *Conn) derpWriteChanOfAddr(addr netip.AddrPort, peer key.NodePublic) cha
if header != nil {
dc.Header = header.Clone()
}
dialer := c.derpRegionDialer.Load()
if dialer != nil {
dc.SetRegionDialer(*dialer)
}

ctx, cancel := context.WithCancel(c.connCtx)
ch := make(chan derpWriteRequest, bufferedDerpWritesBeforeDrop)
Expand Down Expand Up @@ -2367,6 +2374,15 @@ func (c *Conn) SetDERPHeader(header http.Header) {
c.derpHeader.Store(&header)
}

func (c *Conn) SetDERPRegionDialer(dialer func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn) {
c.derpRegionDialer.Store(&dialer)
c.mu.Lock()
defer c.mu.Unlock()
for _, d := range c.activeDerp {
d.c.SetRegionDialer(dialer)
}
}

func (c *Conn) SetNetworkUp(up bool) {
c.mu.Lock()
defer c.mu.Unlock()
Expand Down

0 comments on commit c653484

Please sign in to comment.