Commit Graph
4824 Commits
Author SHA1 Message Date
Igor SerganovandClaude Opus 5.5 1ff8e368b6 hscontrol: arm ephemeral GC when a node registers with an auth key
The ephemeral garbage collector was only armed when a long-poll
session ended, or for every ephemeral node at startup. A client that
registered and went away before its first long-poll reached Connect,
for example a pod killed right after login, never ended a session,
so no deletion timer was armed. The node then stayed until headscale
restarted, well past node.ephemeral.inactivity_timeout.

Schedule the GC right after the auth-key registration, before the
error check: a failed policy refresh still returns the saved node. The
existing Cancel in serveLongPoll stops the timer once the node
connects. A timer that fires while a session is live is still skipped
by the ActiveSessions check.

TestEphemeralGCDoesNotDeleteReconnectedNode now checks that
registration arms the timer and cancels it before replaying its
sessions. Otherwise the 50ms timer could fire while the test's Connect
was still waiting for a NodeStore flush.

TestFailedReconnectDoesNotCancelEphemeralGC and
TestDeleteNodeCancelsEphemeralGC ran with a zero inactivity timeout,
so the registration timer deleted the node at once, and the delete
cancelled the timer the tests armed themselves. They now use 5s, which
outlasts the tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 17:05:36 +01:00
Igor Serganov 704f1cafd3 db: release the IPv4 address when IPv6 allocation fails in Next
IPAllocator.Next took the allocator mutex once per address family.
When the IPv6 allocation failed, the IPv4 address had already been
added to usedIPs and prev4 had moved past it, so the address stayed
reserved until headscale restarted even though no node held it.

Allocate both families under a single critical section, and on an
IPv6 failure remove the IPv4 address from usedIPs and restore prev4.
2026-10-30 17:05:25 +01:00
Igor Serganov 2088f1d2a6 db: make the ephemeral GC safe to close twice
A second Close panicked on the closed cancel channel.
2026-10-30 17:05:14 +01:00
github-actions[bot] 4472cd8b83 Update VOUCHED list
https://github.com/juanfont/headscale/issues/3629#issuecomment-6525293776
2026-10-30 15:35:25 +01:00
Kristoffer Dalby 526daf0841 policy/v2: resolve an ACL's sources once, not once per destination
An ACL compiles to one grant per destination, and each resolved and
merged the same sources again. A wide CI-style ACL took 3s and 674MB
per compile; 88ms and 23MB now.
2026-10-30 14:36:19 +01:00
Kristoffer Dalby 8e45958341 CHANGELOG: align the 0.29.x sections with the releases
0.29.7 now matches what ships; 0.30.0 drops entries 0.29.7 already
released. #3398 never shipped in 0.29.3, #3236 missed 0.29.0.
2026-10-30 10:35:22 +01:00
Kristoffer Dalby 545ace5673 hscontrol: remove unused OIDC user change result 2026-10-29 20:51:50 +01:00
Kristoffer Dalby c0925962c2 hscontrol: bound pending authentication without evicting sessions 2026-10-29 20:51:50 +01:00
Kristoffer Dalby a9508935b9 CHANGELOG: document SSH acceptEnv fix
Updates #3559
2026-10-29 20:51:36 +01:00
Kristoffer Dalby 52842f4c0d integration: guard SSH acceptEnv forwarding
Updates #3559
2026-10-29 20:51:36 +01:00
arkie 8cf43952af types: emit SSH environment capability by default
Fixes #3559
2026-10-29 20:51:36 +01:00
Kristoffer Dalby beb1214926 release: reject dirty sources and build artifacts
Fixes #3583
2026-10-29 15:39:30 +01:00
Kristoffer Dalby c285eff776 CHANGELOG: list the oss-scanner findings for 0.29.7
Move the #3603 entries to 0.29.7 and link the pull request.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 729464091e testcapture: refuse golden captures that name no tool commit
It walks every testdata folder, so a new folder is covered too. Captures
taken since tscap refuses such builds are listed until taken again.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 208043c88d oidc: keep email_verified with the address it came with
Fixes ANT-2026-MX8FKG4K
2026-10-29 14:00:02 +01:00
Kristoffer Dalby b5bebf9b32 db, state: let only the delete that removed a node free its addresses
Fixes ANT-2026-NWTIBB02
2026-10-29 14:00:02 +01:00
Kristoffer Dalby c9e9f72857 state: drop registration locks once unused
The lock is taken before any credential check, so client-chosen machine
keys grew the map forever. Ref-count entries; delete at zero.

