@@ -347,26 +347,26 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
347
347
case c .useWebsockets ():
348
348
var urlStr string
349
349
var tlsConfig * tls.Config
350
- // WebSocket connections require a DERP to proxy.
351
- // DERP mappings have no explicit requirements on the ordering
352
- // of DERP vs STUNOnly nodes. So we pick the first non-STUNOnly one.
353
- var node * tailcfg.DERPNode
354
- for _ , n := range reg .Nodes {
355
- if n .STUNOnly {
356
- continue
350
+ if reg != nil {
351
+ // WebSocket connections require a DERP to proxy.
352
+ // DERP mappings have no explicit requirements on the ordering
353
+ // of DERP vs STUNOnly nodes. So we pick the first non-STUNOnly one.
354
+ var node * tailcfg.DERPNode
355
+ for _ , n := range reg .Nodes {
356
+ if n .STUNOnly {
357
+ continue
358
+ }
359
+ node = n
360
+ break
361
+ }
362
+ if node == nil {
363
+ return nil , 0 , errors .New ("no non-STUN-only nodes in region" )
357
364
}
358
- node = n
359
- break
360
- }
361
- if node == nil {
362
- return nil , 0 , errors .New ("no non-STUN-only nodes in region" )
363
- }
364
- if c .url != nil {
365
- urlStr = c .url .String ()
366
- tlsConfig = c .tlsConfig (nil )
367
- } else {
368
365
urlStr = c .urlString (node )
369
366
tlsConfig = c .tlsConfig (node )
367
+ } else if c .url != nil {
368
+ urlStr = c .url .String ()
369
+ tlsConfig = c .tlsConfig (nil )
370
370
}
371
371
c .logf ("%s: connecting websocket to %v" , caller , urlStr )
372
372
conn , err := dialWebsocketFunc (ctx , urlStr , tlsConfig , c .Header )
@@ -492,6 +492,17 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
492
492
// No need to flush the HTTP request. the derp.Client's initial
493
493
// client auth frame will flush it.
494
494
} else {
495
+ regionID := 0
496
+ if reg != nil {
497
+ regionID = reg .RegionID
498
+ }
499
+
500
+ if tlsState != nil && tlsState .NegotiatedProtocol == "h2" {
501
+ reason := fmt .Sprintf ("The server wanted us to use HTTP/2, but DERP requires Upgrade which needs HTTP/1.1" )
502
+ c .forceWebsockets (regionID , reason )
503
+ return nil , 0 , fmt .Errorf ("DERP server did not switch protocols: %s" , reason )
504
+ }
505
+
495
506
if err := req .Write (brw ); err != nil {
496
507
return nil , 0 , err
497
508
}
@@ -512,17 +523,12 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
512
523
// For safety, we'll assume that status codes >= 400 are
513
524
// proxies that don't support WebSockets.
514
525
if resp .StatusCode >= 400 && resp .StatusCode < 500 {
515
- reason := fmt .Sprintf ("GET failed with status code %d: %s" , resp .StatusCode , b )
516
- c .logf ("We'll use WebSockets on the next connection attempt. A proxy could be disallowing the use of 'Upgrade: derp': %s" , reason )
517
- c .forcedWebsocket .Store (true )
518
- forcedWebsocketCallback := c .forcedWebsocketCallback .Load ()
519
- if forcedWebsocketCallback != nil {
520
- go (* forcedWebsocketCallback )(reg .RegionID , reason )
521
- }
526
+ c .forceWebsockets (regionID , fmt .Sprintf ("GET failed with status code %d (a proxy could be disallowing the use of 'Upgrade: derp'): %s" , resp .StatusCode , b ))
522
527
}
523
528
524
529
return nil , 0 , fmt .Errorf ("GET failed: %v: %s" , err , b )
525
530
}
531
+
526
532
}
527
533
derpClient , err = derp .NewClient (c .privateKey , httpConn , brw , c .logf ,
528
534
derp .MeshKey (c .MeshKey ),
@@ -571,6 +577,15 @@ func (c *Client) SetForcedWebsocketCallback(callback func(region int, reason str
571
577
c .forcedWebsocketCallback .Store (& callback )
572
578
}
573
579
580
+ func (c * Client ) forceWebsockets (regionID int , reason string ) {
581
+ c .logf ("We'll use WebSockets on the next connection attempt: %s" , reason )
582
+ c .forcedWebsocket .Store (true )
583
+ forcedWebsocketCallback := c .forcedWebsocketCallback .Load ()
584
+ if forcedWebsocketCallback != nil {
585
+ go (* forcedWebsocketCallback )(regionID , reason )
586
+ }
587
+ }
588
+
574
589
func (c * Client ) dialURL (ctx context.Context ) (net.Conn , error ) {
575
590
host := c .url .Hostname ()
576
591
if c .dialer != nil {
@@ -635,6 +650,7 @@ func (c *Client) tlsConfig(node *tailcfg.DERPNode) *tls.Config {
635
650
tlsdial .SetConfigExpectedCert (tlsConf , node .CertName )
636
651
}
637
652
}
653
+ tlsConf .NextProtos = []string {"h2" , "http/1.1" }
638
654
return tlsConf
639
655
}
640
656
0 commit comments