mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-10 08:40:07 +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:
committed by
Kristoffer Dalby
parent
57358b7430
commit
84cf38ce24
+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/probe", 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
|
||||
|
||||
@@ -334,8 +334,9 @@ func DERPProbeHandler(
|
||||
// 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
|
||||
// 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(
|
||||
derpMap tailcfg.DERPMapView,
|
||||
derpMap func() tailcfg.DERPMapView,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(
|
||||
writer http.ResponseWriter,
|
||||
@@ -348,7 +349,7 @@ func DERPBootstrapDNSHandler(
|
||||
|
||||
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
|
||||
addrs, err := resolver.LookupIP(resolvCtx, "ip", node.HostName())
|
||||
if err != nil {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
// 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