Compare commits
1 Commits
main
...
nickkhyl/h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6696b8ee62 |
@@ -41,6 +41,13 @@ import (
|
||||
"tailscale.com/types/tkatype"
|
||||
)
|
||||
|
||||
// DialFunc is any function that dials the given address.
|
||||
type DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
// h2cTransport returns nil on platforms where H2C ("cleartext" HTTP/2)
|
||||
// support for the LocalAPI is not implemented.
|
||||
var h2cTransport = func(DialFunc) http.RoundTripper { return nil }
|
||||
|
||||
// defaultLocalClient is the default LocalClient when using the legacy
|
||||
// package-level functions.
|
||||
var defaultLocalClient LocalClient
|
||||
@@ -58,7 +65,7 @@ var defaultLocalClient LocalClient
|
||||
type LocalClient struct {
|
||||
// Dial optionally specifies an alternate func that connects to the local
|
||||
// machine's tailscaled or equivalent. If nil, a default is used.
|
||||
Dial func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
Dial DialFunc
|
||||
|
||||
// Socket specifies an alternate path to the local Tailscale socket.
|
||||
// If empty, a platform-specific default is used.
|
||||
@@ -77,6 +84,9 @@ type LocalClient struct {
|
||||
// different operating system, such as in integration tests.
|
||||
OmitAuth bool
|
||||
|
||||
// AllowH2C enables H2C ("cleartext" HTTP/2) if supported on the current platform.
|
||||
AllowH2C bool
|
||||
|
||||
// tsClient does HTTP requests to the local Tailscale daemon.
|
||||
// It's lazily initialized on first use.
|
||||
tsClient *http.Client
|
||||
@@ -90,7 +100,7 @@ func (lc *LocalClient) socket() string {
|
||||
return paths.DefaultTailscaledSocket()
|
||||
}
|
||||
|
||||
func (lc *LocalClient) dialer() func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
func (lc *LocalClient) dialer() DialFunc {
|
||||
if lc.Dial != nil {
|
||||
return lc.Dial
|
||||
}
|
||||
@@ -114,6 +124,17 @@ func (lc *LocalClient) defaultDialer(ctx context.Context, network, addr string)
|
||||
return safesocket.ConnectContext(ctx, lc.socket())
|
||||
}
|
||||
|
||||
// transport returns the HTTP transport to be used when making requests
|
||||
// to the local machine's Tailscale daemon.
|
||||
func (lc *LocalClient) transport() http.RoundTripper {
|
||||
if lc.AllowH2C {
|
||||
if t := h2cTransport(lc.dialer()); t != nil {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return &http.Transport{DialContext: lc.dialer()}
|
||||
}
|
||||
|
||||
// DoLocalRequest makes an HTTP request to the local machine's Tailscale daemon.
|
||||
//
|
||||
// URLs are of the form http://local-tailscaled.sock/localapi/v0/whois?ip=1.2.3.4.
|
||||
@@ -126,11 +147,7 @@ func (lc *LocalClient) defaultDialer(ctx context.Context, network, addr string)
|
||||
func (lc *LocalClient) DoLocalRequest(req *http.Request) (*http.Response, error) {
|
||||
req.Header.Set("Tailscale-Cap", strconv.Itoa(int(tailcfg.CurrentCapabilityVersion)))
|
||||
lc.tsClientOnce.Do(func() {
|
||||
lc.tsClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: lc.dialer(),
|
||||
},
|
||||
}
|
||||
lc.tsClient = &http.Client{Transport: lc.transport()}
|
||||
})
|
||||
if !lc.OmitAuth {
|
||||
if _, token, err := safesocket.LocalTCPPortAndToken(); err == nil {
|
||||
|
||||
31
client/tailscale/localclient_h2c.go
Normal file
31
client/tailscale/localclient_h2c.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Enabling H2C for LocalAPI is not Windows-specific.
|
||||
// However, Windows is expected to benefit the most
|
||||
// due to additional, potentially slow authentication steps
|
||||
// performed for each new named pipe connection.
|
||||
// As an experiment, we are enabling it on Windows first.
|
||||
//go:build windows
|
||||
|
||||
package tailscale
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
h2cTransport = func(dialer DialFunc) http.RoundTripper {
|
||||
return &http2.Transport{
|
||||
AllowHTTP: true,
|
||||
DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
|
||||
return dialer(ctx, network, addr)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,9 +189,10 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
|
||||
golang.org/x/exp/maps from tailscale.com/util/syspolicy/setting
|
||||
L golang.org/x/net/bpf from github.com/mdlayher/netlink+
|
||||
golang.org/x/net/dns/dnsmessage from net+
|
||||
golang.org/x/net/http/httpguts from net/http
|
||||
golang.org/x/net/http/httpguts from net/http+
|
||||
golang.org/x/net/http/httpproxy from net/http+
|
||||
golang.org/x/net/http2/hpack from net/http
|
||||
W golang.org/x/net/http2 from tailscale.com/client/tailscale
|
||||
golang.org/x/net/http2/hpack from net/http+
|
||||
golang.org/x/net/idna from golang.org/x/crypto/acme/autocert+
|
||||
golang.org/x/net/proxy from tailscale.com/net/netns
|
||||
D golang.org/x/net/route from net+
|
||||
|
||||
@@ -79,7 +79,8 @@ func CleanUpArgs(args []string) []string {
|
||||
}
|
||||
|
||||
var localClient = tailscale.LocalClient{
|
||||
Socket: paths.DefaultTailscaledSocket(),
|
||||
AllowH2C: true,
|
||||
Socket: paths.DefaultTailscaledSocket(),
|
||||
}
|
||||
|
||||
// Run runs the CLI. The args do not include the binary name.
|
||||
|
||||
@@ -451,7 +451,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
golang.org/x/net/http/httpguts from golang.org/x/net/http2+
|
||||
golang.org/x/net/http/httpproxy from net/http+
|
||||
golang.org/x/net/http2 from golang.org/x/net/http2/h2c+
|
||||
golang.org/x/net/http2/h2c from tailscale.com/ipn/ipnlocal
|
||||
golang.org/x/net/http2/h2c from tailscale.com/ipn/ipnlocal+
|
||||
golang.org/x/net/http2/hpack from golang.org/x/net/http2+
|
||||
golang.org/x/net/icmp from tailscale.com/net/ping+
|
||||
golang.org/x/net/idna from golang.org/x/net/http/httpguts+
|
||||
|
||||
@@ -33,6 +33,10 @@ import (
|
||||
"tailscale.com/util/systemd"
|
||||
)
|
||||
|
||||
// addH2C is a no-op on platforms where the LocalAPI
|
||||
// does not support H2C ("cleartext" HTTP/2).
|
||||
var addH2C = func(*http.Server) {}
|
||||
|
||||
// Server is an IPN backend and its set of 0 or more active localhost
|
||||
// TCP or unix socket connections talking to that backend.
|
||||
type Server struct {
|
||||
@@ -515,6 +519,7 @@ func (s *Server) Run(ctx context.Context, ln net.Listener) error {
|
||||
IdleTimeout: 5 * time.Second,
|
||||
ErrorLog: logger.StdLogger(logger.WithPrefix(s.logf, "ipnserver: ")),
|
||||
}
|
||||
addH2C(hs)
|
||||
if err := hs.Serve(ln); err != nil {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
|
||||
29
ipn/ipnserver/server_h2c.go
Normal file
29
ipn/ipnserver/server_h2c.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Enabling H2C for LocalAPI is not Windows-specific.
|
||||
// However, Windows is expected to benefit the most
|
||||
// due to additional, potentially slow authentication steps
|
||||
// performed for each new named pipe connection.
|
||||
// As an experiment, we are enabling it on Windows first.
|
||||
//go:build windows
|
||||
|
||||
package ipnserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
)
|
||||
|
||||
func init() {
|
||||
addH2C = func(s *http.Server) {
|
||||
h2s := &http2.Server{}
|
||||
s.Handler = h2c.NewHandler(s.Handler, h2s)
|
||||
// [http2.ConfigureServer] sets up a server shutdown handler that gracefully
|
||||
// closes connections when [http.Server.Shutdown] is called.
|
||||
// Otherwise, it leaks goroutines.
|
||||
http2.ConfigureServer(s, h2s)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user