summaryrefslogtreecommitdiffhomepage
path: root/control/controlhttp/client.go
AgeCommit message (Collapse)AuthorFilesLines
2025-10-03feature/ace: make ACE modularBrad Fitzpatrick1-6/+10
Updates #12614 Change-Id: Iaee75d8831c4ba5c9705d7877bb78044424c6da1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-30feature, net/tshttpproxy: pull out support for using proxies as a featureBrad Fitzpatrick1-4/+9
Saves 139 KB. Also Synology support, which I saw had its own large-ish proxy parsing support on Linux, but support for proxies without Synology proxy support is reasonable, so I pulled that out as its own thing. Updates #12614 Change-Id: I22de285a3def7be77fdcf23e2bec7c83c9655593 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-20control/controlhttp: simplify, fix race dialing, remove priority conceptBrad Fitzpatrick1-136/+42
controlhttp has the responsibility of dialing a set of candidate control endpoints in a way that minimizes user facing latency. If one control endpoint is unavailable we promptly dial another, racing across the dimensions of: IPv6, IPv4, port 80, and port 443, over multiple server endpoints. In the case that the top priority endpoint was not available, the prior implementation would hang waiting for other results, so as to try to return the highest priority successful connection to the rest of the client code. This hang would take too long with a large dialplan and sufficient client to endpoint latency as to cause the server to timeout the connection due to inactivity in the intermediate state. Instead of trying to prioritize non-ideal candidate connections, the first successful connection is now used unconditionally, improving user facing latency and avoiding any delays that would encroach on the server-side timeout. The tests are converted to memnet and synctest, running on all platforms. Fixes #8442 Fixes tailscale/corp#32534 Co-authored-by: James Tucker <james@tailscale.com> Change-Id: I4eb57f046d8b40403220e40eb67a31c41adb3a38 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Signed-off-by: James Tucker <james@tailscale.com>
2025-09-19net/ace, control/controlhttp: start adding ACE dialing supportBrad Fitzpatrick1-24/+54
Updates tailscale/corp#32227 Change-Id: I38afc668f99eb1d6f7632e82554b82922f3ebb9f Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-06-18net/tlsdial: fix TLS cert validation of HTTPS proxiesBrad Fitzpatrick1-1/+1
If you had HTTPS_PROXY=https://some-valid-cert.example.com running a CONNECT proxy, we should've been able to do a TLS CONNECT request to e.g. controlplane.tailscale.com:443 through that, and I'm pretty sure it used to work, but refactorings and lack of integration tests made it regress. It probably regressed when we added the baked-in LetsEncrypt root cert validation fallback code, which was testing against the wrong hostname (the ultimate one, not the one which we were being asked to validate) Fixes #16222 Change-Id: If014e395f830e2f87f056f588edacad5c15e91bc Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-08net/{netx,memnet},all: add netx.DialFunc, move memnet Network implBrad Fitzpatrick1-1/+2
This adds netx.DialFunc, unifying a type we have a bazillion other places, giving it now a nice short name that's clickable in editors, etc. That highlighted that my earlier move (03b47a55c7956) of stuff from nettest into netx moved too much: it also dragged along the memnet impl, meaning all users of netx.DialFunc who just wanted netx for the type definition were instead also pulling in all of memnet. So move the memnet implementation netx.Network into memnet, a package we already had. Then use netx.DialFunc in a bunch of places. I'm sure I missed some. And plenty remain in other repos, to be updated later. Updates tailscale/corp#27636 Change-Id: I7296cd4591218e8624e214f8c70dab05fb884e95 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-02control/controlhttp: reduce some log spam on context cancelBrad Fitzpatrick1-0/+5
Change-Id: I3ac00ddb29c16e9791ab2be19f454dabd721e4c3 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-02control/controlhttp: set forceNoise443 on Plan 9Brad Fitzpatrick1-0/+9
Updates #5794 Change-Id: Idc67082f5d367e03540e1a5310db5b466ee03666 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-03-25control/controlhttp: quiet "forcing port 443" log spamBrad Fitzpatrick1-1/+6
Minimal mitigation that doesn't do the full refactor that's probably warranted. Updates #15402 Change-Id: I79fd91de0e0661d25398f7d95563982ed1d11561 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-11-07control/controlhttp/controlhttpserver: split out Accept to its own packageBrad Fitzpatrick1-4/+5
Otherwise all the clients only using control/controlhttp for the ts2021 HTTP client were also pulling in WebSocket libraries, as the server side always needs to speak websockets, but only GOOS=js clients speak it. This doesn't yet totally remove the websocket dependency on Linux because Linux has a envknob opt-in to act like GOOS=js for manual testing and force the use of WebSockets for DERP only (not control). We can put that behind a build tag in a future change to eliminate the dep on all GOOSes. Updates #1278 Change-Id: I4f60508f4cad52bf8c8943c8851ecee506b7ebc9 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-02control/control{client,http}: don't noise dial localhost:443 in http-only testsBrad Fitzpatrick1-7/+16
1eaad7d3deb 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 1eaad7d3deb (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>
2024-10-02control/controlhttp: rename a param from addr to optAddr for clarityBrad Fitzpatrick1-14/+20
And update docs. Updates #cleanup Updates #13597 (tangentially; noted this cleanup while debugging) Change-Id: I62440294c78b0bb3f5673be10318dd89af1e1bfe Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-01control/controlhttp: fix connectivity on Alaska Air wifiBrad Fitzpatrick1-0/+12
Updates #13597 Change-Id: Ifbf52b93fd35d64fcf80f8fddbfd610008fd8742 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-01control/controlhttp: factor out some code in prep for future changeBrad Fitzpatrick1-10/+21
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>
2024-08-06control/controlhttp: extract the last network connectionAnton Tolchanov1-12/+13
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>
2024-06-20control/controlclient: add more Screen Time blocking detectionBrad Fitzpatrick1-2/+3
Updates #9658 Updates #12545 Change-Id: Iec1dad354a75f145567b4055d77b1c1db27c89e2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Co-authored-by: Andrea Gottardo <andrea@gottardo.me>
2024-06-19control/controlhttp: add health warning for macOS filtering blocking ↵Brad Fitzpatrick1-1/+43
Tailscale (#12546) Updates #9658 Updates #12545 Change-Id: I6612b9b65eb193a1a651e219b5198c7c20ed94e1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Co-authored-by: Andrea Gottardo <andrea@tailscale.com>
2024-04-27net/netns, net/dns/resolver, etc: make netmon required in most placesBrad Fitzpatrick1-2/+0
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>
2024-04-26health, all: remove health.Global, finish plumbing health.TrackerBrad Fitzpatrick1-2/+1
Updates #11874 Updates #4136 Change-Id: I414470f71d90be9889d44c3afd53956d9f26cd61 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-04-25tsd, ipnlocal, etc: add tsd.System.HealthTracker, start some plumbingBrad Fitzpatrick1-1/+2
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>
2023-08-04control: use tstime instead of time (#8595)Claire Wang1-3/+10
Updates #8587 Signed-off-by: Claire Wang <claire@tailscale.com>
2023-05-01control/controlclient: use dnscache.Resolver for Noise clientAndrew Dunham1-7/+17
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
2023-04-20all: avoid repeated default interface lookupsMihai Parparita1-1/+3
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>
2023-04-17net/dnsfallback: more explicitly pass through logf functionMihai Parparita1-1/+1
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>
2023-04-12net/sockstats: pass in logger to sockstats.WithSockStatsMihai Parparita1-1/+1
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>
2023-03-12various: pass logger.Logf through to more placesAndrew Dunham1-0/+2
Updates #7537 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Id89acab70ea678c8c7ff0f44792d54c7223337c6
2023-03-06sockstats: switch label to enumMihai Parparita1-1/+1
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>
2023-03-01sockstats: instrument networking code pathsMihai Parparita1-0/+3
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>
2023-02-08control/controlhttp: don't require valid TLS cert for Noise connectionBrad Fitzpatrick1-3/+17
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>
2023-01-27all: update copyright and license headersWill Norris1-3/+2
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>
2023-01-17control/controlhttp: add TS_FORCE_NOISE_443, TS_DEBUG_NOISE_DIAL envknobsBrad Fitzpatrick1-2/+25
Updates tailscale/docker-extension#49 Change-Id: I99a154c16c92228bfdf4d2cf6c58cda00e22d72f Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-11-04all: remove old +build tagsBrad Fitzpatrick1-1/+0
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>
2022-10-28control/controlhttp: remove ClientConn.UntrustedUpgradeHeadersBrad Fitzpatrick1-10/+9
It was just added and unreleased but we've decided to go a different route. Details are in 5e9e57ecf531f. Updates #5972 Change-Id: I49016af469225f58535f63a9b0fbe5ab6a5bf304 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-10-17control/controlhttp: allow setting, getting Upgrade headers in Noise upgradeBrad Fitzpatrick1-18/+21
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>
2022-09-23tailcfg, control/controlhttp, control/controlclient: add ControlDialPlan ↵Andrew Dunham1-9/+192
field (#5648) * 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>
2022-09-16control/controlhttp: move Dial options into options struct (#5661)Andrew Dunham1-40/+40
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>
2022-08-15Allow any port for HTTPS when using Noise over TLSJuan Font Alonso1-9/+5
Signed-off-by: Juan Font Alonso <juanfontalonso@gmail.com>
2022-06-02control/controlhttp: allow client and server to communicate over WebSocketsMihai Parparita1-15/+3
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>
2022-04-28control/controlhttp: don't assume port 80 upgrade response will workBrad Fitzpatrick1-28/+43
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>
2022-04-27net/tsdial: add SystemDial as a wrapper on netns.DialMaisem Ali1-6/+5
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>
2022-04-27control/controlhttp: start port 443 fallback sooner if 80's stuckBrad Fitzpatrick1-31/+82
Fixes #4544 Change-Id: I39877e71915ad48c6668351c45cd8e33e2f5dbae Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-04-07control/controlbase: make the protocol version number selectable.David Anderson1-3/+5
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>
2022-03-24net/netutil: move some net utils from control/controlhttp to netutilBrad Fitzpatrick1-18/+2
In prep for reuse elsewhere. Change-Id: I1b804edf76ac66b9108e6f434e77eab7a7472d69 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-02-26controlhttp: add some docs, change Dial's path from /switch to /ts2021Brad Fitzpatrick1-4/+15
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>
2022-01-17control/controlhttp: package to get a controlbase.Conn over HTTP(S).David Anderson1-0/+242
Updates #3488 Signed-off-by: David Anderson <danderson@tailscale.com>