noise: stop serving metrics inside the tunnel

Any machine key reached it, bypassing metrics_listen_addr. No client
asks for it.
This commit is contained in:
Kristoffer Dalby committed 2026-10-28 14:42:21 +00:00
1 parent 8660eb476f
commit 5705538f2e
2 files changed
+43 -2

No files matched your search

-2
View File
@@ -161,8 +161,6 @@ func (h *Headscale) NoiseUpgradeHandler(
r.Use(middleware.RequestLogger(&zerologRequestLogger{}))
r.Use(middleware.Recoverer)
r.Handle("/metrics", metrics.Handler())
r.Route("/machine", func(r chi.Router) {
r.Post("/register", ns.RegistrationHandler)
r.Post("/map", ns.PollNetMapHandler)
+43
View File
@@ -32,9 +32,13 @@ import (
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"tailscale.com/control/ts2021"
"tailscale.com/net/netmon"
"tailscale.com/net/netutil"
"tailscale.com/net/tsdial"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/util/eventbus"
"tailscale.com/util/zstdframe"
)
@@ -1999,6 +2003,45 @@ func TestNoiseHTTPServerTimeouts(t *testing.T) {
})
}
// TestNoiseRouter_DoesNotServeMetrics pins that the metrics registry is not
// reachable through a Noise tunnel. The handshake accepts any machine key, so
// every route on the tunnel's router is open to anyone who reaches the public
// listener; metrics belong on metrics_listen_addr only.
func TestNoiseRouter_DoesNotServeMetrics(t *testing.T) {
t.Parallel()
app := createTestApp(t)
server := httptest.NewServer(app.HTTPHandler())
t.Cleanup(server.Close)
dialer := tsdial.NewDialer(netmon.NewStatic())
dialer.SetBus(eventbus.New())
// A machine key that never registered.
client, err := ts2021.NewClient(ts2021.ClientOpts{
ServerURL: server.URL,
PrivKey: key.NewMachine(),
ServerPubKey: app.noisePrivateKey.Public(),
Dialer: dialer,
Logf: t.Logf,
})
require.NoError(t, err)
t.Cleanup(func() { _ = client.Close() })
// The client sends every request down the tunnel whatever the host.
req, err := http.NewRequestWithContext(
t.Context(), http.MethodGet, "https://headscale/metrics", nil,
)
require.NoError(t, err)
resp, err := client.Do(req)
require.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}
// TestSSHActionFollowUp_ParksOneRequestPerSession pins that a pending SSH
// check keeps one waiting follow-up, the newest. Older waiters re-delegate at
// once instead of staying parked until the session ends.