Przeglądaj źródła

Allow any port for HTTPS when using Noise over TLS

Signed-off-by: Juan Font Alonso <[email protected]>
Juan Font Alonso 4 lat temu
rodzic
commit
64d482ff48

+ 1 - 1
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
 	}

+ 20 - 9
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
 	}

+ 5 - 9
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 <addr's host>: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,