Commit Graph
5023 Commits
Author SHA1 Message Date
Kristoffer Dalby 39a42e9d01 policy/v2: refuse autogroup:member as a test source
As SaaS: unknown user or host. A policy that passed here failed on SaaS.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 98b3900470 policy/v2: resolve user:*@domain to that domain's users
SaaS accepts it and lists those users' nodes. It was accepted here too,
then compiled to nothing with no log line.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 6647cb2e05 policy/v2: map no numeric email local part to a login
The client looks a numeric login up as a UID, so 0@domain reached root
under a localpart rule, and another number someone else's account.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby f786ae33cd state: send the whole node when a relogin removes a key expiry
A patch omits a zero expiry, so peers kept the old one and would cut the
node off when it passed.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 868998a81b state: let a node's name follow a new hostname at login
As SaaS. It stayed old, and the mismatch then read as an admin-set name,
which stopped later hostname changes from renaming the node too.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 197895be2c auth: refuse requested tags with SaaS's bare text
Clients show it as it is, and it carried an internal prefix.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 4ec3f3c161 auth: do not register a deleted device on its logout
A client sends its auth key with a logout. The past expiry only logged,
then the key made a new offline node that peers could see.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 65ccbdeea2 poll: tell peers a node left after 15 seconds, not 10
As SaaS. A router outage of 10 to 15 seconds moved the HA primary for good,
and status flapped. A real crash now fails over 5 seconds later, as on SaaS.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 672aa40158 state: move an offline router's routes in one frame
As SaaS. A peer held an offline primary between two frames: the patch, then
the recompute, which carries the offline state anyway.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby c2b4c97ce1 mapper: send no frame when stripping leaves nothing new
Stripping an unchanged Node and SSHPolicy per stream could leave a frame
with only ControlTime, which SaaS never sends.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 2d094f2243 state: send nothing for a policy write that changes nothing
As SaaS. Every accepted write sent all nodes a map and cleared SSH check
approvals, so a tool that re-posts the same file prompted users again.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 93aef86908 mapper: give a tagged node its own user in its own entry
As SaaS. Clients take a peer with their own user ID for a device of the same
owner, so every tagged peer was a file target and could read debug endpoints.
Updates #2462, #2970
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 490305417c policy/v2: make a user's own devices peers under any policy
As SaaS. Without the peer, sending a file to your own device failed
with 404 under a restrictive policy. The packet filter is unchanged.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 420293cecf policy/v2: keep withdrawn approved routes in wildcard sources
As SaaS, which holds them until an admin removes the approval.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby d2a85b1d16 policy/v2: compile a policy without rules as explicit allow-all
As SaaS, sources are the tailnet ranges and approved routes. They were
"*", so a host on an exit node's network could reach its clients.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 5741dba87d policy/v2: sort approved routes in wildcard sources
They followed NodeStore map order, so the same policy read as changed.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 8ba627c3f4 types: leave the base domain out of search domains without MagicDNS
As SaaS. Alone, it left a client that writes resolv.conf with no nameserver.
Updates #2029
2026-11-03 17:05:00 +01:00
Kristoffer Dalby b04bbd4317 mapper: send a disable-ipv4 holder its peers over IPv6 only
As SaaS. Peers' 100.x addresses routed into tailscale0 and hid a local
host with the same address, which is what the attr is meant to avoid.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 68b0274694 types: lead AllowedIPs with the node's own addresses
As SaaS. tailscale whois prints AllowedIPs[2:] as routes, so sorted
entries showed an own address in place of a subnet route.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby edad4ff324 types: do not stamp is-admin on tagged nodes
A tagged node has no user to hold the role. SaaS leaves it out unless policy
grants it. Stop stripping the cap, so captures now compare it.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 581ec5b3a0 derp: keep node order across map refreshes
Clients close their home relay when its order changes. SaaS's never moved.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 6fe0df64e1 CHANGELOG: note the map field changes
Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby a7f2c85cfd mapper: send base_domain as the exit node filtered set
SaaS sends its own domains, which name nothing here. Otherwise an exit node
proxies tailnet names, and where its OS resolver reaches MagicDNS a client
reads its view of the tailnet. MagicDNS only: without it, base_domain can be
public, and clients ask the exit node for its names. Reverse lookups stay
open, as on SaaS.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby ef6d033d19 state, change: send the last seen time in the offline patch
As SaaS, on every offline patch and no online one. Peers otherwise show no
last-seen time until the next full map. SaaS sends a coarser time; the exact
one here is deliberate.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 5083d77731 mapper: leave online state off a node's own entry
As SaaS. Clients take their own state from the map poll.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 50be190482 mapper: leave Cap off a node's own entry
As SaaS. Clients read it from peers only; a client knows its own version.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 7d50f33e32 types: leave MachineAuthorized off peer entries
SaaS sets it only on a node's own entry, the only one clients read.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 0d5e4f28e9 types: stop sending machine keys in map entries
Stable identity that outlives node key rotation. SaaS sends it on no entry; no
client from our minimum version on acts on it.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 12de511271 servertest: compare map entry fields with SaaS
Wire rules from frames, entry fields from a replay, exit node filter by the
names it covers. Known differences listed as skips.

