mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-24 15:26:49 +09:00
derp/server: resolve the live DERP map in /bootstrap-dns
The handler captured the startup map, so hostnames added by derp.auto_update never resolved.
This commit is contained in:
1 parent
57358b7430
commit
84cf38ce24
3 files changed
+33
-3
No files matched your search
+1
-1
@@ -501,7 +501,7 @@ func (h *Headscale) createRouter(apiV1Mux, apiV2Mux http.Handler) *chi.Mux {
|
|||||||
r.HandleFunc("/derp", h.DERPServer.DERPHandler)
|
r.HandleFunc("/derp", h.DERPServer.DERPHandler)
|
||||||
r.HandleFunc("/derp/probe", derpServer.DERPProbeHandler)
|
r.HandleFunc("/derp/probe", derpServer.DERPProbeHandler)
|
||||||
r.HandleFunc("/derp/latency-check", derpServer.DERPProbeHandler)
|
r.HandleFunc("/derp/latency-check", derpServer.DERPProbeHandler)
|
||||||
r.HandleFunc("/bootstrap-dns", derpServer.DERPBootstrapDNSHandler(h.state.DERPMap()))
|
r.HandleFunc("/bootstrap-dns", derpServer.DERPBootstrapDNSHandler(h.state.DERPMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth is enforced inside each Huma mux per-operation, so the whole API
|
// Auth is enforced inside each Huma mux per-operation, so the whole API
|
||||||
|
|||||||
@@ -334,8 +334,9 @@ func DERPProbeHandler(
|
|||||||
// They have a cache, but not clear if that is really necessary at Headscale, uh, scale.
|
// They have a cache, but not clear if that is really necessary at Headscale, uh, scale.
|
||||||
// An example implementation is found here https://derp.tailscale.com/bootstrap-dns
|
// An example implementation is found here https://derp.tailscale.com/bootstrap-dns
|
||||||
// Coordination server is included automatically, since local DERP is using the same DNS Name in d.serverURL.
|
// Coordination server is included automatically, since local DERP is using the same DNS Name in d.serverURL.
|
||||||
|
// derpMap is called per request so DERP map updates are served.
|
||||||
func DERPBootstrapDNSHandler(
|
func DERPBootstrapDNSHandler(
|
||||||
derpMap tailcfg.DERPMapView,
|
derpMap func() tailcfg.DERPMapView,
|
||||||
) func(http.ResponseWriter, *http.Request) {
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(
|
return func(
|
||||||
writer http.ResponseWriter,
|
writer http.ResponseWriter,
|
||||||
@@ -348,7 +349,7 @@ func DERPBootstrapDNSHandler(
|
|||||||
|
|
||||||
var resolver net.Resolver
|
var resolver net.Resolver
|
||||||
|
|
||||||
for _, region := range derpMap.Regions().All() { //nolint:unqueryvet // not SQLBoiler, tailcfg iterator
|
for _, region := range derpMap().Regions().All() { //nolint:unqueryvet // not SQLBoiler, tailcfg iterator
|
||||||
for _, node := range region.Nodes().All() { //nolint:unqueryvet // not SQLBoiler, tailcfg iterator
|
for _, node := range region.Nodes().All() { //nolint:unqueryvet // not SQLBoiler, tailcfg iterator
|
||||||
addrs, err := resolver.LookupIP(resolvCtx, "ip", node.HostName())
|
addrs, err := resolver.LookupIP(resolvCtx, "ip", node.HostName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/tailcfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestGenerateRegionInsecureTLS pins the contract nix/testkit.nix relies on:
|
// TestGenerateRegionInsecureTLS pins the contract nix/testkit.nix relies on:
|
||||||
@@ -58,3 +64,26 @@ func TestGenerateRegionInsecureTLS(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDERPBootstrapDNSHandlerFollowsDERPMapUpdates guards against the handler
|
||||||
|
// resolving a DERP map captured at startup: hostnames that a later
|
||||||
|
// auto-update adds must be served.
|
||||||
|
func TestDERPBootstrapDNSHandlerFollowsDERPMapUpdates(t *testing.T) {
|
||||||
|
var current atomic.Pointer[tailcfg.DERPMap]
|
||||||
|
current.Store(&tailcfg.DERPMap{})
|
||||||
|
|
||||||
|
handler := DERPBootstrapDNSHandler(func() tailcfg.DERPMapView {
|
||||||
|
return current.Load().View()
|
||||||
|
})
|
||||||
|
|
||||||
|
current.Store(&tailcfg.DERPMap{Regions: map[tailcfg.DERPRegionID]*tailcfg.DERPRegion{
|
||||||
|
1: {RegionID: 1, Nodes: []*tailcfg.DERPNode{{Name: "1a", RegionID: 1, HostName: "localhost"}}},
|
||||||
|
}})
|
||||||
|
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
handler(rec, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/bootstrap-dns", nil))
|
||||||
|
|
||||||
|
var got map[string][]net.IP
|
||||||
|
require.NoError(t, json.NewDecoder(rec.Body).Decode(&got))
|
||||||
|
assert.Contains(t, got, "localhost")
|
||||||
|
}
|
||||||
Reference in new issue
Block a user