This change adds a ringbuffer to each magicsock endpoint that keeps a
fixed set of "changes"–debug information about what updates have been
made to that endpoint.
Additionally, this adds a LocalAPI endpoint and associated
"debug peer-status" CLI subcommand to fetch the set of changes for a given
IP or hostname.
Updates tailscale/corp#9364
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I34f726a71bddd0dfa36ec05ebafffb24f6e0516a
Makes it cheaper/simpler to persist values, and encourages reuse of
labels as opposed to generating an arbitrary number.
Updates tailscale/corp#9230
Updates #3363
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This prevents a panic where we synthesize a new netmap in
setClientStatus after we've shut down and nil'd out the controlclient,
since that function expects to be called while connected to control.
Fixes#7392
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ib631eb90f34f6afa008d69bbb386f70da145e102
Uses the hooks added by tailscale/go#45 to instrument the reads and
writes on the major code paths that do network I/O in the client. The
convention is to use "<package>.<type>:<label>" as the annotation for
the responsible code path.
Enabled on iOS, macOS and Android only, since mobile platforms are the
ones we're most interested in, and we are less sensitive to any
throughput degradation due to the per-I/O callback overhead (macOS is
also enabled for ease of testing during development).
For now just exposed as counters on a /v0/sockstats PeerAPI endpoint.
We also keep track of the current interface so that we can break out
the stats by interface.
Updates tailscale/corp#9230
Updates #3363
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The log ID types were moved to a separate package so that
code that only depend on log ID types do not need to link
in the logic for the logtail client itself.
Not all code need the logtail client.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Exposes the delegated interface data added by #7248 in the debug
endpoint. I would have found it useful when working on that PR, and
it may be handy in the future as well.
Also makes the interfaces table slightly easier to parse by adding
borders to it. To make then nicer-looking, the CSP was relaxed to allow
inline styles.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
With #6566 we added an external mechanism for getting the default
interface, and used it on macOS and iOS (see tailscale/corp#8201).
The goal was to be able to get the default physical interface even when
using an exit node (in which case the routing table would say that the
Tailscale utun* interface is the default).
However, the external mechanism turns out to be unreliable in some
cases, e.g. when multiple cellular interfaces are present/toggled (I
have occasionally gotten my phone into a state where it reports the pdp_ip1
interface as the default, even though it can't actually route traffic).
It was observed that `ifconfig -v` on macOS reports an "effective interface"
for the Tailscale utn* interface, which seems promising. By examining
the ifconfig source code, it turns out that this is done via a
SIOCGIFDELEGATE ioctl syscall. Though this is a private API, it appears
to have been around for a long time (e.g. it's in the 10.13 xnu release
at https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/net/if_types.h.auto.html)
and thus is unlikely to go away.
We can thus use this ioctl if the routing table says that a utun*
interface is the default, and go back to the simpler mechanism that
we had before #6566.
Updates #7184
Updates #7188
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Followup to #7235, we were not treating the formatting arguments as
variadic. This worked OK for single values, but stopped working when
we started passing multiple values (noticed while trying out #7244).
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Useful when debugging issues (e.g. to see the full routing table), and
easier to refer to the output via a browser than trying to read it from
the logs generated by `bugreport --diagnose`.
Behind a canDebug() check, similar to the /magicsock and /interfaces
endpoints.
Updates #7184
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
With #6566 we started to more aggressively bind to the default interface
on Darwin. We are seeing some reports of the wrong cellular interface
being chosen on iOS. To help with the investigation, this adds to knobs
to control the behavior changes:
- CapabilityDebugDisableAlternateDefaultRouteInterface disables the
alternate function that we use to get the default interface on macOS
and iOS (implemented in tailscale/corp#8201). We still log what it
would have returned so we can see if it gets things wrong.
- CapabilityDebugDisableBindConnToInterface is a bigger hammer that
disables binding of connections to the default interface altogether.
Updates #7184
Updates #7188
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The profileManager was using the LoginName as a proxy to figure out if the profile
had logged in, however the LoginName is not present if the node was created with an
Auth Key that does not have an associated user.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
We now handle the case where the NetworkMap.SelfNode has already expired
and do not return an expiry time in the past (which causes an ~infinite
loop of timers to fire).
Additionally, we now add an explicit check to ensure that the next
expiry time is never before the current local-to-the-system time, to
ensure that we don't end up in a similar situation due to clock skew.
Finally, we add more tests for this logic to ensure that we don't
regress on these edge cases.
Fixes#7193
Change-Id: Iaf8e3d83be1d133a7aab7f8d62939e508cc53f9c
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
If the user passes the --diagnose flag, print a warning if any of the
default or fallback DNS resolvers are Tailscale IPs. This can interfere
with the ability to connect to the controlplane, and is typically
something to pay attention to if there's a connectivity issue.
Change-Id: Ib14bf6228c037877fbdcd22b069212b1a4b2c456
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
We can log too quickly for logtail to catch up, even when we opt out of
log rate-limiting. When the user passes the --diagnose flag to
bugreport, we use a token bucket to control how many logs per second are
printed and sleep until we're able to write more.
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: If27672d66b621b589280bd0fe228de367ffcbd8f
The iOS has a command to reset the persisted state of the app, but it
was doing its own direct keychain manipulation. This proved to be
brittle (since we changed how preferences are stored with #6022), so
we instead add a LocalAPI endpoint to do do this, which can be updated
in tandem.
This clears the same state as the iOS implementation (tailscale/corp#3186),
that is the machine key and preferences (which includes the node key).
Notably this does not clear the logtail ID, so that logs from the device
still end up in the same place.
Updates tailscale/corp#8923
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This updates all source files to use a new standard header for copyright
and license declaration. Notably, copyright no longer includes a date,
and we now use the standard SPDX-License-Identifier header.
This commit was done almost entirely mechanically with perl, and then
some minimal manual fixes.
Updates #6865
Signed-off-by: Will Norris <will@tailscale.com>
When turned on via environment variable (off by default), this will use
the BSD routing APIs to query what interface index a socket should be
bound to, rather than binding to the default interface in all cases.
Updates #5719
Updates #5940
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ib4c919471f377b7a08cd3413f8e8caacb29fee0b
This allows users to temporarily enable/disable dnscache logging via a
new node capability, to aid in debugging strange connectivity issues.
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I46cf2596a8ae4c1913880a78d0033f8b668edc08
The current node isn't in NetMap.Peers, so without this we would not
have fired this timer on self expiry.
Updates #6932
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Id57f96985397e372f9226802d63b42ff92c95093
On macOS (AppStore and macsys), we need to bind to ""/all-interfaces
due to the network sandbox. Ideally we would only bind to the
Tailscale interface, but macOS errors out if we try to
to listen on privileged ports binding only to a specific
interface.
We also implement the lc.Control hook, same as we do for
peerapi. It doesn't solve our problem but it's better that
we do and would likely be required when Apple gets around to
fixing per-interface priviliged port binding.
Fixes: #6364
Signed-off-by: Shayne Sweeney <shayne@tailscale.com>
This change delays the first flush in the /watch-ipn-bus/ handler
until after the watcher has been successfully installed on the IPN
bus. It does this by adding a new onWatchAdded callback to
LocalBackend.WatchNotifications().
Without this, the endpoint returns a 200 almost immediatly, and
only then installs a watcher for IPN events. This means there's a
small window where events could be missed by clients after calling
WatchIPNBus().
Fixestailscale/corp#8594.
Signed-off-by: salman <salman@tailscale.com>
In order to be able to synthesize a new NetMap when a node expires, have
LocalBackend start a timer when receiving a new NetMap that fires
slightly after the next node expires. Additionally, move the logic that
updates expired nodes into LocalBackend so it runs on every netmap
(whether received from controlclient or self-triggered).
Updates #6932
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I833390e16ad188983eac29eb34cc7574f555f2f3
Needed for clients that get information via the /v0/status LocalAPI
endpoint (e.g. to not offer expired exit nodes as options).
Updates tailscale/corp#8702
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
UI works remains, but data is there now.
Updates #4015
Change-Id: Ib91e94718b655ad60a63596e59468f3b3b102306
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Unsigned peers should not be allowed to generate Wake-on-Lan packets,
only access Funnel.
Updates #6934
Updates #7515
Updates #6475
Signed-off-by: James Tucker <james@tailscale.com>
This makes `tailscale debug watch-ipn` safe to use for troubleshooting
user issues, in addition to local debugging during development.
Signed-off-by: David Anderson <danderson@tailscale.com>
By default, `http.Transport` keeps idle connections open hoping to re-use them in the future. Combined with a separate transport per request in HTTP proxy this results in idle connection leak.
Fixes#6773
Use multierr.Range to iterate through an error tree
instead of multiple invocations of errors.As.
This scales better as we add more Go error types to the switch.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Mainly motivated by wanting to know how much Taildrop is used, but
also useful when tracking down how many invalid requests are
generated.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Nodes which have both -advertise-exit-node and -exit-node in prefs
should continue have them until the next invocation of `tailscale up`.
Updates #3569.
Signed-off-by: salman <salman@tailscale.com>
* Do not print the status at the end of a successful operation
* Ensure the key of the current node is actually trusted to make these changes
Signed-off-by: Tom DNetto <tom@tailscale.com>
This handles the case where the inner *os.PathError is wrapped in
another error type, and additionally will redact errors of type
*os.LinkError. Finally, add tests to verify that redaction works.
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ie83424ff6c85cdb29fb48b641330c495107aab7c
x/exp/slices now has ContainsFunc (golang/go#53983) so we can delete
our versions.
Change-Id: I5157a403bfc1b30e243bf31c8b611da25e995078
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For testing of Windows GUI client.
Updates #6480
Change-Id: I42f7526d95723e14bed7085fb759e371b43aa9da
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
To simplify clients getting the initial state when they subscribe.
Change-Id: I2490a5ab2411253717c74265a46a98012b80db82
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If user's fn returned false and never canceled their ctx, we never
stopped the NotifyWatchEngineUpdates goroutine.
This was introduced recently (this cycle).
Change-Id: I3453966ac71e00727296ddd237ef845782f4e52e
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We were writing the error when getting the default interface before
setting the content type, so we'd get HTML treated as plain text.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The peerapi IPv6 listener has a nil listener.
But we didn't need the listener's address anyway, so don't
try to use it.
Change-Id: I8e8a1a895046d129a3683973e732d9bed82f3b02
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Previously, `TAILSCALE_USE_WIP_CODE` was needed to hit a bunch of the TKA paths. With
this change:
- Enablement codepaths (NetworkLockInit) and initialization codepaths (tkaBootstrapFromGenesisLocked via tkaSyncIfNeeded)
require either the WIP envknob or CapabilityTailnetLockAlpha.
- Normal operation codepaths (tkaSyncIfNeeded, tkaFilterNetmapLocked) require TKA to be initialized, or either-or the
envknob / capability.
- Auxillary commands (ie: changing tka keys) require TKA to be initialized.
The end result is that it shouldn't be possible to initialize TKA (or subsequently use any of its features) without being
sent the capability or setting the envknob on tailscaled yourself.
I've also pulled out a bunch of unnecessary checks for CanSupportNetworkLock().
Signed-off-by: Tom DNetto <tom@tailscale.com>
We merge/dedupe profiles based on UserID and NodeID, however we were not accounting for ControlURLs.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The Go style weirds people out so we try to stick to the more
well-known double hyphen style in docs.
Change-Id: Iad6db5c82cda37f6b7687eed7ecd9276f8fd94d6
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This reverts commit f1130421f0.
It was submitted with failing tests (go generate checks)
Requires a lot of API changes to fix so rolling back instead of
forward.
Change-Id: I024e8885c0ed44675d3028a662f386dda811f2ad
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We want users to have the freedom to start tailscaled with `-no-logs-no-support`,
but that is obviously in direct conflict with tailnets that have network logging
enabled.
When we detect that condition, we record the issue in health, notify the client,
set WantRunning=false, and bail.
We clear the item in health when a profile switch occurs, since it is a
per-tailnet condition that should not propagate across profiles.
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
Only the macOS/iOS clients care about it still, so we'll move it
to their repo.
But keep a test that makes sure that LocalBackend continues to
implement it so we get an early warning sign before we break
macOS/iOS.
Change-Id: I56392b740fe55b4d28468b77124c821b5c46c22b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We use this pattern in a number of places (in this repo and elsewhere)
and I was about to add a fourth to this repo which was crossing the line.
Add this type instead so they're all the same.
Also, we have another Set type (SliceSet, which tracks its keys in
order) in another repo we can move to this package later.
Change-Id: Ibbdcdba5443fae9b6956f63990bdb9e9443cefa9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The "userID is empty everywhere but Windows" docs on lots of places
but not everywhere while using just a string type was getting
confusing. This makes a new type to wrap up those rules, however
weird/historical they might be.
Change-Id: I142e85a8e38760988d6c0c91d0efecedade81b9b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
So GUI clients don't need to poll for it.
We still poll internally (for now!) but that's still cheaper. And will
get much cheaper later, without having to modify clients once they
start sending this bit.
Change-Id: I36647b701c8d1fe197677e5eb76f6894e8ff79f7
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Follow-up to #6467 and #6506.
LocalBackend knows the server-mode state, so move more auth checking
there, removing some bookkeeping from ipnserver.Server.
Updates #6417
Updates tailscale/corp#8051
Change-Id: Ic5d14a077bf0dccc92a3621bd2646bab2cc5b837
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This matches CanSSHD (TS_DISABLE_SSH_SERVER) for administratively
disabling the code on a node, regardless of local or server configs.
This can be configured in /etc/default/tailscaled on Linux,
%ProgramData%\Tailscale\tailscaled-env.txt on Windows,
or /etc/tailscale/tailscaled-env.txt on Synology. (see getPlatformEnvFile)
Also delete some dead code and tidy up some docs.
Change-Id: I79a87c03e33209619466ea8aeb0f6651afcb8789
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Centralize the fake GOOS stuff, start to use it more. To be used more
in the future.
Change-Id: Iabacfbeaf5fca0b53bf4d5dbcdc0367f05a205f9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
While reading the DNS code noticed that we were still using FallbackResolvers
in this code path but the comment was out of date.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Profile keys are not deleted but are instead set to `nil` which results
in getting a nil error and we were not handling that correctly.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit implements `tailscale lock log [--limit N]`, which displays an ordered list
of changes to network-lock state in a manner familiar to `git log`.
Signed-off-by: Tom DNetto <tom@tailscale.com>
By always firing off a sync after enablement, the control plane should know the node's TKA head
at all times.
Signed-off-by: Tom DNetto <tom@tailscale.com>
We were not checking the currentUserID in all code paths that looped over
knownProfiles. This only impacted multi-user Windows setups.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The earlier 5f6d63936f was not complete.
Updates tailscale/corp#7515
Change-Id: I35efca51d1584c48ef6834a7d29cd42d7c943628
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We would end up with duplicate profiles for the node as the UserID
would have chnaged. In order to correctly deduplicate profiles, we
need to look at both the UserID and the NodeID. A single machine can
only ever have 1 profile per NodeID and 1 profile per UserID.
Note: UserID of a Node can change when the node is tagged/untagged,
and the NodeID of a device can change when the node is deleted so we
need to check for both.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The fix in 4fc8538e2 was sufficient for IPv6. Browsers (can?) send the
IPv6 literal, even without a port number, in brackets.
Updates tailscale/corp#7948
Change-Id: I0e429d3de4df8429152c12f251ab140b0c8f6b77
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I was too late with review feedback to 513780f4f8.
Updates tailscale/corp#7948
Change-Id: I8fa3b4eba4efaff591a2d0bfe6ab4795638b7c3a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We were not updating the LoginProfile.UserProfile when a netmap
updated the UserProfile (e.g. when a node was tagged via the admin panel).
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This moves the NetworkLock key from a dedicated StateKey to be part of the persist.Persist struct.
This struct is stored as part for ipn.Prefs and is also the place where we store the NodeKey.
It also moves the ChonkDir from "/tka" to "/tka-profile/<profile-id>". The rename was intentional
to be able to delete the "/tka" dir if it exists.
This means that we will have a unique key per profile, and a unique directory per profile.
Note: `tailscale logout` will delete the entire profile, including any keys. It currently does not
delete the ChonkDir.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
We do not need to wait for it to complete. And we might have to
call Shutdown from callback from the controlclient which might
already be holding a lock that Shutdown requires.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Found by tests in another repo. TKA code wasn't always checking enough to be sure a node-key was set for the current state.
Signed-off-by: Tom DNetto <tom@tailscale.com>
The health package was turning into a rando dumping ground. Make a new
Warnable type instead that callers can request an instance of, and
then Set it locally in their code without the health package being
aware of all the things that are warnable. (For plenty of things the
health package will want to know details of how Tailscale works so it
can better prioritize/suppress errors, but lots of the warnings are
pretty leaf-y and unrelated)
This just moves two of the health warnings. Can probably move more
later.
Change-Id: I51e50e46eb633f4e96ced503d3b18a1891de1452
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This makes it so that the backend also restarts when users change,
otherwise an extra call to Start was required.
Updates #713
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Noticed this while debugging something else, we would reset all routes if
either `--advertise-exit-node` or `--advertise-routes` were set. This handles
correctly updating them.
Also added tests.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
It left the envknob turned on which meant that running all the tests
in the package had different behavior than running just any one test.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Example output:
# Health check:
# - Some peers are advertising routes but --accept-routes is false
Also, move "tailscale status" health checks to the bottom, where they
won't be lost in large netmaps.
Updates #2053
Updates #6266
Change-Id: I5ae76a0cd69a452ce70063875cd7d974bfeb8f1a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Numerous issues have been filed concerning an inability to install and run
Tailscale headlessly in unattended mode, particularly after rebooting. The
server mode `Prefs` stored in `server-state.conf` were not being updated with
`Persist` state once the node had been succesfully logged in.
Users have been working around this by finagling with the GUI to make it force
a state rewrite. This patch makes that unnecessary by ensuring the required
server mode state is updated when prefs are updated by the control client.
Fixes https://github.com/tailscale/tailscale/issues/3186
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
Even if the name is right, or is configured on a different port.
Updates tailscale/corp#7515
Change-Id: I8b721968f3241af10d98431e1b5ba075223e6cd3
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>