Skip to content

Commit 0cda9db

Browse files
committed
wgengine/magicsock: allow passing url dialer to derp client
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.
1 parent e2ae516 commit 0cda9db

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

derp/derphttp/derphttp_client.go

+36
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ type Client struct {
6161
logf logger.Logf
6262
dialer func(ctx context.Context, network, addr string) (net.Conn, error)
6363

64+
// regionDialer allows the caller to override the dialer used to
65+
// connect to DERP regions. If nil, the default dialer is used.
66+
regionDialer func(ctx context.Context, r *tailcfg.DERPRegion) net.Conn
67+
6468
// Either url or getRegion is non-nil:
6569
url *url.URL
6670
getRegion func() *tailcfg.DERPRegion
@@ -313,6 +317,31 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
313317
}
314318
}()
315319

320+
if c.regionDialer != nil {
321+
conn := c.regionDialer(ctx, reg)
322+
if conn != nil {
323+
brw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
324+
derpClient, err := derp.NewClient(c.privateKey, conn, brw, c.logf,
325+
derp.MeshKey(c.MeshKey),
326+
derp.CanAckPings(c.canAckPings),
327+
derp.IsProber(c.IsProber),
328+
)
329+
if err != nil {
330+
return nil, 0, err
331+
}
332+
if c.preferred {
333+
// It's important that this happens in a goroutine because
334+
// of synchronous I/O woes.
335+
go derpClient.NotePreferred(true)
336+
}
337+
c.serverPubKey = derpClient.ServerPublicKey()
338+
c.client = derpClient
339+
c.netConn = conn
340+
c.connGen++
341+
return c.client, c.connGen, nil
342+
}
343+
}
344+
316345
var node *tailcfg.DERPNode // nil when using c.url to dial
317346
switch {
318347
case c.useWebsockets():
@@ -513,6 +542,13 @@ func (c *Client) SetURLDialer(dialer func(ctx context.Context, network, addr str
513542
c.dialer = dialer
514543
}
515544

545+
// SetRegionDialer sets the dialer to use for dialing DERP regions.
546+
func (c *Client) SetRegionDialer(dialer func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn) {
547+
c.mu.Lock()
548+
c.regionDialer = dialer
549+
c.mu.Unlock()
550+
}
551+
516552
// SetForcedWebsocketCallback is a callback that is called when the client
517553
// decides to force WebSockets on the next connection attempt.
518554
func (c *Client) SetForcedWebsocketCallback(callback func(region int, reason string)) {

wgengine/magicsock/magicsock.go

+16
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ type Conn struct {
349349
// headers that are passed to the DERP HTTP client
350350
derpHeader atomic.Pointer[http.Header]
351351

352+
// derpRegionDialer is passed to the DERP client
353+
derpRegionDialer atomic.Pointer[func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn]
354+
352355
// stats maintains per-connection counters.
353356
stats atomic.Pointer[connstats.Statistics]
354357

@@ -1514,6 +1517,10 @@ func (c *Conn) derpWriteChanOfAddr(addr netip.AddrPort, peer key.NodePublic) cha
15141517
if header != nil {
15151518
dc.Header = header.Clone()
15161519
}
1520+
dialer := c.derpRegionDialer.Load()
1521+
if dialer != nil {
1522+
dc.SetRegionDialer(*dialer)
1523+
}
15171524

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

2377+
func (c *Conn) SetDERPRegionDialer(dialer func(ctx context.Context, region *tailcfg.DERPRegion) net.Conn) {
2378+
c.derpRegionDialer.Store(&dialer)
2379+
c.mu.Lock()
2380+
defer c.mu.Unlock()
2381+
for _, d := range c.activeDerp {
2382+
d.c.SetRegionDialer(dialer)
2383+
}
2384+
}
2385+
23702386
func (c *Conn) SetNetworkUp(up bool) {
23712387
c.mu.Lock()
23722388
defer c.mu.Unlock()

0 commit comments

Comments
 (0)