When the repo is checked out as a nested worktree, a go.work in the
outer tree hijacks module resolution, which makes the rebuild fails
with "main module does not contain package." Set GOWORK=off for the
build since the hook is self-contained.
Bumps HOOK_VERSION so existing installs pick up the fix.
Updates #cleanup
Change-Id: Ibd14849efc26e4e1893c5b8e300caa71573f54bd
Signed-off-by: Fernando Serboncini <fserb@fserb.com.br>
Pull the hook logic into a reusable githook library package so
tailscale/corp can share it via a thin wrapper main instead of
keeping a forked copy in sync.
The install flow also changes: a wrapper scripts now build the
binary and reinstall the git hooks. Pulling new shared code no
longer requires re-running the installer.
Updates tailscale/corp#39860
Change-Id: I4d606d11c8c883015c190c54e3387a7f9fe4dd32
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
reflect.DeepEqual is expensive and allocates heavily. Replace it with
a field-by-field comparison that does zero allocations.
Adds tests and benchmarks for the new Equal method.
Fixes#19363
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
On dual-stack clusters defaulting to IPv6, the ProxyGroup egress
service only got an IPv6 address, which causes request failures.
Individual egress proxies already set PreferDualStack correctly.
Fixes: #18768
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Consolidate the duplicated WebSocket frame-parsing logic from Read
and Write into a shared processFrames loop, fixing several bugs in
the process:
- Mixed control and data frames in a single Read/Write call buffer
were not handled: a control frame would cause merged data frames
to be skipped.
- Multiple data frames into one Write call weren't being correctly
parsed: only the first frame was processed, ignoring the rest in
the buffer.
- msg.isFinalized was being set before confirming the fragment was
complete, so an incomplete msg fragment, could've been sometimes
marked as finalized.
- Continuation frames without any payload were being treated as if
they didn't have stream ID, even thought the id is already known
from the initial fragment.
Fixestailscale/corp#39583
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
Co-authored-by: chaosinthecrd <tom@tmlabs.co.uk>
Set csrf.Path("/") so the CSRF cookie is available across all routes,
not just the path where it was set.
Add helpers to expose the gorilla/csrf token for use.
Updates #19264
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
derpActiveFunc was being called immediately as a bare goroutine,
before startGate was resolved. For the firstDerp case, startGate
is c.derpStarted which only closes after dc.Connect() completes,
so derpActiveFunc was firing before the DERP connection existed.
We now block it with the same logic used by runDerpReader and by
runDerpWriter.
Updates: #18810
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
The test ping() passed the full 60s context to each PingWithOpts call,
so if the first attempt hung (DERP not yet registered), the retry loop
never reached attempt 2. Use a 2s per-call timeout instead.
Updates: #18810
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Stop stripping the "*." prefix from wildcard domains when used
as storage keys. Instead, replace "*" with "wildcard_" only at
the filesystem boundary in certFile and keyFile. This prevents
wildcard and non-wildcard certs from colliding in storage.
Updates #1196
Updates #7081
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Instead of relying on the local timezone, which may cause
non-deterministic behavior in some CIs, we force timezone
to be UTC on default created clocks.
Fixes: tailscale/corp#37005
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
When the NodeAttrDNSSubdomainResolve capability is present, enable
wildcard certificate issuance to cover all single-level subdomains
of a node's CertDomain.
Without the capability, only exact CertDomain matches are allowed,
so node.ts.net yields a cert for node.ts.net. With the capability,
we now generate wildcard certificates. Wildcard certs include both
the wildcard and base domain in their SANs, and ACME authorization
requests both identifiers. The cert filenames are kept still based
on the base domain with the wildcard prefix stripped, so we aren't
creating separate files. DNS challenges still used the base domain
The checkCertDomain function is replaced by resolveCertDomain that
both validates and returns the appropriate cert domain to request.
Name validation is now moved earlier into GetCertPEMWithValidity()
Fixes#1196
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
On Windows, TempDir cleanup fails if file handles are still open.
TestConcurrentSameFile wasn't closing Filch instances before exit
Fixes#18570
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
This adds a new node capability 'dns-subdomain-resolve' that signals
that all of hosts' subdomains should resolve to the same IP address.
It allows wildcard matching on any node marked with this capability.
This change also includes an util/dnsname utility function that lets
us access the parent of a full qualified domain name. MagicDNS takes
this function and recursively searchs for a matching real node name.
One important thing to observe is that, in this context, a subdomain
can have multiple sub labels. This means that for a given node named
machine, both my.machine and be.my.machine will be a positive match.
Updates #1196
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
When tailscaled gets started with userspace networking, it won't
modify your system's network configuration. For this, it creates
a noopManager for DNS management. noopManager correctly observes
that there's no real OS DNS to send queries to. This leads to we
completely dropping any DNS internal resolution from `dns query`
This change alters this so that even without a base config we'll
still allow the internal resolver to handle internal DNS queries
Fixes#18354
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
* cmd/k8s-operator: add support for taiscale.com/http-redirect
The k8s-operator now supports a tailscale.com/http-redirect annotation
on Ingress resources. When enabled, this automatically creates port 80
handlers that automatically redirect to the equivalent HTTPS location.
Fixes#11252
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
* Fix for permanent redirect
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
* lint
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
* warn for redirect+endpoint
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
* tests
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
---------
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Adds a new Redirect field to HTTPHandler for serving HTTP redirects
from the Tailscale serve config. The redirect URL supports template
variables ${HOST} and ${REQUEST_URI} that are resolved per request.
By default, it redirects using HTTP Status 302 (Found). For another
redirect status, like 301 - Moved Permanently, pass the HTTP status
code followed by ':' on Redirect, like: "301:https://tailscale.com"
Updates #11252
Updates #11330
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
Single letter 'l' variables can eventually become confusing when
they're rendered in some fonts that make them similar to 1 or I.
Updates #cleanup
Signed-off-by: Fernando Serboncini <fserb@tailscale.com>