Skip to content

Commit c3306bf

Browse files
committed
control/controlhttp/controlhttpserver: split out Accept to its own package
Otherwise all the clients only using control/controlhttp for the ts2021 HTTP client were also pulling in WebSocket libraries, as the server side always needs to speak websockets, but only GOOS=js clients speak it. This doesn't yet totally remove the websocket dependency on Linux because Linux has a envknob opt-in to act like GOOS=js for manual testing and force the use of WebSockets for DERP only (not control). We can put that behind a build tag in a future change to eliminate the dep on all GOOSes. Updates tailscale#1278 Change-Id: I4f60508f4cad52bf8c8943c8851ecee506b7ebc9 Signed-off-by: Brad Fitzpatrick <[email protected]>
1 parent 23880eb commit c3306bf

File tree

10 files changed

+68
-42
lines changed

10 files changed

+68
-42
lines changed

cmd/k8s-operator/depaware.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
8080
github.com/beorn7/perks/quantile from github.com/prometheus/client_golang/prometheus
8181
github.com/bits-and-blooms/bitset from github.com/gaissmai/bart
8282
💣 github.com/cespare/xxhash/v2 from github.com/prometheus/client_golang/prometheus
83-
github.com/coder/websocket from tailscale.com/control/controlhttp+
84-
github.com/coder/websocket/internal/errd from github.com/coder/websocket
85-
github.com/coder/websocket/internal/util from github.com/coder/websocket
86-
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
83+
L github.com/coder/websocket from tailscale.com/derp/derphttp+
84+
L github.com/coder/websocket/internal/errd from github.com/coder/websocket
85+
L github.com/coder/websocket/internal/util from github.com/coder/websocket
86+
L github.com/coder/websocket/internal/xsync from github.com/coder/websocket
8787
L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw
8888
💣 github.com/davecgh/go-spew/spew from k8s.io/apimachinery/pkg/util/dump
8989
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com+
@@ -658,6 +658,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
658658
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
659659
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
660660
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
661+
tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp
661662
tailscale.com/control/controlknobs from tailscale.com/control/controlclient+
662663
tailscale.com/derp from tailscale.com/derp/derphttp+
663664
tailscale.com/derp/derphttp from tailscale.com/ipn/localapi+
@@ -740,7 +741,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
740741
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
741742
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
742743
tailscale.com/net/tstun from tailscale.com/tsd+
743-
tailscale.com/net/wsconn from tailscale.com/control/controlhttp+
744+
L tailscale.com/net/wsconn from tailscale.com/derp/derphttp
744745
tailscale.com/omit from tailscale.com/ipn/conffile
745746
tailscale.com/paths from tailscale.com/client/tailscale+
746747
💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal

cmd/tailscale/depaware.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
55
W 💣 github.com/alexbrainman/sspi from github.com/alexbrainman/sspi/internal/common+
66
W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate
77
W 💣 github.com/alexbrainman/sspi/negotiate from tailscale.com/net/tshttpproxy
8-
github.com/coder/websocket from tailscale.com/control/controlhttp+
9-
github.com/coder/websocket/internal/errd from github.com/coder/websocket
10-
github.com/coder/websocket/internal/util from github.com/coder/websocket
11-
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
8+
L github.com/coder/websocket from tailscale.com/derp/derphttp+
9+
L github.com/coder/websocket/internal/errd from github.com/coder/websocket
10+
L github.com/coder/websocket/internal/util from github.com/coder/websocket
11+
L github.com/coder/websocket/internal/xsync from github.com/coder/websocket
1212
L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw
1313
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/pe+
1414
W 💣 github.com/dblohm7/wingoes/pe from tailscale.com/util/winutil/authenticode
@@ -86,6 +86,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
8686
tailscale.com/cmd/tailscale/cli/ffcomplete/internal from tailscale.com/cmd/tailscale/cli/ffcomplete
8787
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
8888
tailscale.com/control/controlhttp from tailscale.com/cmd/tailscale/cli
89+
tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp
8990
tailscale.com/control/controlknobs from tailscale.com/net/portmapper
9091
tailscale.com/derp from tailscale.com/derp/derphttp
9192
tailscale.com/derp/derphttp from tailscale.com/net/netcheck
@@ -124,7 +125,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
124125
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
125126
tailscale.com/net/tsaddr from tailscale.com/client/web+
126127
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
127-
tailscale.com/net/wsconn from tailscale.com/control/controlhttp+
128+
L tailscale.com/net/wsconn from tailscale.com/derp/derphttp
128129
tailscale.com/paths from tailscale.com/client/tailscale+
129130
💣 tailscale.com/safesocket from tailscale.com/client/tailscale+
130131
tailscale.com/syncs from tailscale.com/cmd/tailscale/cli+

