Commit Graph
5033 Commits
Author SHA1 Message Date
Kristoffer Dalby 4f6a727e93 gen/client/v2: regenerate for routeSelection 2026-11-03 17:05:00 +01:00
Kristoffer Dalby 88f90d040d api/v2: report routeSelection in tailnet settings 2026-11-03 17:05:00 +01:00
Kristoffer Dalby b9f12abf02 gen/client/v2: regenerate for the device host detail 2026-11-03 17:05:00 +01:00
Kristoffer Dalby 7063c04581 api/v2: add device shields-up, SSH, distro and connectivity fields
Same read shapes as SaaS. Latency stays empty: headscale drops it on arrival.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 9ba1c5e5e2 gen/client/v2: regenerate for connectedToControl and lastSeen 2026-11-03 17:05:00 +01:00
Kristoffer Dalby f1788c1ce4 api/v2: send connectedToControl and lastSeen on connected devices
SaaS sends both on every device. The SDK reported live devices as
disconnected, and tscli delete devices panicked on the missing lastSeen.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 9841280d11 api/v2: use SaaS's text for an unknown device 2026-11-03 17:05:00 +01:00
Kristoffer Dalby e99d8f3f88 api/v2: list devices sorted by name
SaaS sorts by name. NodeStore order moved on every write, so
order-sensitive Terraform configs showed changes.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 88339d8ff1 servertest: pin the refusal of a policy naming autogroup:admin
The replay rewrites the autogroup away, so nothing showed this difference.
2026-11-03 17:05:00 +01:00
Kristoffer Dalby 1bce65a236 policy/v2: name ssh-behavior-v1 a deliberate difference
SaaS stamps it on every node. Sending it would change existing users' login
environment, so it stays a nodeAttr. Document that and pin it.
2026-11-03 17:05:00 +01:00
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