diff --git a/control/controlclient/netmap.go b/control/controlclient/netmap.go index 703de7a34..b2790bfc9 100644 --- a/control/controlclient/netmap.go +++ b/control/controlclient/netmap.go @@ -238,19 +238,24 @@ func (nm *NetworkMap) _WireGuardConfig(uflags int, dnsOverride []wgcfg.IP, allEn } fmt.Fprintf(buf, "[Peer]\n") fmt.Fprintf(buf, "PublicKey = %s\n", base64.StdEncoding.EncodeToString(peer.Key[:])) - if len(peer.Endpoints) > 0 { - if len(peer.Endpoints) == 1 { - fmt.Fprintf(buf, "Endpoint = %s", peer.Endpoints[0]) + var endpoints []string + if peer.DERP != "" { + endpoints = append(endpoints, peer.DERP) + } + endpoints = append(endpoints, peer.Endpoints...) + if len(endpoints) > 0 { + if len(endpoints) == 1 { + fmt.Fprintf(buf, "Endpoint = %s", endpoints[0]) } else if allEndpoints { // TODO(apenwarr): This mode is incompatible. // Normal wireguard clients don't know how to // parse it (yet?) fmt.Fprintf(buf, "Endpoint = %s", - strings.Join(peer.Endpoints, ",")) + strings.Join(endpoints, ",")) } else { fmt.Fprintf(buf, "Endpoint = %s # other endpoints: %s", - peer.Endpoints[0], - strings.Join(peer.Endpoints[1:], ", ")) + endpoints[0], + strings.Join(endpoints[1:], ", ")) } buf.WriteByte('\n') } diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 5cbe1f152..2408e13d1 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -129,6 +129,7 @@ type Node struct { Addresses []wgcfg.CIDR // IP addresses of this Node directly AllowedIPs []wgcfg.CIDR // range of IP addresses to route to this node Endpoints []string `json:",omitempty"` // IP+port (public via STUN, and local LANs) + DERP string `json:",omitempty"` // DERP-in-IP:port ("127.3.3.40:N") endpoint Hostinfo Hostinfo Created time.Time LastSeen *time.Time `json:",omitempty"` diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index b1461967e..e1c7ed4f3 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -160,7 +160,7 @@ func TestHostinfoEqual(t *testing.T) { } func TestNodeEqual(t *testing.T) { - nodeHandles := []string{"ID", "Name", "User", "Key", "KeyExpiry", "Machine", "Addresses", "AllowedIPs", "Endpoints", "Hostinfo", "Created", "LastSeen", "MachineAuthorized"} + nodeHandles := []string{"ID", "Name", "User", "Key", "KeyExpiry", "Machine", "Addresses", "AllowedIPs", "Endpoints", "DERP", "Hostinfo", "Created", "LastSeen", "MachineAuthorized"} if have := fieldsOf(reflect.TypeOf(Node{})); !reflect.DeepEqual(have, nodeHandles) { t.Errorf("Node.Equal check might be out of sync\nfields: %q\nhandled: %q\n", have, nodeHandles)