Fixes ANT-2026-ZC18AF82
2026-10-29 14:00:02 +01:00
Kristoffer Dalby b833be283c types, auth, noise: let one request wait on each auth session
One verdict per session, so one waiter: the newest. A displaced one
returns at once (register error, SSH re-delegate), not at session end.
A waiter keeps only the follow-up URL and the cached registration.

Fixes ANT-2026-NM50ZP4N
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 7892a8462c auth: check the follow-up's machine key before it waits
A session has one verdict; another machine holding the URL could take
it.

Fixes ANT-2026-NM50ZP4N
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 28959cb27c noise: time out stalled bodies and idle tunnels
The hijack drops the outer server's deadlines; any machine key gets a
tunnel.

Fixes ANT-2026-K903ZEUA
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 5a4d366ce1 auth, state: keep only hostname, OS and tags in pending registrations
The rest arrives with the first MapRequest. A relogin keeps the node's
current Hostinfo, endpoints and disco key; an oversized merge is a 400.

Fixes ANT-2026-RQS7JAPP
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 4ce928411e state: bound client reports of nodes loaded at startup
Rows stored before the bounds are trimmed the same way at load; a
Hostinfo still over budget is dropped until the node reports again.

Fixes ANT-2026-RQS7JAPP
Fixes ANT-2026-5B6KE87K
Fixes ANT-2026-KFCFFM34
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 2e563635d0 types, noise: bound the Hostinfo and endpoints a client reports
Keep the first 256 endpoints and 4096 routes; refuse longer hostnames,
too many tags, zoned endpoints and >64 KiB NetInfo or other Hostinfo.
The body limit counted wire bytes, not what NodeStore and peers keep.

Fixes ANT-2026-RQS7JAPP
Fixes ANT-2026-5B6KE87K
Fixes ANT-2026-KFCFFM34
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 15a8c7584e hscontrol: refuse a key expiry that cannot be encoded
handleRegister, the OIDC auth path and SetNodeExpiry refuse it. Expiries
are stored in UTC, which SQLite can read back, and loaded in UTC, as
PostgreSQL returns the server's zone. The v1 API answers 400.

Fixes ANT-2026-QMCAFJ1Q
2026-10-29 14:00:02 +01:00
Kristoffer Dalby e3c1bfd68e mapper: skip peers whose key expiry cannot be encoded
json.Marshal refuses a year outside [0,9999], so one stored expiry
failed every map with that node. TailNode and key patches send UTC, the
builder drops what fails and the boot scan names the node.

Fixes ANT-2026-QMCAFJ1Q
2026-10-29 14:00:02 +01:00
Kristoffer Dalby b23d4dc535 .github: regenerate integration test workflow 2026-10-29 14:00:02 +01:00
Kristoffer Dalby e1de83cbdf state: give another user's key on a tagged machine a new device
Only a key that speaks for a tagged node re-authenticates it: a tagged
key, or one of the user it was tagged from. Another user's key or login
adds that user's own device, or only wakes the node under its node key.

Fixes ANT-2026-AWGRB7O1
2026-10-29 14:00:02 +01:00
Kristoffer Dalby e67ef8619a state: need a valid pre-auth key to re-register an expired tagged node
Fixes ANT-2026-LYVGXVSW
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 47d82023e7 state: never serve a single address inside the node ranges
Such a route names a node, not a subnet: it stays approved and listed
but no viewer gets it. Via inclusions skip the election, so the rule
sits on everything RoutesForPeer returns.

