1eaad7d3de regressed some tests in another repo that were starting up
a control server on `http://127.0.0.1:nnn`. Because there was no https
running, and because of a bug in 1eaad7d3de (which ended up checking
the recently-dialed-control check twice in a single dial call), we
ended up forcing only the use of TLS dials in a test that only had
plaintext HTTP running.
Instead, plumb down support for explicitly disabling TLS fallbacks and
use it only when running in a test and using `http` scheme control
plane URLs to 127.0.0.1 or localhost.
This fixes the tests elsewhere.
Updates #13597
Change-Id: I97212ded21daf0bd510891a278078daec3eebaa6
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This pulls out the clock and forceNoise443 code into methods on the
Dialer as cleanup in its own commit to make a future change less
distracting.
Updates #13597
Change-Id: I7001e57fe7b508605930c5b141a061b6fb908733
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Coder has just adopted nhooyr/websocket which unfortunately changes the import path.
`github.com/coder/coder` imports `tailscale.com/net/wsconn` which was still pointing
to `nhooyr.io/websocket`, but this change updates it.
See https://coder.com/blog/websocket
Updates #13154
Change-Id: I3dec6512472b14eae337ae22c5bcc1e3758888d5
Signed-off-by: Kyle Carberry <kyle@carberry.com>
The same context we use for the HTTP request here might be re-used by
the dialer, which could result in `GotConn` being called multiple times.
We only care about the last one.
Fixes#13009
Signed-off-by: Anton Tolchanov <anton@tailscale.com>
The goal is to move more network state accessors to netmon.Monitor
where they can be cheaper/cached. But first (this change and others)
we need to make sure the one netmon.Monitor is plumbed everywhere.
Some notable bits:
* tsdial.NewDialer is added, taking a now-required netmon
* because a tsdial.Dialer always has a netmon, anything taking both
a Dialer and a NetMon is now redundant; take only the Dialer and
get the NetMon from that if/when needed.
* netmon.NewStatic is added, primarily for tests
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: I877f9cb87618c4eb037cee098241d18da9c01691
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This adds a health.Tracker to tsd.System, accessible via
a new tsd.System.HealthTracker method.
In the future, that new method will return a tsd.System-specific
HealthTracker, so multiple tsnet.Servers in the same process are
isolated. For now, though, it just always returns the temporary
health.Global value. That permits incremental plumbing over a number
of changes. When the second to last health.Global reference is gone,
then the tsd.System.HealthTracker implementation can return a private
Tracker.
The primary plumbing this does is adding it to LocalBackend and its
dozen and change health calls. A few misc other callers are also
plumbed. Subsequent changes will flesh out other parts of the tree
(magicsock, controlclient, etc).
Updates #11874
Updates #4136
Change-Id: Id51e73cfc8a39110425b6dc19d18b3975eac75ce
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This makes wsconn.Conns somewhat present reasonably when they are
the client of an http.Request, rather than just put a placeholder
in that field.
Updates tailscale/corp#13777
Signed-off-by: David Anderson <danderson@tailscale.com>
These specific tests rely on some timers in the controlhttp code.
Without time moving forward and timers triggering, the tests fail.
Updates #8587
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This passes the *dnscache.Resolver down from the Direct client into the
Noise client and from there into the controlhttp client. This retains
the Resolver so that it can share state across calls instead of creating
a new resolver.
Updates #4845
Updates #6110
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ia5d6af1870f3b5b5d7dd5685d775dcf300aec7af
On some platforms (notably macOS and iOS) we look up the default
interface to bind outgoing connections to. This is both duplicated
work and results in logspam when the default interface is not available
(i.e. when a phone has no connectivity, we log an error and thus cause
more things that we will try to upload and fail).
Fixed by passing around a netmon.Monitor to more places, so that we can
use its cached interface state.
Fixes#7850
Updates #7621
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Redoes the approach from #5550 and #7539 to explicitly pass in the logf
function, instead of having global state that can be overridden.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Using log.Printf may end up being printed out to the console, which
is not desirable. I noticed this when I was investigating some client
logs with `sockstats: trace "NetcheckClient" was overwritten by another`.
That turns to be harmless/expected (the netcheck client will fall back
to the DERP client in some cases, which does its own sockstats trace).
However, the log output could be visible to users if running the
`tailscale netcheck` CLI command, which would be needlessly confusing.
Updates tailscale/corp#9230
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
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>
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>
We don't require any cert at all for Noise-over-plaintext-port-80-HTTP,
so why require a valid cert chain for Noise-over-HTTPS? The reason we use
HTTPS at all is to get through firewalls that allow tcp/443 but not tcp/80,
not because we need the security properties of TLS.
Updates #3198
Signed-off-by: Brad Fitzpatrick <bradfitz@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>
The //go:build syntax was introduced in Go 1.17:
https://go.dev/doc/go1.17#build-lines
gofmt has kept the +build and go:build lines in sync since
then, but enough time has passed. Time to remove them.
Done with:
perl -i -npe 's,^// \+build.*\n,,' $(git grep -l -F '+build')
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
It was just added and unreleased but we've decided to go a different route.
Details are in 5e9e57ecf5.
Updates #5972
Change-Id: I49016af469225f58535f63a9b0fbe5ab6a5bf304
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
New plan for #5972. Instead of sending the public key in the clear
(from earlier unreleased 246274b8e9) where the client might have to
worry about it being dropped or tampered with and retrying, we'll
instead send it post-Noise handshake but before the HTTP/2 connection
begins.
This replaces the earlier extraHeaders hook with a different sort of
hook that allows us to combine two writes on the wire in one packet.
Updates #5972
Change-Id: I42cdf7c1859b53ca4dfa5610bd1b840c6986e09c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We removed it in #4806 in favor of the built-in functionality from the
nhooyr.io/websocket package. However, it has an issue with deadlines
that has not been fixed yet (see nhooyr/websocket#350). Temporarily
go back to using a custom wrapper (using the fix from our fork) so that
derpers will stop closing connections too aggressively.
Updates #5921
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Not currently used, but will allow us to usually remove a round-trip for
a future feature.
Updates #5972
Change-Id: I2770ea28e3e6ec9626d1cbb505a38ba51df7fba2
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Control may not be bound to (just) localhost when sharing dev servers,
allow the Wasm client to connect to it in that case too.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
* tailcfg, control/controlhttp, control/controlclient: add ControlDialPlan field
This field allows the control server to provide explicit information
about how to connect to it; useful if the client's link status can
change after the initial connection, or if the DNS settings pushed by
the control server break future connections.
Change-Id: I720afe6289ec27d40a41b3dcb310ec45bd7e5f3e
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
This turns 'dialParams' into something more like net.Dialer, where
configuration fields are public on the struct.
Split out of #5648
Change-Id: I0c56fd151dc5489c3c94fb40d18fd639e06473bc
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
The data that we send over WebSockets is encrypted and thus not
compressible. Additionally, Safari has a broken implementation of compression
(see nhooyr/websocket#218) that makes enabling it actively harmful.
Fixestailscale/corp#6943
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Forcing the insecure protocol (and perserving the port number) is only
desired for localhost testing, in prod we need to use wss:// to avoid
mixed-content errors.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
We can't do Noise-over-HTTP in Wasm/JS (because we don't have bidirectional
communication), but we should be able to do it over WebSockets. Reuses
derp WebSocket support that allows us to turn a WebSocket connection
into a net.Conn.
Updates #3157
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Just because we get an HTTP upgrade response over port 80, don't
assume we'll be able to do bi-di Noise over it. There might be a MITM
corp proxy or anti-virus/firewall interfering. Do a bit more work to
validate the connection before proceeding to give up on the TLS port
443 dial.
Updates #4557 (probably fixes)
Change-Id: I0e1bcc195af21ad3d360ffe79daead730dfd86f1
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The connections returned from SystemDial are automatically closed when
there is a major link change.
Also plumb through the dialer to the noise client so that connections
are auto-reset when moving from cellular to WiFi etc.
Updates #3363
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Doing so makes development unpleasant, because we have to first break the
client by bumping to a version the control server rejects, then upgrade
the control server to make it accept the new version.
This strict rejection at handshake time is only necessary if we want to
blocklist some vulnerable protocol versions in the future. So, switch
to a default-permissive stance: until we have such a version that we
have to eagerly block early, we'll accept whatever version the client
presents, and leave it to the user of controlbase.Conn to make decisions
based on that version.
Noise still enforces that the client and server *agree* on what protocol
version is being used, and the control server still has the option to
finish the handshake and then hang up with an in-noise error, rather
than abort at the handshake level.
Updates #3488
Signed-off-by: David Anderson <danderson@tailscale.com>
This is so that we can plumb our client capability version through
the protocol as the Noise version. The capability version increments
more frequently than strictly required (the Noise version only needs
to change when cryptographically-significant changes are made to
the protocol, whereas the capability version also indicates changes
in non-cryptographically-significant parts of the protocol), but this
gives us a safe pre-auth way to determine if the client supports
future protocol features, while still relying on Noise's strong
assurance that the client and server have agreed on the same version.
Currently, the server executes the same protocol regardless of the
version number, and just presents the version to the caller so they
can do capability-based things in the upper RPC protocol. In future,
we may add a ratchet to disallow obsolete protocols, or vary the
Noise handshake behavior based on requested version.
Updates #3488
Signed-off-by: David Anderson <danderson@tailscale.com>
When I deployed server-side changes, I put the upgrade handler at /ts2021
instead of /switch. We could move the server to /switch, but ts2021 seems
more specific and better, but I don't feel strongly.
Updates #3488
Change-Id: Ifbf8ea60a815fd2fa1bfbe1b7af1ac2a27218354
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>