Browse Source

derp,magicsock: add debug envknobs for HTTP and derp server name (#7744)

Make developing derp easier by:

1. Creating an envknob telling clients to use HTTP to connect to derp
servers, so devs don't have to acquire a valid TLS cert.

2. Creating an envknob telling clients which derp server to connect
to, so devs don't have to edit the ACLs in the admin console to add a
custom DERP map.

3. Explaining how the -dev and -a command lines args to derper
interact.

To use this:

1. Run derper with -dev.

2. Run tailscaled with TS_DEBUG_USE_DERP_HTTP=1 and
TS_DEBUG_USE_DERP_ADDR=localhost

This will result in the client connecting to derp via HTTP on port
3340.

Fixes #7700

Signed-off-by: Val <[email protected]>
valscale 2 years ago
parent
commit
7bfb7744b7

+ 2 - 2
cmd/derper/derper.go

@@ -36,8 +36,8 @@ import (
 )
 
 var (
-	dev        = flag.Bool("dev", false, "run in localhost development mode")
-	addr       = flag.String("a", ":443", "server HTTPS listen address, in form \":port\", \"ip:port\", or for IPv6 \"[ip]:port\". If the IP is omitted, it defaults to all interfaces.")
+	dev        = flag.Bool("dev", false, "run in localhost development mode (overrides -a)")
+	addr       = flag.String("a", ":443", "server HTTP/HTTPS listen address, in form \":port\", \"ip:port\", or for IPv6 \"[ip]:port\". If the IP is omitted, it defaults to all interfaces. Serves HTTPS if the port is 443 and/or -certmode is manual, otherwise HTTP.")
 	httpPort   = flag.Int("http-port", 80, "The port on which to serve HTTP. Set to -1 to disable. The listener is bound to the same IP (if any) as specified in the -a flag.")
 	stunPort   = flag.Int("stun-port", 3478, "The UDP port on which to serve STUN. The listener is bound to the same IP (if any) as specified in the -a flag.")
 	configPath = flag.String("c", "", "config file path")

+ 13 - 1
derp/derphttp/derphttp_client.go

@@ -174,6 +174,10 @@ func urlPort(u *url.URL) string {
 	return ""
 }
 
+// debugDERPUseHTTP tells clients to connect to DERP via HTTP on port
+// 3340 instead of HTTPS on 443.
+var debugUseDERPHTTP = envknob.RegisterBool("TS_DEBUG_USE_DERP_HTTP")
+
 func (c *Client) targetString(reg *tailcfg.DERPRegion) string {
 	if c.url != nil {
 		return c.url.String()
@@ -185,6 +189,10 @@ func (c *Client) useHTTPS() bool {
 	if c.url != nil && c.url.Scheme == "http" {
 		return false
 	}
+	if debugUseDERPHTTP() {
+		return false
+	}
+
 	return true
 }
 
@@ -200,7 +208,11 @@ func (c *Client) urlString(node *tailcfg.DERPNode) string {
 	if c.url != nil {
 		return c.url.String()
 	}
-	return fmt.Sprintf("https://%s/derp", node.HostName)
+	proto := "https"
+	if debugUseDERPHTTP() {
+		proto = "http"
+	}
+	return fmt.Sprintf("%s://%s/derp", proto, node.HostName)
 }
 
 // AddressFamilySelector decides whether IPv6 is preferred for

+ 9 - 3
wgengine/magicsock/debugknobs.go

@@ -33,13 +33,19 @@ var (
 	debugReSTUNStopOnIdle = envknob.RegisterBool("TS_DEBUG_RESTUN_STOP_ON_IDLE")
 	// debugAlwaysDERP disables the use of UDP, forcing all peer communication over DERP.
 	debugAlwaysDERP = envknob.RegisterBool("TS_DEBUG_ALWAYS_USE_DERP")
+	// debugDERPAddr sets the derp address manually, overriding the DERP map from control.
+	debugUseDERPAddr = envknob.RegisterString("TS_DEBUG_USE_DERP_ADDR")
+	// debugDERPUseHTTP tells clients to connect to DERP via HTTP on port 3340 instead of
+	// HTTPS on 443.
+	debugUseDERPHTTP = envknob.RegisterBool("TS_DEBUG_USE_DERP_HTTP")
 	// debugEnableSilentDisco disables the use of heartbeatTimer on the endpoint struct
 	// and attempts to handle disco silently. See issue #540 for details.
 	debugEnableSilentDisco = envknob.RegisterBool("TS_DEBUG_ENABLE_SILENT_DISCO")
-	// DebugSendCallMeUnknownPeer sends a CallMeMaybe to a
-	// non-existent destination every time we send a real
-	// CallMeMaybe to test the PeerGoneNotHere logic.
+	// debugSendCallMeUnknownPeer sends a CallMeMaybe to a non-existent destination every
+	// time we send a real CallMeMaybe to test the PeerGoneNotHere logic.
 	debugSendCallMeUnknownPeer = envknob.RegisterBool("TS_DEBUG_SEND_CALLME_UNKNOWN_PEER")
+	// Hey you! Adding a new debugknob? Make sure to stub it out in the debugknob_stubs.go
+	// file too.
 )
 
 // inTest reports whether the running program is a test that set the

+ 2 - 0
wgengine/magicsock/debugknobs_stubs.go

@@ -16,8 +16,10 @@ func debugOmitLocalAddresses() bool    { return false }
 func logDerpVerbose() bool             { return false }
 func debugReSTUNStopOnIdle() bool      { return false }
 func debugAlwaysDERP() bool            { return false }
+func debugUseDERPHTTP() bool           { return false }
 func debugEnableSilentDisco() bool     { return false }
 func debugSendCallMeUnknownPeer() bool { return false }
+func debugUseDERPAddr() string         { return "" }
 func debugUseDerpRouteEnv() string     { return "" }
 func debugUseDerpRoute() opt.Bool      { return "" }
 func inTest() bool                     { return false }

+ 23 - 0
wgengine/magicsock/magicsock.go

@@ -2572,6 +2572,29 @@ func (c *Conn) SetDERPMap(dm *tailcfg.DERPMap) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 
+	var derpAddr = debugUseDERPAddr()
+	if derpAddr != "" {
+		derpPort := 443
+		if debugUseDERPHTTP() {
+			// Match the port for -dev in derper.go
+			derpPort = 3340
+		}
+		dm = &tailcfg.DERPMap{
+			OmitDefaultRegions: true,
+			Regions: map[int]*tailcfg.DERPRegion{
+				999: {
+					RegionID: 999,
+					Nodes: []*tailcfg.DERPNode{{
+						Name:     "999dev",
+						RegionID: 999,
+						HostName: derpAddr,
+						DERPPort: derpPort,
+					}},
+				},
+			},
+		}
+	}
+
 	if reflect.DeepEqual(dm, c.derpMap) {
 		return
 	}