From 64d482ff482b6a616d7f24f939dbc5093d93909b Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Wed, 30 Mar 2022 00:14:12 +0200 Subject: [PATCH] Allow any port for HTTPS when using Noise over TLS Signed-off-by: Juan Font Alonso --- control/controlclient/direct.go | 2 +- control/controlclient/noise.go | 29 ++++++++++++++++++++--------- control/controlhttp/client.go | 14 +++++--------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 06346bebc..4c5292d8e 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -1329,7 +1329,7 @@ func (c *Direct) setDNSNoise(ctx context.Context, req *tailcfg.SetDNSRequest) er if err != nil { return err } - res, err := np.Post(fmt.Sprintf("https://%v/%v", np.serverHost, "machine/set-dns"), "application/json", bytes.NewReader(bodyData)) + res, err := np.Post(fmt.Sprintf("https://%v/%v", np.host, "machine/set-dns"), "application/json", bytes.NewReader(bodyData)) if err != nil { return err } diff --git a/control/controlclient/noise.go b/control/controlclient/noise.go index 8fc0d714e..f5b6b12a3 100644 --- a/control/controlclient/noise.go +++ b/control/controlclient/noise.go @@ -7,7 +7,6 @@ package controlclient import ( "context" "crypto/tls" - "fmt" "math" "net" "net/http" @@ -50,7 +49,9 @@ type noiseClient struct { dialer *tsdial.Dialer privKey key.MachinePrivate serverPubKey key.MachinePublic - serverHost string // the host:port part of serverURL + host string // the host part of serverURL + httpPort string // the default port to call + httpsPort string // the fallback Noise-over-https port // mu only protects the following variables. mu sync.Mutex @@ -65,18 +66,28 @@ func newNoiseClient(priKey key.MachinePrivate, serverPubKey key.MachinePublic, s if err != nil { return nil, err } - var host string + var httpPort string + var httpsPort string if u.Port() != "" { - // If there is an explicit port specified use it. - host = u.Host + // If there is an explicit port specified, trust the scheme and hope for the best + if u.Scheme == "http" { + httpPort = u.Port() + httpsPort = "443" + } else { + httpPort = "80" + httpsPort = u.Port() + } } else { - // Otherwise, controlhttp.Dial expects an http endpoint. - host = fmt.Sprintf("%v:80", u.Hostname()) + // Otherwise, use the standard ports + httpPort = "80" + httpsPort = "443" } np := &noiseClient{ serverPubKey: serverPubKey, privKey: priKey, - serverHost: host, + host: u.Hostname(), + httpPort: httpPort, + httpsPort: httpsPort, dialer: dialer, } @@ -154,7 +165,7 @@ func (nc *noiseClient) dial(_, _ string, _ *tls.Config) (net.Conn, error) { // thousand version numbers before getting to this point. panic("capability version is too high to fit in the wire protocol") } - conn, err := controlhttp.Dial(ctx, nc.serverHost, nc.privKey, nc.serverPubKey, uint16(tailcfg.CurrentCapabilityVersion), nc.dialer.SystemDial) + conn, err := controlhttp.Dial(ctx, nc.host, nc.httpPort, nc.httpsPort, nc.privKey, nc.serverPubKey, uint16(tailcfg.CurrentCapabilityVersion), nc.dialer.SystemDial) if err != nil { return nil, err } diff --git a/control/controlhttp/client.go b/control/controlhttp/client.go index d7169fedb..7717e931d 100644 --- a/control/controlhttp/client.go +++ b/control/controlhttp/client.go @@ -43,24 +43,20 @@ import ( "tailscale.com/types/key" ) -// Dial connects to the HTTP server at addr, requests to switch to the +// Dial connects to the HTTP server at host:httpPort, requests to switch to the // Tailscale control protocol, and returns an established control // protocol connection. // // If Dial fails to connect using addr, it also tries to tunnel over -// TLS to :443 as a compatibility fallback. +// TLS to host:httpsPort as a compatibility fallback. // // The provided ctx is only used for the initial connection, until // Dial returns. It does not affect the connection once established. -func Dial(ctx context.Context, addr string, machineKey key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16, dialer dnscache.DialContextFunc) (*controlbase.Conn, error) { - host, port, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } +func Dial(ctx context.Context, host string, httpPort string, httpsPort string, machineKey key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16, dialer dnscache.DialContextFunc) (*controlbase.Conn, error) { a := &dialParams{ host: host, - httpPort: port, - httpsPort: "443", + httpPort: httpPort, + httpsPort: httpsPort, machineKey: machineKey, controlKey: controlKey, version: protocolVersion,