cmd/tailscaled/depaware.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
7979
L github.com/aws/smithy-go/transport/http/internal/io from github.com/aws/smithy-go/transport/http
8080
L github.com/aws/smithy-go/waiter from github.com/aws/aws-sdk-go-v2/service/ssm
8181
github.com/bits-and-blooms/bitset from github.com/gaissmai/bart
82-
github.com/coder/websocket from tailscale.com/control/controlhttp+
83-
github.com/coder/websocket/internal/errd from github.com/coder/websocket
84-
github.com/coder/websocket/internal/util from github.com/coder/websocket
85-
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
82+
L github.com/coder/websocket from tailscale.com/derp/derphttp+
83+
L github.com/coder/websocket/internal/errd from github.com/coder/websocket
84+
L github.com/coder/websocket/internal/util from github.com/coder/websocket
85+
L github.com/coder/websocket/internal/xsync from github.com/coder/websocket
8686
L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw
8787
LD 💣 github.com/creack/pty from tailscale.com/ssh/tailssh
8888
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com+
@@ -249,6 +249,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
249249
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
250250
tailscale.com/control/controlclient from tailscale.com/cmd/tailscaled+
251251
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
252+
tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp
252253
tailscale.com/control/controlknobs from tailscale.com/control/controlclient+
253254
tailscale.com/derp from tailscale.com/derp/derphttp+
254255
tailscale.com/derp/derphttp from tailscale.com/cmd/tailscaled+
@@ -327,7 +328,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
327328
tailscale.com/net/tsdial from tailscale.com/cmd/tailscaled+
328329
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
329330
tailscale.com/net/tstun from tailscale.com/cmd/tailscaled+
330-
tailscale.com/net/wsconn from tailscale.com/control/controlhttp+
331+
L tailscale.com/net/wsconn from tailscale.com/derp/derphttp
331332
tailscale.com/omit from tailscale.com/ipn/conffile
332333
tailscale.com/paths from tailscale.com/client/tailscale+
333334
💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal

control/controlclient/noise_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"time"
1616

1717
"golang.org/x/net/http2"
18-
"tailscale.com/control/controlhttp"
18+
"tailscale.com/control/controlhttp/controlhttpserver"
1919
"tailscale.com/internal/noiseconn"
2020
"tailscale.com/net/netmon"
2121
"tailscale.com/net/tsdial"
@@ -201,7 +201,7 @@ func (up *Upgrader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
201201
return nil
202202
}
203203

204-
cbConn, err := controlhttp.AcceptHTTP(r.Context(), w, r, up.noiseKeyPriv, earlyWriteFn)
204+
cbConn, err := controlhttpserver.AcceptHTTP(r.Context(), w, r, up.noiseKeyPriv, earlyWriteFn)
205205
if err != nil {
206206
up.logf("controlhttp: Accept: %v", err)
207207
return

control/controlhttp/client.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"time"
3939

4040
"tailscale.com/control/controlbase"
41+
"tailscale.com/control/controlhttp/controlhttpcommon"
4142
"tailscale.com/envknob"
4243
"tailscale.com/health"
4344
"tailscale.com/net/dnscache"
@@ -571,9 +572,9 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, optAddr netip.Ad
571572
Method: "POST",
572573
URL: u,
573574
Header: http.Header{
574-
"Upgrade": []string{upgradeHeaderValue},
575-
"Connection": []string{"upgrade"},
576-
handshakeHeaderName: []string{base64.StdEncoding.EncodeToString(init)},
575+
"Upgrade": []string{controlhttpcommon.UpgradeHeaderValue},
576+
"Connection": []string{"upgrade"},
577+
controlhttpcommon.HandshakeHeaderName: []string{base64.StdEncoding.EncodeToString(init)},
577578
},
578579
}
579580
req = req.WithContext(ctx)
@@ -597,7 +598,7 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, optAddr netip.Ad
597598
return nil, fmt.Errorf("httptrace didn't provide a connection")
598599
}
599600

