Cache DNS results of earlier login.tailscale.com control dials, and use
them for future dials if DNS is slow or broken.
Fixes various issues with trickier setups with the domain's DNS server
behind a subnet router.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In 1.0, subnet relays were not specially handled when WPAD+PAC was
present on the network.
In 1.2, on Windows, subnet relays were disabled if WPAD+PAC was
present. That was what some users wanted, but not others.
This makes it configurable per domain, reverting back to the 1.0
default state of them not being special. Users who want that behavior
can then enable it.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In tests, we force binding to localhost to avoid OS firewall warning
dialogs.
But for IPv6, we were trying (and failing) to bind to 127.0.0.1.
You'd think we'd just say "localhost", but that's apparently ill
defined. See
https://tools.ietf.org/html/draft-ietf-dnsop-let-localhost-be-localhost
and golang/go#22826. (It's bitten me in the past, but I can't
remember specific bugs.)
So use "::1" explicitly for "udp6", which makes the test quieter.
Seeing "frontend-provided legacy machine key" was weird (and not quite
accurate) on Linux machines where it comes from the _daemon key's
persist prefs, not the "frontend".
Make the log message distinguish between the cases.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Otherwise log upload HTTP requests generate proxy errrors which
generate logs which generate HTTP requests which generate proxy
errors which generate more logs, etc.
Fixes#879
When the service was running without a client (e.g. after a reboot)
and then the owner logs in and the GUI attaches, the computed state
key changed to "" (driven by frontend prefs), and then it was falling
out of server mode, despite the GUI-provided prefs still saying it
wanted server mode.
Also add some logging. And remove a scary "Access denied" from a
user-visible error, making the two possible already-in-use error
messages consistent with each other.
On Windows, we were previously treating a server used by different
users as a fatal error, which meant the second user (upon starting
Tailscale, explicitly or via Start Up programs) got an invasive error
message dialog.
Instead, give it its own IPN state and change the Notify.ErrMessage to
be details in that state. Then the Windows GUI can be less aggresive
about that happening.
Also,
* wait to close the IPN connection until the server ownership state
changes so the GUI doesn't need to repeatedly reconnect to discover
changes.
* fix a bug discovered during testing: on system reboot, the
ipnserver's serverModeUser was getting cleared while the state
transitioned from Unknown to Running. Instead, track 'inServerMode'
explicitly and remove the old accessor method which was error prone.
* fix a rare bug where the client could start up and set the server
mode prefs in its Start call and we wouldn't persist that to the
StateStore storage's prefs start key. (Previously it was only via a
prefs toggle at runtime)
os.IsNotExist doesn't unwrap errors. errors.Is does.
The ioutil.ReadFile ones happened to be fine but I changed them so
we're consistent with the rule: if the error comes from os, you can
use os.IsNotExist, but from any other package, use errors.Is.
(errors.Is always would also work, but not worth updating all the code)
The motivation here was that we were logging about failure to migrate
legacy relay node prefs file on startup, even though the code tried
to avoid that.
See golang/go#41122
It was especially bad on our GUI platforms with a frontend that polls it.
No need to log it every few seconds if it's unchanged. Make it slightly
less allocate-y while I'm here.
It's still Windows-only for now but it's easy to de-Windows-ify when needed.
Moving it out of corp repo and into tailscale/tailscale so we can use
it in ipnserver.BabysitProc.
Updates #726
Updating the Windows firewall is usually reasonably fast, but
sometimes blocks for 20 seconds, 4 minutes, etc. Not sure why.
Until we understand that's happening, configure it in the background
without blocking the normal control flow.
Updates #785
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If we can't find the mapping from SID ("user ID") -> username, don't
treat that as a fatal. Apparently that happens in the wild for Reasons.
Ignore it for now. It's just a nice-to-have for error messages in the
rare multi-user case.
Updates #869
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The RusagePrefixLog is rarely useful, hasn't been useful in a long
time, is rarely the measurement we need, and is pretty spammy (and
syscall-heavy). Disable it by default. We can enable it when we're
debugging memory.
Fix from regression in previous commit
(0e3048d8e0) that was caught by e2e
tests.
In that previous commit, the user's own profile was omitted from the
NetworkMap in the case where the user only had one node.
I was going to make support for this advertised from the client, but
turns out only "tailscale status" even uses the UserProfiles field and
fails gracefully (omits that field) if a user profile for a user is
missing, so I think we can just reuse the DeltaPeers field from the
client to ask the control server to also delta encode the user
profiles.
For the few users running 1.1.x (unstable) versions between DeltaPeers
support (1.1.82) and this (~1.1.541), they'll just sometimes have
missing names in "tailscale status --json" or "tailscale status --web"
(the only places the UserProfile is used).
The previous code read too explicitly like log.Printf("I am here1"),
log.Printf("I am here2"). It still is with this change, but prettier, and
less subject to code rearranging order.
We were creating the controlclient and starting the portpoll concurrently,
which frequently resulted in the first controlclient connection being canceled
by the firsdt portpoll result ~milliseconds later, resulting in another
HTTP request.
Instead, wait a bit for the first portpoll result so it's much less likely to
interrupt our controlclient connection.
Updates tailscale/corp#557
On startup, clients do a MapRequest with empty endpoints while they
learn the DERP map to discover the STUN servers they then query to
learn their endpoints.
Set MapRequest.ReadOnly on those initial queries to not broadcast the
empty endpoints out to peers. The read results will come a half second
later (or less).
Updates tailscale/corp#557
At startup the client doesn't yet have the DERP map so can't do STUN
queries against DERP servers, so it only knows it local interface
addresses, not its STUN-mapped addresses.
We were reporting the interface-local addresses to control, getting
the DERP map, and then immediately reporting the full set of
updates. That was an extra HTTP request to control, but worse: it was
an extra broadcast from control out to all the peers in the network.
Now, skip the initial update if there are no stun results and we don't
have a DERP map.
More work remains optimizing start-up requests/map updates, but this
is a start.
Updates tailscale/corp#557
There was a bug with the lazy wireguard config code where, if the
minimum set of peers to tell wireguard didn't change, we skipped
calling userspaceEngine.updateActivityMapsLocked which updated
the various data structures that matched incoming traffic to later
reconfigure the minimum config.
That meant if an idle peer restarted and changed discovery keys, we
skipped updating our maps of disco keys/IPs that would caused us to
lazily inflate the config for that peer later if/when it did send
traffic.
This partially (but not yet fully) migrates Windows to tailscaled's
StateStore storage system.
This adds a new bool Pref, ForceDaemon, defined as:
// ForceDaemon specifies whether a platform that normally
// operates in "client mode" (that is, requires an active user
// logged in with the GUI app running) should keep running after the
// GUI ends and/or the user logs out.
//
// The only current applicable platform is Windows. This
// forced Windows to go into "server mode" where Tailscale is
// running even with no users logged in. This might also be
// used for macOS in the future. This setting has no effect
// for Linux/etc, which always operate in daemon mode.
Then, when ForceDaemon becomes true, we now write use the StateStore
to track which user started it in server mode, and store their prefs
under that key.
The ipnserver validates the connections/identities and informs that
LocalBackend which userid is currently in charge.
The GUI can then enable/disable server mode at runtime, without using
the CLI.
But the "tailscale up" CLI was also fixed, so Windows users can use
authkeys or ACL tags, etc.
Updates #275
It was previously possible for two different Windows users to connect
to the IPN server at once, but it didn't really work. They mostly
stepped on each other's toes and caused chaos.
Now only one can control it, but it can be active for everybody else.
Necessary dependency step for Windows server/headless mode (#275)
While here, finish wiring up the HTTP status page on Windows, now that
all the dependent pieces are available.
Due to a copy/paste-o, we were monitoring address changes twice, and
not monitoring route changes at all.
Verified with 'tailscale debug --monitor' that this actually works now (while
running 'route add 10.3.0.0 mask 255.255.0.0 10.0.0.1' and 'route delete (same)'
back and forth in cmd.exe)
In practice route changes are accompanied by address changes and this
doesn't fix any known issues. I just noticed this while reading this
code again. But at least the code does what it was trying to do now.
If no interfaces are up, calm down and stop spamming so much. It was
noticed as especially bad on Windows, but probably was bad
everywhere. I just have the best network conditions testing on a
Windows VM.
Updates #604
So previous routes aren't shadowing resources that the operating
system might need (Windows Domain Controller, DNS server, corp HTTP
proxy, WinHTTP fetching the PAC file itself, etc).
This effectively detects when we're transitioning from, say, public
wifi to corp wifi and makes Tailscale remove all its routes and stops
its TCP connections and tries connecting to everything anew.
Updates tailscale/corp#653
Not used for anything yet (except logging), but populate the current
proxy autoconfig PAC URL in Interfaces.State.
A future change will do things based on it.