Skip to content

Commit 058fa46

Browse files
authored
fix: force websockets when http2 is negotiated (#16)
1 parent bf5761a commit 058fa46

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

derp/derphttp/derphttp_client.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,16 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
477477
req.Header.Set("Upgrade", "DERP")
478478
req.Header.Set("Connection", "Upgrade")
479479

480+
regionID := 0
481+
if reg != nil {
482+
regionID = reg.RegionID
483+
}
484+
if tlsState != nil && tlsState.NegotiatedProtocol == "h2" {
485+
reason := "The server wanted us to use HTTP/2, but DERP requires Upgrade which needs HTTP/1.1"
486+
c.forceWebsockets(regionID, reason)
487+
return nil, 0, fmt.Errorf("DERP server did not switch protocols: %s", reason)
488+
}
489+
480490
if !serverPub.IsZero() && serverProtoVersion != 0 {
481491
// parseMetaCert found the server's public key (no TLS
482492
// middlebox was in the way), so skip the HTTP upgrade
@@ -492,17 +502,6 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
492502
// No need to flush the HTTP request. the derp.Client's initial
493503
// client auth frame will flush it.
494504
} 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-
506505
if err := req.Write(brw); err != nil {
507506
return nil, 0, err
508507
}
@@ -650,7 +649,7 @@ func (c *Client) tlsConfig(node *tailcfg.DERPNode) *tls.Config {
650649
tlsdial.SetConfigExpectedCert(tlsConf, node.CertName)
651650
}
652651
}
653-
tlsConf.NextProtos = []string{"h2", "http/1.1"}
652+
tlsConf.NextProtos = []string{"http/1.1", "h2"}
654653
return tlsConf
655654
}
656655

derp/derphttp/derphttp_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,13 @@ func TestHTTP2WebSocketFallback(t *testing.T) {
235235
s.Accept(context.Background(), wc, brw, r.RemoteAddr)
236236
}))
237237
httpsrv.TLS = &tls.Config{
238-
NextProtos: []string{"h2", "http/1.1"},
238+
NextProtos: []string{"h2"},
239+
GetCertificate: func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) {
240+
// Add this to ensure fast start works!
241+
cert := httpsrv.TLS.Certificates[0]
242+
cert.Certificate = append(cert.Certificate, s.MetaCert())
243+
return &cert, nil
244+
},
239245
}
240246
httpsrv.StartTLS()
241247

@@ -264,7 +270,7 @@ func TestHTTP2WebSocketFallback(t *testing.T) {
264270
t.Fatal("client didn't error on initial connect")
265271
}
266272
reason := <-reasonCh
267-
if !strings.Contains(reason, "wanted us to use HTTP/2") {
273+
if !strings.Contains(reason, "DERP requires Upgrade which needs") {
268274
t.Fatalf("reason doesn't contain message: %s", reason)
269275
}
270276
if err := c.Connect(context.Background()); err != nil {

0 commit comments

Comments
 (0)