Fixes ANT-2026-MLP8ZR5T
2026-10-29 14:00:02 +01:00
Kristoffer Dalby c4d4e32f12 servertest, policy/v2: add re-authentication golden data
Expired, live, ephemeral and admin-tagged devices logging in again with
spent, revoked, valid and other users' keys, by key and by login;
tag ownership through tags per policy function.

Updates ANT-2026-LYVGXVSW
Updates ANT-2026-AWGRB7O1
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 5c2cf6ed6f servertest: add login, profile, restart and register log helpers
TryNewClient returns a refused login; Login covers profile switches and
interactive logins approved through ApproveAuth; RegisterAttempts reads
the client's register log.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby b18bbf4313 servertest: add route approval lifecycle golden data
Owner changes, re-auth, revokes, policy pushes, withdraw and logout
replayed step by step against SaaS approvals and served routes.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby aa40174989 prek: exempt step captures from the large file check
They keep a netmap per node per step and must stay as recorded.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 1716eece74 servertest: add relogin and auth key helpers
Relogin builds a new Direct on the same machine key and persisted
node key, as tailscaled does on up --auth-key; force rotates the key.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 286d6ea05d policy/v2, servertest, hscontrol: add tailnet overlap route captures
Routers announcing tailnet addresses, approved by policy, admin key and
devices:routes token; replayed through policy, map stream and v1/v2
APIs.

Updates ANT-2026-MLP8ZR5T
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 59f7c558a6 servertest: compare router self routes with captures
Replays ten routes captures through the mapper too; SaaS's address
ranges for "*" now resolve. Known gaps are skip entries per node.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 32652326b9 servertest: compare user profiles in via captures
Self and peer profiles, by login and display name. A tagged self gets
its own profile in SaaS; listed as a skip entry until headscale matches.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 7d787867c9 servertest: list passing via captures
Fourteen committed via captures already match at map level; run them.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 1e397e8cd5 testcapture: record multi-step captures and API error detail
Optional Steps, NodeIDs, error data and login state; v1 files unchanged.
Register log and raw map frame parsers; Write refuses auth keys and
login URLs.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 46e374aa78 hscontrol: keep golden file names valid in Go module zips
A '>' in one name stopped go get from fetching headscale.
2026-10-29 14:00:02 +01:00
Kristoffer Dalby 0dd9079d0b .gitattributes: mark golden data as generated
GitHub collapses generated files in pull request diffs.
2026-10-29 14:00:02 +01:00
github-actions[bot] 2e465d85b9 all: regenerate generated files 2026-10-29 13:39:27 +01:00
github-actions[bot] b715b9041d .github: bump 3 action pins 2026-10-29 13:39:27 +01:00
github-actions[bot] 2a17ad88eb go.mod: update dependencies 2026-10-29 13:39:27 +01:00
github-actions[bot] d4d4c7c7a3 Makefile: bump oapi-codegen v2.8.0 to v2.8.1 2026-10-29 13:39:27 +01:00
github-actions[bot] 816c7065ee flake.lock: update nixpkgs 2026-10-29 13:39:27 +01:00
Kristoffer Dalby cd66e2414a noise: restrict metrics to the metrics listener
Fixes #3571
2026-10-29 13:05:56 +01:00
Kristoffer Dalby 1a48b276ef docs: explain how to disable SSH forwarding 2026-10-29 12:43:14 +01:00
Kristoffer Dalby 998c4b0619 policy: pin SSH forwarding behavior and recommend upgrades 2026-10-29 12:43:14 +01:00
Kristoffer Dalby bd1876e1fa tools/bump: keep the tested Terraform provider releases current
A new release arrives as a bump pull request; verify reports a stale set.
2026-10-29 11:04:05 +01:00