600-
if next := resp.Header.Get("Upgrade"); next != upgradeHeaderValue {
601+
if next := resp.Header.Get("Upgrade"); next != controlhttpcommon.UpgradeHeaderValue {
601602
resp.Body.Close()
602603
return nil, fmt.Errorf("server switched to unexpected protocol %q", next)
603604
}

control/controlhttp/constants.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ import (
1818
)
1919

2020
const (
21-
// upgradeHeader is the value of the Upgrade HTTP header used to
22-
// indicate the Tailscale control protocol.
23-
upgradeHeaderValue = "tailscale-control-protocol"
24-
25-
// handshakeHeaderName is the HTTP request header that can
26-
// optionally contain base64-encoded initial handshake
27-
// payload, to save an RTT.
28-
handshakeHeaderName = "X-Tailscale-Handshake"
29-
3021
// serverUpgradePath is where the server-side HTTP handler to
3122
// to do the protocol switch is located.
3223
serverUpgradePath = "/ts2021"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Tailscale Inc & AUTHORS
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
// Package controlhttpcommon contains common constants for used
5+
// by the controlhttp client and controlhttpserver packages.
6+
package controlhttpcommon
7+
8+
// UpgradeHeader is the value of the Upgrade HTTP header used to
9+
// indicate the Tailscale control protocol.
10+
const UpgradeHeaderValue = "tailscale-control-protocol"
11+
12+
// handshakeHeaderName is the HTTP request header that can
13+
// optionally contain base64-encoded initial handshake
14+
// payload, to save an RTT.
15+
const HandshakeHeaderName = "X-Tailscale-Handshake"

control/controlhttp/server.go renamed to control/controlhttp/controlhttpserver/controlhttpserver.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
//go:build !ios
55

6-
package controlhttp
6+
// Packet controlhttpserver contains the HTTP server side of the ts2021 control protocol.
7+
package controlhttpserver
78

89
import (
910
"context"
@@ -18,6 +19,7 @@ import (
1819

1920
"github.com/coder/websocket"
2021
"tailscale.com/control/controlbase"
22+
"tailscale.com/control/controlhttp/controlhttpcommon"
2123
"tailscale.com/net/netutil"
2224
"tailscale.com/net/wsconn"
2325
"tailscale.com/types/key"
@@ -45,12 +47,12 @@ func acceptHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request, pri
4547
if next == "websocket" {
4648
return acceptWebsocket(ctx, w, r, private)
4749
}
48-
if next != upgradeHeaderValue {
50+
if next != controlhttpcommon.UpgradeHeaderValue {
4951
http.Error(w, "unknown next protocol", http.StatusBadRequest)
5052
return nil, fmt.Errorf("client requested unhandled next protocol %q", next)
5153
}
5254

53-
initB64 := r.Header.Get(handshakeHeaderName)
55+
initB64 := r.Header.Get(controlhttpcommon.HandshakeHeaderName)
5456
if initB64 == "" {
5557
http.Error(w, "missing Tailscale handshake header", http.StatusBadRequest)
5658
return nil, errors.New("no tailscale handshake header in HTTP request")
@@ -67,7 +69,7 @@ func acceptHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request, pri
6769
return nil, errors.New("can't hijack client connection")
6870
}
6971

70-
w.Header().Set("Upgrade", upgradeHeaderValue)
72+
w.Header().Set("Upgrade", controlhttpcommon.UpgradeHeaderValue)
7173
w.Header().Set("Connection", "upgrade")
7274
w.WriteHeader(http.StatusSwitchingProtocols)
7375

@@ -117,7 +119,7 @@ func acceptHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request, pri
117119
// speak HTTP) to a Tailscale control protocol base transport connection.
118120
func acceptWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request, private key.MachinePrivate) (*controlbase.Conn, error) {
119121
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
120-
Subprotocols: []string{upgradeHeaderValue},
122+
Subprotocols: []string{controlhttpcommon.UpgradeHeaderValue},
121123
OriginPatterns: []string{"*"},
122124
// Disable compression because we transmit Noise messages that are not
123125
// compressible.
@@ -129,15 +131,15 @@ func acceptWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request
129131
if err != nil {
130132
return nil, fmt.Errorf("Could not accept WebSocket connection %v", err)
131133
}
132-
if c.Subprotocol() != upgradeHeaderValue {
134+
if c.Subprotocol() != controlhttpcommon.UpgradeHeaderValue {
133135
c.Close(websocket.StatusPolicyViolation, "client must speak the control subprotocol")
134136
return nil, fmt.Errorf("Unexpected subprotocol %q", c.Subprotocol())
135137
}
136138
if err := r.ParseForm(); err != nil {
137139
c.Close(websocket.StatusPolicyViolation, "Could not parse parameters")
138140
return nil, fmt.Errorf("parse query parameters: %v", err)
139141
}
140-
initB64 := r.Form.Get(handshakeHeaderName)
142+
initB64 := r.Form.Get(controlhttpcommon.HandshakeHeaderName)
141143
if initB64 == "" {
142144
c.Close(websocket.StatusPolicyViolation, "missing Tailscale handshake parameter")
143145
return nil, errors.New("no tailscale handshake parameter in HTTP request")

control/controlhttp/http_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ import (
2323
"time"
2424

2525
"tailscale.com/control/controlbase"
26+
"tailscale.com/control/controlhttp/controlhttpcommon"
27+
"tailscale.com/control/controlhttp/controlhttpserver"
2628
"tailscale.com/net/dnscache"
2729
"tailscale.com/net/netmon"
2830
"tailscale.com/net/socks5"
2931
"tailscale.com/net/tsdial"
3032
"tailscale.com/tailcfg"
3133
"tailscale.com/tstest"
34+
"tailscale.com/tstest/deptest"
3235
"tailscale.com/tstime"
3336
"tailscale.com/types/key"
3437
"tailscale.com/types/logger"
@@ -158,7 +161,7 @@ func testControlHTTP(t *testing.T, param httpTestParam) {
158161
return err
159162
}
160163
}
161-
conn, err := AcceptHTTP(context.Background(), w, r, server, earlyWriteFn)
164+
conn, err := controlhttpserver.AcceptHTTP(context.Background(), w, r, server, earlyWriteFn)
162165
if err != nil {
163166
log.Print(err)
164167
}
@@ -529,7 +532,7 @@ EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
529532

530533
func brokenMITMHandler(clock tstime.Clock) http.HandlerFunc {
531534
return func(w http.ResponseWriter, r *http.Request) {
532-
w.Header().Set("Upgrade", upgradeHeaderValue)
535+
w.Header().Set("Upgrade", controlhttpcommon.UpgradeHeaderValue)
533536
w.Header().Set("Connection", "upgrade")
534537
w.WriteHeader(http.StatusSwitchingProtocols)
535538
w.(http.Flusher).Flush()
@@ -574,7 +577,7 @@ func TestDialPlan(t *testing.T) {
574577
close(done)
575578
})
576579
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
577-
conn, err := AcceptHTTP(context.Background(), w, r, server, nil)
580+
conn, err := controlhttpserver.AcceptHTTP(context.Background(), w, r, server, nil)
578581
if err != nil {
579582
log.Print(err)
580583
} else {
@@ -816,3 +819,14 @@ func (c *closeTrackConn) Close() error {
816819
c.d.noteClose(c)
817820
return c.Conn.Close()
818821
}
822+
823+
func TestDeps(t *testing.T) {
824+
deptest.DepChecker{
825+
GOOS: "darwin",
826+
GOARCH: "arm64",
827+
BadDeps: map[string]string{
828+
// Only the controlhttpserver needs WebSockets...
829+
"github.com/coder/websocket": "controlhttp client shouldn't need websockets",
830+
},
831+
}.Check(t)
832+
}

tstest/integration/testcontrol/testcontrol.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"time"
2727

2828
"golang.org/x/net/http2"
29-
"tailscale.com/control/controlhttp"
29+
"tailscale.com/control/controlhttp/controlhttpserver"
3030
"tailscale.com/net/netaddr"
3131
"tailscale.com/net/tsaddr"
3232
"tailscale.com/tailcfg"
@@ -288,7 +288,7 @@ func (s *Server) serveNoiseUpgrade(w http.ResponseWriter, r *http.Request) {
288288
s.mu.Lock()
289289
noisePrivate := s.noisePrivKey
290290
s.mu.Unlock()
291-
cc, err := controlhttp.AcceptHTTP(ctx, w, r, noisePrivate, nil)
291+
cc, err := controlhttpserver.AcceptHTTP(ctx, w, r, noisePrivate, nil)
292292
if err != nil {
293293
log.Printf("AcceptHTTP: %v", err)
294294
return

0 commit comments

Comments
 (0)