Updates #3626
2026-11-03 16:29:03 +01:00
Kristoffer Dalby 1986b52983 CHANGELOG: note via applying only to the ip part of a grant
Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 398223c640 servertest: replay the via grant shapes through the mapper
Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby f88a24c509 policy/v2: record via grant shapes
Narrow and subnet sources, app with and without ip, an empty app, and a non-via
primary.

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 2c70845bda policy/v2: count a router in a subnet source as a via viewer
SaaS sends it the via route (via-grant-v83).

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 9fff03f4b5 policy/v2: apply via only to the ip part of a grant
SaaS treats app as if via were absent: v80 and v84 peer the same, v87 peers a
non-via router, v88 and v91 send the route on the primary. Dropping a via grant
with no ip at compile left grant-k12's nodes with no peers.

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby aa7b2ab404 policyutil: send a router no capability for its subnet
via-grant-v84 and v86 show SaaS sending none.

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 3fdedefbf9 policy/v2: link a via grant's sources to its router only
A rule naming the route also linked a router that is a source to all others
serving it. SaaS does not (via-grant-v81).

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 5642d976b2 policy, state: correct MatchersForNode's doc
It filters routes. Peers come from BuildPeerMap.

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby 5be981ca95 servertest: replay the member-to-subnet routes capture
Same shape as #3626: the router is in no rule.

Updates #3626
2026-11-03 15:53:04 +01:00
Kristoffer Dalby aeceef9cce policy/v2: anonymize a public endpoint in older captures
Recordings since hold only documentation addresses.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby 52d6dea601 hscontrol: drop user profiles no node in a capture uses
A client keeps every profile it was sent; these were never SaaS state.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby ec2e76e7cd servertest: replay ACL captures with auto-approved routes
Only the policy approves their routes, so broken approval fails the replay.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby 7a47710d64 servertest: keep filter sources that name no peer
They stopped a replay before any comparison; a side lacking one still differs.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby db0b6c9d5d policy/v2: hold source form skips to the same addresses
A listed check hides any difference, so both filter paths must first match as ranges.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby c59e19be21 policy/v2: check that captures agree on routes
Parts of a capture are read seconds apart, so an approval can split them.
Also refuses tool failures, lost nodes, unknown peers, lagging viewers and approvals that never landed.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby 4671143b8f policy/v2: record again captures split by a route approval
tscap read approved_routes before the netmaps, and five captures lost a node.
Contiguous new addresses make SaaS and headscale source forms differ, so those checks are listed.
Also moved by recording now: capver 131 to 142, default-auto-update, self RoutableIPs.
2026-11-03 15:52:58 +01:00
Kristoffer Dalby 8b41925a1f nix: support systemctl reload in the headscale service
Fixes #3027

Claude-Session: https://claude.ai/code/session_01RHEZM1qJ2hgndiXio7P56h
2026-11-03 15:52:52 +01:00
Kristoffer Dalby c7daf6d923 .github: regenerate integration test workflow
Fixes #3027

Claude-Session: https://claude.ai/code/session_01RHEZM1qJ2hgndiXio7P56h
2026-11-03 15:52:52 +01:00
Kristoffer Dalby 021f0294f8 integration: test TLS certificate reload on SIGHUP
Fixes #3027

Claude-Session: https://claude.ai/code/session_01RHEZM1qJ2hgndiXio7P56h
2026-11-03 15:52:52 +01:00
Kristoffer Dalby b3ffec4269 hscontrol: reload manual TLS certificate on SIGHUP
Files that fail to load or are not valid now keep the previous certificate.

Fixes #3027

Claude-Session: https://claude.ai/code/session_01RHEZM1qJ2hgndiXio7P56h
2026-11-03 15:52:52 +01:00
Kristoffer Dalby 7bd88aee79 .github: exempt milestoned issues from stale bot, stale after 45 days (#3652)
Milestone means triaged. Close message said 14 days; config is 7.
2026-11-03 15:52:47 +01:00