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>
* and move goroutine scrubbing code to its own package for reuse
* bump capver to 45
Change-Id: I9b4dfa5af44d2ecada6cc044cd1b5674ee427575
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
SetDNS calls were broken by 6d04184325 the other day. Unreleased.
Caught by tests in another repo.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
At some point we started restarting map polls on health change, but we
don't remember why. Maybe it was a desperate workaround for something.
I'm not sure it ever worked.
Rather than have a haunted graveyard, remove it.
In its place, though, and somewhat as a safety backup, send those
updates over the HTTP/2 noise channel if we have one open. Then if
there was a reason that a map poll restart would help we could do it
server-side. But mostly we can gather error stats and show
machine-level health info for debugging.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In prep for a future change that would've been very copy/paste-y.
And because the set-dns call doesn't currently use a context,
so timeouts/cancelations are plumbed.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
- removed some in-flow time calls
- increase buffer size to 2MB to overcome syscall cost
- move relative time computation from record to report time
Signed-off-by: James Tucker <james@tailscale.com>
The fragment offset is an 8 byte offset rather than a byte offset, so
the short packet limit is now in fragment block size in order to compare
with the offset value.
The packet flags are in the first 3 bits of the flags/frags byte, and
so after conversion to a uint16 little endian value they are at the
start, not the end of the value - the mask for extracting "more
fragments" is adjusted to match this byte.
Extremely short fragments less than 80 bytes are dropped, but fragments
over 80 bytes are now accepted.
Fixes#5727
Signed-off-by: James Tucker <james@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>
We're adding two log IDs to facilitate data-plane audit logging: a node-specific
log ID, and a domain-specific log ID.
Updated util/deephash/deephash_test.go with revised expectations for tailcfg.Node.
Updates https://github.com/tailscale/corp/issues/6991
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This fixes a race condition which caused `c.muCond.Broadcast()` to
never fire in the `firstDerp` if block. It resulted in `Close()`
hanging forever.
Signed-off-by: Kyle Carberry <kyle@carberry.com>
Personal preference (so it's obvious it's not a bool flag), but it
also matches the --state= before it.
Bonus: stop allowing PORT to sneak in extra flags to be passed as
their own arguments, as $FOO and ${FOO} expand differently. (${FOO} is
required to concat to strings)
Change-Id: I994626a5663fe0948116b46a971e5eb2c4023216
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
As the comment in the code says, netstack should always respond to ICMP
echo requests to a 4via6 address, even if the netstack instance isn't
normally processing subnet traffic.
Follow-up to #5709
Change-Id: I504d0776c5824071b2a2e0e687bc33e24f6c4746
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
It was checking if the sshServer was initialized as a proxy, but that
could either not have been initialized yet or Tailscale SSH could have
been disabled after intialized.
Also bump tailcfg.CurrentCapabilityVersion
Signed-off-by: Maisem Ali <maisem@tailscale.com>
We were just logging them to the console, which is useful for debugging,
but we may want to show them in the UI too.
Updates tailscale/corp#6939
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This doesn't change any behaviour for now, other than maybe running a
full netcheck more often. The intent is to start gathering data on
captive portals, and additionally, seeing this in the 'tailscale
netcheck' command should provide a bit of additional information to
users.
Updates #1634
Change-Id: I6ba08f9c584dc0200619fa97f9fde1a319f25c76
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
d5e7e309 changed the `hostinfo.GetVersion` from distro and distro version
to UTS Name Release and moved distribution information under
`hostinfo.Distro*`.
`tailscale configure-host` command implementation for Synology DSM
environments relies on the old semantics of this string for matching DSM
Major version so it's been broken for a few days.
Pull in `hostinfo` and prefix match `hostinfo.DistroVersion` to match
DSM major version.
Signed-off-by: Berk D. Demir <bdd@mindcast.org>
5 seconds may not be enough if we're still loading the derp map and
connecting to a slow machine.
Updates #5693
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The check was happening too early and in the case of error would wait 5
s and then error out. This makes it so that it does validations before
the SSH check.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
For control to fetch a list of Tailscale SSH username candidates to
filter against the Tailnet's SSH policy to present some valid
candidates to a user.
Updates #3802
Updates tailscale/corp#7007
Change-Id: I3dce57b7a35e66891d5e5572e13ae6ef3c898498
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This would've caught the regression from 7c49db02a before it was
submitted so 42f1d92ae0 wouldn't have been necessary to fix it.
Updates #4482
Change-Id: Ia4a9977e21853f68df96f043672c86a86c0181db
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
From 5c42990c2f, not yet released in a stable build.
Caught by existing tests.
Fixes#5685
Change-Id: Ia76bb328809d9644e8b96910767facf627830600
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Baby steps towards turning off heartbeat pings entirely as per #540.
This doesn't change any current magicsock functionality and requires additional
changes to send/disco paths before the flag can be turned on.
Updates #540
Change-Id: Idc9a72748e74145b068d67e6dd4a4ffe3932efd0
Signed-off-by: Jenny Zhang <jz@tailscale.com>
Signed-off-by: Jenny Zhang <jz@tailscale.com>
ipnserver previously had support for a Windows-only environment
variable mechanism that further only worked when Windows was running
as a service, not from a console.
But we want it to work from tailscaed too, and we want it to work on
macOS and Synology. So move it to envknob, now that envknob can change
values at runtime post-init.
A future change will wire this up for more platforms, and do something
more for CLI flags like --port, which the bug was originally about.
Updates #5114
Change-Id: I9fd69a9a91bb0f308fc264d4a6c33e0cbe352d71
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
So things like #5660 don't happen in the future.
Change-Id: I01234f241e297d5b7bdd18da1bb3cc5420ad2225
Signed-off-by: Brad Fitzpatrick <bradfitz@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 GitHub CodeQL scanner flagged the localapi's cert domain usage as a problem
because user input in the URL made it to disk stat checks.
The domain is validated against the ipnstate.Status later, and only
authenticated root/configured users can hit this, but add some
paranoia anyway.
Change-Id: I373ef23832f1d8b3a27208bc811b6588ae5a1ddd
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The io/ioutil package has been deprecated as of Go 1.16 [1]. This commit
replaces the existing io/ioutil functions with their new definitions in
io and os packages.
Reference: https://golang.org/doc/go1.16#ioutil
Signed-off-by: Eng Zer Jun <engzerjun@gmail.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>
The version.CmdName implementation is buggy such that it does not correctly
identify the binary name if it embeds other go binaries.
For now, add a NewWithConfigPath API that allows the caller to explicitly
specify this information.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
As noted in #5617, our documented method of blocking log.tailscale.io
DNS no longer works due to bootstrap DNS.
Instead, provide an explicit flag (--no-logs-no-support) and/or env
variable (TS_NO_LOGS_NO_SUPPORT=true) to explicitly disable logcatcher
uploads. It also sets a bit on Hostinfo to say that the node is in that
mode so we can end any support tickets from such nodes more quickly.
This does not yet provide an easy mechanism for users on some
platforms (such as Windows, macOS, Synology) to set flags/env. On
Linux you'd used /etc/default/tailscaled typically. Making it easier
to set flags for other platforms is tracked in #5114.
Fixes#5617Fixestailscale/corp#1475
Change-Id: I72404e1789f9e56ec47f9b7021b44c025f7a373a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This change masks the bitspace used when setting and querying the fwmark on packets. This allows
tailscaled to play nicer with other networking software on the host, assuming the other networking
software is also using fwmarks & a different mask.
IPTables / mark module has always supported masks, so this is safe on the netfilter front.
However, busybox only gained support for parsing + setting masks in 1.33.0, so we make sure we
arent such a version before we add the "/<mask>" syntax to an ip rule command.
Signed-off-by: Tom DNetto <tom@tailscale.com>
The auto-generated hostname is nice as a default, but there are cases
where the client has a more specific name that it can generate.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The default WebLinksAddon handler uses window.open(), but that gets blocked
by the popup blocker when the event being handled is another window. We
instead need to invoke open() on the window that the event was triggered
in.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The `tailscale web` UI is the primary interface for Synology and Home
Assistant users (and perhaps others), so is the logical place to put our
open source license notices. I don't love adding things to what is
currently a very minimal UI, but I'm not sure of a better option.
Updates tailscale/corp#5780
Signed-off-by: Will Norris <will@tailscale.com>
The plan has changed. Doing query parameters rather than path +
heades. NextDNS added support for query parameters.
Updates #2452
Change-Id: I4783c0a06d6af90756d9c80a7512644ba702388c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For debugging a macOS-specific magicsock issue. macOS runs in
bind-to-interface mode always. This lets me force Linux into the same
mode as macOS, even if the Linux kernel supports SO_MARK, as it
usually does.
Updates #2331 etc
Change-Id: Iac9e4a7429c1781337e716ffc914443b7aa2869d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
And put the rationale in the name too to save the callers the need for a comment.
Change-Id: I090f51b749a5a0641897ee89a8fb2e2080c8b782
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
More user friendly, and as a side-effect we handle SSH check mode better,
since the URL that's output is now clickable.
Fixes#5247
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Clarify & verify that some DoH URLs can be sent over tailcfg
in some limited cases.
Updates #2452
Change-Id: Ibb25db77788629c315dc26285a1059a763989e24
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
NextDNS is unique in that users create accounts and then get
user-specific DNS IPs & DoH URLs.
For DoH, the customer ID is in the URL path.
For IPv6, the IP address includes the customer ID in the lower bits.
For IPv4, there's a fragile "IP linking" mechanism to associate your
public IPv4 with an assigned NextDNS IPv4 and that tuple maps to your
customer ID.
We don't use the IP linking mechanism.
Instead, NextDNS is DoH-only. Which means using NextDNS necessarily
shunts all DNS traffic through 100.100.100.100 (programming the OS to
use 100.100.100.100 as the global resolver) because operating systems
can't usually do DoH themselves.
Once it's in Tailscale's DoH client, we then connect out to the known
NextDNS IPv4/IPv6 anycast addresses.
If the control plane sends the client a NextDNS IPv6 address, we then
map it to the corresponding NextDNS DoH with the same client ID, and
we dial that DoH server using the combination of v4/v6 anycast IPs.
Updates #2452
Change-Id: I3439d798d21d5fc9df5a2701839910f5bef85463
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Allows other work to be unblocked while xtermjs/xterm.js#4069 is worked
through.
To enable testing the popup window handling, the standalone app allows
opening of SSH sessions in new windows by holding down the alt key
while pressing the SSH button.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Store the requested size is a struct field, and use that when actually
creating the SSH session.
Fixes#5567
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Fix broken build from 255c0472fb
"Oh, that's safe to commit because most tests are passing and it's
just a comment change!", I thought, forgetting I'd added a test that
parses its comments.
Change-Id: Iae93d595e06fec48831215a98adbb270f3bfda05
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
gofmt in 1.19 is now opinionated about structured text formatting in
comments. It did not like our style and kept fighting us whenever we
changed these lines. Give up the fight and be a bulleted list for it.
See:
* https://go.dev/doc/go1.19#go-doc and
* https://go.dev/doc/comment
Updates #4872
Change-Id: Ifae431218471217168c003ab3b4e03c394ca8105
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Fixes an panic in `(*magicsock.Conn).ServeHTTPDebug` when the
`recentPongs` ring buffer for an endpoint wraps around.
Signed-off-by: Colin Adler <colin1adler@gmail.com>
If we accept a forwarded TCP connection before dialing, we can
erroneously signal to a client that we support IPv6 (or IPv4) without
that actually being possible. Instead, we only complete the client's TCP
handshake after we've dialed the outbound connection; if that fails, we
respond with a RST.
Updates #5425 (maybe fixes!)
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Allows imports of the NPM package added by 1a093ef482
to be replaced with import("http://localhost:9090/pkg/pkg.js"), so that
changes can be made in parallel to both the module and code that uses
it (without any need for NPM publishing or even building of the package).
Updates #5415
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Incoming disco packets are now dropped unless they match one of the
current bound ports, or have a zero port*.
The BPF filter passes all packets with a disco header to the raw packet
sockets regardless of destination port (in order to avoid needing to
reconfigure BPF on rebind).
If a BPF enabled node has just rebound, due to restart or rebind, it may
receive and reply to disco ping packets destined for ports other than
those which are presently bound. If the pong is accepted, the pinging
node will now assume that it can send WireGuard traffic to the pinged
port - such traffic will not reach the node as it is not destined for a
bound port.
*The zero port is ignored, if received. This is a speculative defense
and would indicate a problem in the receive path, or the BPF filter.
This condition is allowed to pass as it may enable traffic to flow,
however it will also enable problems with the same symptoms this patch
otherwise fixes.
Fixes#5536
Signed-off-by: James Tucker <james@tailscale.com>
1f959edeb0 introduced a regression for JS
where the initial bind no longer occurred at all for JS.
The condition is moved deeper in the call tree to avoid proliferation of
higher level conditions.
Updates #5537
Signed-off-by: James Tucker <james@tailscale.com>
Both RebindingUDPConns now always exist. the initial bind (which now
just calls rebind) now ensures that bind is called for both, such that
they both at least contain a blockForeverConn. Calling code no longer
needs to assert their state.
Signed-off-by: James Tucker <james@tailscale.com>
This is especially helpful as we launch newer DERPs over time, and older
clients have progressively out-of-date static DERP maps baked in. After
this, as long as the client has successfully connected once, it'll cache
the most recent DERP map it knows about.
Resolves an in-code comment from @bradfitz
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
It was previously using jobcontrol to achieve this, but that apparently
doesn't work when there is no tty. This makes it so that it directly
handles SIGINT and SIGTERM and passes it on to tailscaled. I tested this
works on a Digital Ocean K8s cluster.
Fixes#5512
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Allow callers to verify that a net.Listener is a tsnet.listener by type
asserting against this Server method, as well as providing access to the
underlying Server.
This is initially being added to support the caddy integration in
caddyserver/caddy#5002.
Signed-off-by: Will Norris <will@tailscale.com>
Apparently the validate route doesn't check content-types or handle
hujson with comments correctly. This patch makes gitops-pusher convert
the hujson to normal json.
Signed-off-by: Xe <xe@tailscale.com>
Signed-off-by: Xe <xe@tailscale.com>
With MagicDNS GA, we are giving every tailnet a tailnet-<hex>.ts.net name.
We will only parse out if legacy domains include beta.tailscale.net; otherwise,
set tailnet to the full domain format going forward.
Signed-off-by: nyghtowl <warrick@tailscale.com>
This is entirely optional (i.e. failing in this code is non-fatal) and
only enabled on Linux for now. Additionally, this new behaviour can be
disabled by setting the TS_DEBUG_DISABLE_AF_PACKET environment variable.
Updates #3824
Replaces #5474
Co-authored-by: Andrew Dunham <andrew@du.nham.ca>
Signed-off-by: David Anderson <danderson@tailscale.com>
This will be needed to support preauth-keys with network lock in the future,
so getting the core mechanics out of the way now.
Signed-off-by: Tom DNetto <tom@tailscale.com>
If ExtraRecords (Hosts) are specified without a corresponding split
DNS route and global DNS is specified, then program the host OS DNS to
use 100.100.100.100 so it can blend in those ExtraRecords.
Updates #1543
Change-Id: If49014a5ecc8e38978ff26e54d1f74fe8dbbb9bc
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We were just outputting them to the terminal, but that's hard to debug
because we immediately tear down the terminal when getting an error.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This makes a "modified externally" error turn into a "modified externally" warning. It means CI won't fail if someone does something manually in the admin console.
Signed-off-by: Xe <xe@tailscale.com>
The next time we update the toolchain, all of the CI
Actions will automatically use it when go.mod is updated.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
It is unclear whether the lack of checking nil-ness of slices
was an oversight or a deliberate feature.
Lacking a comment, the assumption is that this was an oversight.
Also, expand the logic to perform cycle detection for recursive slices.
We do this on a per-element basis since a slice is semantically
equivalent to a list of pointers.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Adds an on-demand GitHub Action that publishes the package to the npm
registry (currently under tailscale-connect, will be moved to
@tailscale/connect once we get control of the npm org).
Makes the package.json for the NPM package be dynamically generated to
have the current Tailscale client version.
Updates #5415
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
On sufficiently large tailnets, even writing the peer header (~95 bytes)
can result in a large amount of data that needs to be serialized and
deserialized. Only write headers for peers that need to have their
configuration changed.
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Avoid contention from fetching status for all peers, and instead fetch
status for a single peer.
Updates tailscale/coral#72
Signed-off-by: James Tucker <james@tailscale.com>
Somehow I accidentally set the wrong registry value here.
It should be DisableDynamicUpdate=1 and not EnableDNSUpdate=0.
This is a regression from 545639e.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This lets the control plane can make HTTP requests to nodes.
Then we can use this for future things rather than slapping more stuff
into MapResponse, etc.
Change-Id: Ic802078c50d33653ae1f79d1e5257e7ade4408fd
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I was working on my "dump iptables rules using only syscalls" branch and
had a bunch of C structure decoding to do. Rather than manually
calculating the padding or using unsafe trickery to actually cast
variable-length structures to Go types, I'd rather use a helper package
that deals with padding for me.
Padding rules were taken from the following article:
http://www.catb.org/esr/structure-packing/
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
In addition to printing goroutine stacks, explicitly track all in-flight
operations and print them when the watchdog triggers (along with the
time they were started at). This should make debugging watchdog failures
easier, since we can look at the longest-running operation(s) first.
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Prior to this change, if BIRD stops responding wgengine.watchdogEngine
will crash tailscaled.
This happens because in wgengine.userspaceEngine, we end up blocking
forever trying to write a request to or read a response from BIRD with
wgLock held, and then future watchdog'd calls will block on acquiring
that mutex until the watchdog kills the process. With the timeout, we at
least get the chance to print an error message and decide whether we
want to crash or not.
Updates tailscale/coral#72
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
Add a new lookupTypeHasher function that is just a cached front-end
around the makeTypeHasher function.
We do not need to worry about the recursive type cycle issue that
made getTypeInfo more complicated since makeTypeHasher
is not directly recursive. All calls to itself happen lazily
through a sync.Once upon first use.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
The entry logic of Hash has extra complexity to make sure
we always have an addressable value on hand.
If not, we heap allocate the input.
For this reason we document that there are performance benefits
to always providing a pointer.
Rather than documenting this, just enforce it through generics.
Also, delete the unused HasherForType function.
It's an interesting use of generics, but not well tested.
We can resurrect it from code history if there's a need for it.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This helps pprof better identify which Go kinds take the most time
since the kind is always in the function name.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This helps pprof better identify which Go kinds take the most time
since the kind is always in the function name.
There is a minor adjustment where we hash the length of the map
to be more on the cautious side.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Rather than having two copies []fieldInfo,
just maintain one and perform merging in the same pass.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This helps pprof better identify which Go kinds take the most time
since the kind is always in the function name.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Use of reflect.Value.SetXXX panics if the provided argument was
obtained from an unexported struct field.
Instead, pass an unsafe.Pointer around and convert to a
reflect.Value when necessary (i.e., for maps and interfaces).
Converting from unsafe.Pointer to reflect.Value guarantees that
none of the read-only bits will be populated.
When running in race mode, we attach type information to the pointer
so that we can type check every pointer operation.
This also type-checks that direct memory hashing is within
the valid range of a struct value.
We add test cases that previously caused deephash to panic,
but now pass.
Performance:
name old time/op new time/op delta
Hash 14.1µs ± 1% 14.1µs ± 1% ~ (p=0.590 n=10+9)
HashPacketFilter 2.53µs ± 2% 2.44µs ± 1% -3.79% (p=0.000 n=9+10)
TailcfgNode 1.45µs ± 1% 1.43µs ± 0% -1.36% (p=0.000 n=9+9)
HashArray 318ns ± 2% 318ns ± 2% ~ (p=0.541 n=10+10)
HashMapAcyclic 32.9µs ± 1% 31.6µs ± 1% -4.16% (p=0.000 n=10+9)
There is a slight performance gain due to the use of unsafe.Pointer
over reflect.Value methods. Also, passing an unsafe.Pointer (1 word)
on the stack is cheaper than passing a reflect.Value (3 words).
Performance gains are diminishing since SHA-256 hashing now dominates the runtime.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
When built with "deephash_debug", print the set of HashXXX methods.
Example usage:
$ go test -run=GetTypeHasher/string_slice -tags=deephash_debug
U64(2)+U64(3)+S("foo")+U64(3)+S("bar")+FIN
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Rather than separate functions to hash each kind,
just rely on the fact that these are direct memory hashable,
thus simplifying the code.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
So next time something like #5340 happens we can identify all affected
nodes and have the control plane send them health warnings.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Every implementation of typeHasherFunc always returns true,
which implies that the slow path is no longer executed.
Delete it.
h.hashValueWithType(v, ti, ...) is deleted as it is equivalent to:
ti.hasher()(h, v)
h.hashValue(v, ...) is deleted as it is equivalent to:
ti := getTypeInfo(v.Type())
ti.hasher()(h, v)
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
also set git committer, which is apparently what this action uses for
signoff rather than git author. Remove branch-suffix, which isn't
proving useful, and add installation_id, which isn't technically
necessary in the tailscale/tailscale repo, but makes this consistent
with the workflows in other repos.
Signed-off-by: Will Norris <will@tailscale.com>
Updates #5435
Based on the discussion in #5435, we can better support transactional data models
by making the underlying storage layer a parameter (which can be specialized for
the request) rather than a long-lived member of Authority.
Now that Authority is just an instantaneous snapshot of state, we can do things
like provide idempotent methods and make it cloneable, too.
Signed-off-by: Tom DNetto <tom@tailscale.com>
It doesn't make a ton of sense for disablement to be communicated as an AUM, because
any failure in the AUM or chain mechanism will mean disablement wont function.
Instead, tracking of the disablement secrets remains inside the state machine, but
actual disablement and communication of the disablement secret is done by the caller.
Signed-off-by: Tom DNetto <tom@tailscale.com>
The CapabilityFileSharingTarget capability added by eb32847d85
is meant to control the ability to share with nodes not owned by the
current user, not to restrict all sharing (the coordination server is
not currently populating the capability at all)
Fixestailscale/corp#6669
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This will update a licenses/tailscale.md file with all of our go
dependencies and their respective licenses. Notices for other clients
will be triggered by similar actions in other repos.
Co-authored-by: Andrew Dunham <andrew@tailscale.com>
Signed-off-by: Will Norris <will@tailscale.com>
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
`src/` is broken up into several subdirectories:
- `lib/` and `types`/ for shared code and type definitions (more code
will be moved here)
- `app/` for the existing Preact-app
- `pkg/` for the new NPM package
A new `build-pkg` esbuild-based command is added to generate the files
for the NPM package. To generate type definitions (something that esbuild
does not do), we set up `dts-bundle-generator`.
Includes additional cleanups to the Wasm type definitions (we switch to
string literals for enums, since exported const enums are hard to use
via packages).
Also allows the control URL to be set a runtime (in addition to the
current build option), so that we don't have to rebuild the package
for dev vs. prod use.
Updates #5415
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Needed to identify the node. A serverside-check the machine key (used
to authenticate the noise session) is that of the specified NodeID
ensures the authenticity of the request.
Signed-off-by: Tom DNetto <tom@tailscale.com>
When sharing nodes, the name of the sharee node is not exposed (instead
it is hardcoded to "device-of-shared-to-user"), which means that we
can't determine the tailnet of that node. Don't immediately fail when
that happens, since it only matters if "Expected-Tailnet" is used.
Signed-off-by: Will Norris <will@tailscale.com>
Add support for maps and interfaces to the fast path.
Add cycle-detection to the pointer handling logic.
This logic is mostly copied from the slow path.
A future commit will delete the slow path once
the fast path never falls back to the slow path.
Performance:
name old time/op new time/op delta
Hash-24 18.5µs ± 1% 14.9µs ± 2% -19.52% (p=0.000 n=10+10)
HashPacketFilter-24 2.54µs ± 1% 2.60µs ± 1% +2.19% (p=0.000 n=10+10)
HashMapAcyclic-24 31.6µs ± 1% 30.5µs ± 1% -3.42% (p=0.000 n=9+8)
TailcfgNode-24 1.44µs ± 2% 1.43µs ± 1% ~ (p=0.171 n=10+10)
HashArray-24 324ns ± 1% 324ns ± 2% ~ (p=0.425 n=9+9)
The additional cycle detection logic doesn't incur much slow down
since it only activates if a type is recursive, which does not apply
for any of the types that we care about.
There is a notable performance boost since we switch from the fath path
to the slow path less often. Most notably, a struct with a field that
could not be handled by the fast path would previously cause
the entire struct to go through the slow path.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
We can't write to src/ when tsconnect is used a dependency in another
repo (see also b763a12331). We therefore
need to switch from writing to src/ to using esbuild plugins to handle
the requests for wasm_exec.js (the Go JS runtime for Wasm) and the
Wasm build of the Go module.
This has the benefit of allowing Go/Wasm changes to be picked up without
restarting the server when in dev mode (Go compilation is fast enough
that we can do this on every request, CSS compilation continues to be
the long pole).
Fixes#5382
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The Start method was removed in 4c27e2fa22, but the comment on NewConn
still mentioned it doesn't do anything until this method is called.
Signed-off-by: Kris Brandow <kris.brandow@gmail.com>
We're going to want to enable audit logging on a per-Tailnet basis. When this
happens, we want control to inform the Tailnet's clients of this capability.
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This works around the 2.3s delay in short name lookups when SNR is
enabled.
C:\Windows\System32\drivers\etc\hosts file. We only add known hosts that
match the search domains, and we populate the list in order of
Search Domains so that our matching algorithm mimics what Windows would
otherwise do itself if SNR was off.
Updates #1659
Signed-off-by: Maisem Ali <maisem@tailscale.com>
There are 5 types that we care about that implement AppendTo:
key.DiscoPublic
key.NodePublic
netip.Prefix
netipx.IPRange
netip.Addr
The key types are thin wrappers around [32]byte and are memory hashable.
The netip.Prefix and netipx.IPRange types are thin wrappers over netip.Addr
and are hashable by default if netip.Addr is hashable.
The netip.Addr type is the only one with a complex structure where
the default behavior of deephash does not hash it correctly due to the presence
of the intern.Value type.
Drop support for AppendTo and instead add specialized hashing for netip.Addr
that would be semantically equivalent to == on the netip.Addr values.
The AppendTo support was already broken prior to this change.
It was fully removed (intentionally or not) in #4870.
It was partially restored in #4858 for the fast path,
but still broken in the slow path.
Just drop support for it altogether.
This does mean we lack any ability for types to self-hash themselves.
In the future we can add support for types that implement:
interface { DeepHash() Sum }
Test and fuzz cases were added for the relevant types that
used to rely on the AppendTo method.
FuzzAddr has been executed on 1 billion samples without issues.
Signed-off-by: Joe Tsai joetsai@digital-static.net
Rename Hash as Block512 to indicate that this is a general-purpose
hash.Hash for any algorithm that operates on 512-bit block sizes.
While we rename the package as hashx in this commit,
a subsequent commit will move the sha256x package to hashx.
This is done separately to avoid confusing git.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Also, rename canMemHash to typeIsMemHashable to be consistent.
There are zero changes to the semantics.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Any type that is memory hashable must not be recursive since
there are definitely no pointers involved to make a cycle.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Put the t.Size() == 0 check first since this is applicable in all cases.
Drop the last struct field conditional since this is covered by the
sumFieldSize check at the end.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Hashing []any is slow since hashing of interfaces is slow.
Hashing of interfaces is slow since we pessimistically assume
that cycles can occur through them and start cycle tracking.
Drop the variadic signature of Update and fix callers to pass in
an anonymous struct so that we are hashing concrete types
near the root of the value tree.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Convert ParseResponse and Response to use netip.AddrPort instead of
net.IP and separate port.
Fixes#5281
Signed-off-by: Kris Brandow <kris.brandow@gmail.com>
Like LLMNR, NetBIOS also adds resolution delays and we don't support it
anyway so just disable it on the interface.
Updates #1659
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Currently we forward unmatched queries to the default resolver on
Windows. This results in duplicate queries being issued to the same
resolver which is just wasted.
Updates #1659
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Formatting a time.Time as RFC3339 is slow.
See https://go.dev/issue/54093
Now that we have efficient hashing of fixed-width integers,
just hash the time.Time as a binary value.
Performance:
Hash-24 19.0µs ± 1% 18.6µs ± 1% -2.03% (p=0.000 n=10+9)
TailcfgNode-24 1.79µs ± 1% 1.40µs ± 1% -21.74% (p=0.000 n=10+9)
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
It flakes more often than it runs. It provides no value and builds
failure blindness, making people get used to submitting on red.
Bye.
Change-Id: If5491c70737b4c9851c103733b1855af2a90a9e9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Switch deephash to use sha256x.Hash.
We add sha256x.HashString to efficiently hash a string.
It uses unsafe under the hood to convert a string to a []byte.
We also modify sha256x.Hash to export the underlying hash.Hash
for testing purposes so that we can intercept all hash.Hash calls.
Performance:
name old time/op new time/op delta
Hash-24 19.8µs ± 1% 19.2µs ± 1% -3.01% (p=0.000 n=10+10)
HashPacketFilter-24 2.61µs ± 0% 2.53µs ± 1% -3.01% (p=0.000 n=8+10)
HashMapAcyclic-24 31.3µs ± 1% 29.8µs ± 0% -4.80% (p=0.000 n=10+9)
TailcfgNode-24 1.83µs ± 1% 1.82µs ± 2% ~ (p=0.305 n=10+10)
HashArray-24 344ns ± 2% 323ns ± 1% -6.02% (p=0.000 n=9+10)
The performance gains is not as dramatic as sha256x over sha256 due to:
1. most of the hashing already occurring through the direct memory hashing logic, and
2. what does not go through direct memory hashing is slowed down by reflect.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
I documented capver 37 in 4ee64681a but forgot to bump the actual
constant. I've done this previously too, so add a test to prevent
it from happening again.
Change-Id: I6f7659db1243d30672121a384beb386d9f9f5b98
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In Go 1.19, the reflect.Value.MapRange method uses "function outlining"
so that the allocation of reflect.MapIter is inlinable by the caller.
If the iterator doesn't escape the caller, it can be stack allocated.
See https://go.dev/cl/400675
Performance:
name old time/op new time/op delta
HashMapAcyclic-24 31.9µs ± 2% 32.1µs ± 1% ~ (p=0.075 n=10+10)
name old alloc/op new alloc/op delta
HashMapAcyclic-24 0.00B 0.00B ~ (all equal)
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
The hash.Hash provided by sha256.New is much more efficient
if we always provide it with data a multiple of the block size.
This avoids double-copying of data into the internal block
of sha256.digest.x. Effectively, we are managing a block ourselves
to ensure we only ever call hash.Hash.Write with full blocks.
Performance:
name old time/op new time/op delta
Hash 33.5µs ± 1% 20.6µs ± 1% -38.40% (p=0.000 n=10+9)
The logic has gone through CPU-hours of fuzzing.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
The logic of deephash is both simpler and easier to reason about
if values are always addressable.
In Go, the composite kinds are slices, arrays, maps, structs,
interfaces, pointers, channels, and functions,
where we define "composite" as a Go value that encapsulates
some other Go value (e.g., a map is a collection of key-value entries).
In the cases of pointers and slices, the sub-values are always addressable.
In the cases of arrays and structs, the sub-values are always addressable
if and only if the parent value is addressable.
In the case of maps and interfaces, the sub-values are never addressable.
To make them addressable, we need to copy them onto the heap.
For the purposes of deephash, we do not care about channels and functions.
For all non-composite kinds (e.g., strings and ints), they are only addressable
if obtained from one of the composite kinds that produce addressable values
(i.e., pointers, slices, addressable arrays, and addressable structs).
A non-addressible, non-composite kind can be made addressable by
allocating it on the heap, obtaining a pointer to it, and dereferencing it.
Thus, if we can ensure that values are addressable at the entry points,
and shallow copy sub-values whenever we encounter an interface or map,
then we can ensure that all values are always addressable and
assume such property throughout all the logic.
Performance:
name old time/op new time/op delta
Hash-24 21.5µs ± 1% 19.7µs ± 1% -8.29% (p=0.000 n=9+9)
HashPacketFilter-24 2.61µs ± 1% 2.62µs ± 0% +0.29% (p=0.037 n=10+9)
HashMapAcyclic-24 30.8µs ± 1% 30.9µs ± 1% ~ (p=0.400 n=9+10)
TailcfgNode-24 1.84µs ± 1% 1.84µs ± 2% ~ (p=0.928 n=10+10)
HashArray-24 324ns ± 2% 332ns ± 2% +2.45% (p=0.000 n=10+10)
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Otherwise we just keep looping over the same thing again and again.
```
dns udp query: upstream nameservers not set
dns udp query: upstream nameservers not set
dns udp query: upstream nameservers not set
```
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This change allows for an auth key to be specified as a url query param
for use in development mode. If an auth key is specified and valid, it
will authorize the client for use immediately.
Updates #5144
Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
Reduces the amount of boilerplate to render the UI and makes it easier to
respond to state changes (e.g. machine getting authorized, netmap changing,
etc.)
Preact adds ~13K to our bundle size (5K after Brotli) thus is a neglibible
size contribution. We mitigate the delay in rendering the UI by having a static
placeholder in the HTML.
Required bumping the esbuild version to pick up evanw/esbuild#2349, which
makes it easier to support Preact's JSX code generation.
Fixes#5137Fixes#5273
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This makes debugging easier, you can pass an AUMHash to a printf and get
a string that is easy to debug.
Also rearrange how directories/files work in the FS store: use the first
two characters of the string representation as the prefix directory, and
use the entire AUMHash string as the file name. This is again to aid
debugging: you can `ls` a directory and line up what prints out easily
with what you get from a printf in debug code.
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
The Do function assists in calling functions that must succeed.
It only interacts well with functions that return (T, err).
Signatures with more return arguments are not supported.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
It should be safe to initialize multiple Server instances
without any resource leaks what-so-ever.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Following the pattern elsewhere, we create a new tka-specific types package for the types
that need to couple between the serialized structure types, and tka.
Signed-off-by: Tom DNetto <tom@tailscale.com>
To improve the local development experience, this change allows a
control url to be passed in with the `--dev-control=` flag.
If the flag is passed in when not specifying dev, an error is returned.
If no flag is passed, the default remains the Tailscale controlled
control server set by `ipn.DefaultControlURL`.
Co-authored-by: Maisem Ali <maisem@tailscale.com>
Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
Initialize logtail and provide an uploader that works in the
browser (we make a no-cors cross-origin request to avoid having to
open up the logcatcher servers to CORS).
Fixes#5147
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
We have very similar code in corp, moving it to util/precompress allows
it to be reused.
Updates #5133
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
4001d0bf25 caused tests in another repo to fail with a crash, calling
a nil func. This might not be the right fix, but fixes the build.
Change-Id: I67263f883c298f307abdd22bc2a30b3393f062e6
Co-authored-by: Maisem Ali <maisem@tailscale.com>
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
- A network-lock key is generated if it doesn't already exist, and stored in the StateStore. The public component is communicated to control during registration.
- If TKA state exists on the filesystem, a tailnet key authority is initialized (but nothing is done with it for now).
Signed-off-by: Tom DNetto <tom@tailscale.com>
JS -> native nodes worked already, tested by exposing a fetch() method
to JS (it's Promise-based to be consistent with the native fetch() API).
Native nodes -> JS almost worked, we just needed to set the LocalBackend
on the userspace netstack.
Fixes#5130
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Avoids waterfalling of requests from the file (its load is triggered
from JavaScript).
Also has other cleanups to index.html, adding a <title> and moving the
<script> to being loaded sooner (but still not delaying page rendering
by using the defer attribute).
Fixes#5141Fixes#5135
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Changes Gzip and Brotli to optimize for speed instead of size. This
signficantly speeds up Brotli, and is useful when iterating locally
or running the build during a CI job (where we just care that it
can successfully build).
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Makes the terminal container DOM node as large as the window (except for
the header) via flexbox. The xterm.js terminal is then sized to fit via
xterm-addon-fit. Once we have a computed rows/columns size, and we can
tell the SSH session of the computed size.
Required introducing an IPNSSHSession type to allow the JS to control
the SSH session once opened. That alse allows us to programatically
close it, which we do when the user closes the window with the session
still active.
I initially wanted to open the terminal in a new window instead (so that
it could be resizable independently of the main window), but xterm.js
does not appear to work well in that mode (possibly because it adds an
IntersectionObserver to pause rendering when the window is not visible,
and it ends up doing that when the parent window is hidden -- see
xtermjs/xterm.js@87dca56dee)
Fixes#5150
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This adds the inverse to CapabilityFileSharingSend so that senders can
identify who they can Taildrop to.
Updates #2101
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Also rename it to expandDelegateURLLocked, previously it was trying
to acquire the mutex while holding the mutex.
Fixes#5235
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The Header field allows the server to specify specific headers to set.
Example use case: server returns 429 with the "Retry-After" header set.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
If the field is the zero value, then avoid serializing the field.
This reduces verbosity in server logs.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Switch to Go 1.19rc2 in prep for the Go 1.19 GA release on Tuesday.
(We won't be using any Go 1.19 features until then.)
Updates #5210
Change-Id: I94fa0ae8f5645fb7579429668f3970c18d1796d8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Just reading the code again in prep for some alloc reductions.
Change-Id: I065226ea794b7ec7144c2b15942d35131c9313a8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
- `--box` when ./cmd/tailscaled is built with this flag, it builds a
"toybox" style binary that includes tailscale and tailscaled.
- `--extra-small` strip the output binary and omit some dependencies
(currently AWS integration).
Signed-off-by: James Tucker <james@tailscale.com>
The go wasm process exiting is a sign of an unhandled panic. Also
add a explicit recover() call in the notify callback, that's where most
logic bugs are likely to happen (and they may not be fatal).
Also fixes the one panic that was encountered (nill pointer dereference
when generating the JS view of the netmap).
Fixes#5132
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The definition of winHTTPProxyInfo was using the wrong type (uint16 vs uint32)
for its first field. I fixed that type.
Furthermore, any UTF16 strings returned in that structure must be explicitly
freed. I added code to do this.
Finally, since this is the second time I've seen type safety errors in this code,
I switched the native API calls over to use wrappers generated by mkwinsyscall.
I know that would not have helped prevent the previous two problems, but every
bit helps IMHO.
Updates https://github.com/tailscale/tailscale/issues/4811
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
Integrates Tailwind CSS as an esbuild plugin that invokes the CLI
to process the input. It takes ~400ms, so it seems like the easiest
option (vs running a separate process for dev mode).
Existing minimal look and feel is replicated with Tailwind classes,
mostly to prove that the entire system works, including unused
class removal.
Also fixes yarn warnings about package.json not having a license
(which were showing up when invoking any scripts).
Fixes#5136Fixes#5129
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Continues to use esbuild for development mode and building. Also
includes a `yarn lint` script that uses tsc to do full type checking.
Fixes#5138
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
It was actually unused earlier, but I had a test program
in my git workdir, keeping go mod tidy from cleaning it.
(more CI needed, perhaps)
Updates #5162
Change-Id: I9047a9aaa6fde7736d6ef516dc3bb652d06fe921
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Technically not the same as the wasm cross-compilation, but it's
closely connected to it.
Also includes some fixes to tool/yasm to make it actually work on
non-ARM platforms.
Fixes#5134
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Somewhere my local configuration or program versions are producing
marker files earlier in the process that lack a line terminator. This
doesn't need to cause an exit via set -e, we can just continue the
process. $extracted matches $REV anyway, so the process works.
Signed-off-by: James Tucker <james@tailscale.com>
Ongoing log writing keeps the spinning disks from hibernating.
Extends earlier implementation for Synology to also handle QNAP.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
As discussed in previous PRs, we can register for notifications when group
policies are updated and act accordingly.
This patch changes nrptRuleDatabase to receive notifications that group policy
has changed and automatically move our NRPT rules between the local and
group policy subkeys as needed.
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
When dbus restarts it can cause the tailscaled to crash because the nil
signal was not handled in resolved.Fixing so the nil signal leads to a
connection reset and tailscaled stays connected to systemd when dbus restarted.
Fixes#4645
Co-authored-by: James Tucker <james@tailscale.com>
Signed-off-by: nyghtowl <warrick@tailscale.com>
Co-authored-by: James Tucker <james@tailscale.com>
This allows gitops-pusher to detect external ACL changes. I'm not
sure what to call this problem, so I've been calling it the "three
version problem" in my notes. The basic problem is that at any given
time we only have two versions of the ACL file at any given point:
the version in CONTROL and the one in the git repo. In order to
check if there has been tampering of the ACL files in the admin
panel, we need to have a _third_ version to compare against.
In this case I am not storing the old ACL entirely (though that could
be a reasonable thing to add in the future), but only its sha256sum.
This allows us to detect if the shasum in control matches the shasum
we expect, and if that expectation fails, then we can react
accordingly.
This will require additional configuration in CI, but I'm sure that
can be done.
Signed-off-by: Xe <xe@tailscale.com>
Adds a tool/yarn helper script that uses specific versions of yarn and
node, downloading them if necessary.
Modeled after tool/go (and the yarn and node Redo scripts from the
corp repo).
Also allows the path to yarn to be overidden (in case the user does not
want to use this script) and always pipes yarn output (to make debugging
and viewing of process easier).
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This has the benefit of propagating SIGINT to tailscaled, which in turn
can react to the event and logout in case of an ephemeral node.
Also fix missing run.sh in Dockerfile.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This adds a lighter mechanism for endpoint updates from control.
Change-Id: If169c26becb76d683e9877dc48cfb35f90cc5f24
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
When using tsconnect as a module in another repo, we cannot write to
the ./dist directory (modules directories are read-only by default -
there is a -modcacherw flag for `go get` but we can't count on it).
We add a -distdir flag that is honored by both the build and serve
commands for where to place output in.
Somewhat tedious because esbuild outputs paths relative to the working
directory, so we need to do some extra munging to make them relative
to the output directory.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
We now have the actual module that we need to build, so switch to
building it directly instead of its (expected) dependencies.
Also fix a copy/paste error in a jsdeps comment.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
The control plane server doesn't send these to modern clients so we
don't need them in the tree. The server has its own serialization code
to generate legacy MapResponses when needed.
Change-Id: Idd1e5d96ddf9d4306f2da550d20b77f0c252817a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Runs a Tailscale client in the browser (via a WebAssembly build of the
wasm package) and allows SSH access to machines. The wasm package exports
a newIPN function, which returns a simple JS object with methods like
start(), login(), logout() and ssh(). The golang.org/x/crypto/ssh
package is used for the SSH client.
Terminal emulation and QR code renedring is done via NPM packages (xterm
and qrcode respectively), thus we also need a JS toolchain that can
install and bundle them. Yarn is used for installation, and esbuild
handles loading them and bundling for production serving.
Updates #3157
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This PR implements the synchronization mechanics for TKA: generating a SyncOffer, processing a SyncOffer to find an intersection,
and computing the set of AUMs that should be transmitted to effect convergence.
This is the final PR implementing core mechanics for TKA.
Signed-off-by: Tom DNetto <tom@tailscale.com>
This lets us distinguish "no IPv6 because the device's ISP doesn't
offer IPv6" from "IPv6 is unavailable/disabled in the OS".
Signed-off-by: David Anderson <danderson@tailscale.com>
QTS 5.0 doesn't always pass a qtoken, in some circumstances
it sends a NAS_SID cookie for us to verify instead.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
We were not handling errors occurred while copying data between the subprocess and the connection.
This makes it so that we pass the appropriate signals when to the process and the connection.
This also fixes mosh.
Updates #4919
Co-authored-by: James Tucker <raggi@tailscale.com>
Co-authored-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Signed-off-by: Maisem Ali <maisem@tailscale.com>
FS implements Chonk, and given the expected load characteristics (frequent use
of AUM() + ChildAUMs(), and infrequent use of Heads() + CommitVerifiedAUMs()), the
implementation avoids scanning the filesystem to service AUM() and ChildAUMs().
Signed-off-by: Tom DNetto <tom@tailscale.com>
3f686688a6 regressed the Windows beFirewallKillswitch code,
preventing the /firewall subprocess from running.
Fixestailscale/corp#6063
Change-Id: Ibd105759e5fecfeffc54f587f8ddcd0f1cbc4dca
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We make assertions about stringification of 0.5. IEEE floating point and
all reasonable proprietary floating point can exactly represent 0.5.
We don't make assertions about other floating point values, too brittle
in tests.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
Chonks are responsible for efficient storage of AUMs and other TKA state.
For testing/prototyping I've implemented an in-memory version, but once we
start to use this from tailscaled we'll need a file-based version.
Signed-off-by: Tom DNetto <tom@tailscale.com>
Clients may have platform-specific metrics they would like uploaded
(e.g. extracted from MetricKit on iOS). Add a new local API endpoint
that allows metrics to be updated by a simple name/value JSON-encoded
struct.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Apparently the API for running ACL tests returns a 200 if the ACL tests
fail. This is weird, but we can handle it.
Signed-off-by: Xe <xe@tailscale.com>
This is the first in a series of PRs implementing the internals for the
Tailnet Key Authority. This PR implements the AUM and Key types, which
are used by pretty much everything else. Future PRs:
- The State type & related machinery
- The Tailchonk (storage) type & implementation
- The Authority type and sync implementation
Signed-off-by: Tom DNetto <tom@tailscale.com>
If ConfigFromFile cannot find the configuration file,
we must not initialize it with NewConfig.
Instead, we need it to fail validation so that it eventually writes
a newly constructed configuration file.
Otherwise, new tailscale instances will never be able store a persistent
log config and start with a new config file upon every bootup.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
And rewrite cloud detection to try to do only zero or one metadata
discovery request for all clouds, only doing a first (or second) as
confidence increases. Work remains for Windows, but a start.
And add Cloud to tailcfg.Hostinfo, which helped with testing using
"tailcfg debug hostinfo".
Updates #4983 (Linux only)
Updates #4984
Change-Id: Ib03337089122ce0cb38c34f724ba4b4812bc614e
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Together with 06aa141632 this minimizes
the number of NEPacketTunnelNetworkSettings updates that we have to do,
and thus avoids Chrome interrupting outstanding requests due to
(perceived) network changes.
Updates #3102
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Currently if you use '-c' and ping a host that times out, ping will
continue running indefinitely. This change exits the loop with "no
reply" when we time out, hit the value specified by '-c' and do not
have anyPong. If we have anyPong it returns nil.
Signed-off-by: Aaron Bieber <aaron@bolddaemon.com>
And remove the GCP special-casing from ipn/ipnlocal; do it only in the
forwarder for *.internal.
Fixes#4980Fixes#4981
Change-Id: I5c481e96d91f3d51d274a80fbd37c38f16dfa5cb
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This does three things:
* If you're on GCP, it adds a *.internal DNS split route to the
metadata server, so we never break GCP DNS names. This lets people
have some Tailscale nodes on GCP and some not (e.g. laptops at home)
without having to add a Tailnet-wide *.internal DNS route.
If you already have such a route, though, it won't overwrite it.
* If the 100.100.100.100 DNS forwarder has nowhere to forward to,
it forwards it to the GCP metadata IP, which forwards to 8.8.8.8.
This means there are never errNoUpstreams ("upstream nameservers not set")
errors on GCP due to e.g. mangled /etc/resolv.conf (GCP default VMs
don't have systemd-resolved, so it's likely a DNS supremacy fight)
* makes the DNS fallback mechanism use the GCP metadata IP as a
fallback before our hosted HTTP-based fallbacks
I created a default GCP VM from their web wizard. It has no
systemd-resolved.
I then made its /etc/resolv.conf be empty and deleted its GCP
hostnames in /etc/hosts.
I then logged in to a tailnet with no global DNS settings.
With this, tailscaled writes /etc/resolv.conf (direct mode, as no
systemd-resolved) and sets it to 100.100.100.100, which then has
regular DNS via the metadata IP and *.internal DNS via the metadata IP
as well. If the tailnet configures explicit DNS servers, those are used
instead, except for *.internal.
This also adds a new util/cloudenv package based on version/distro
where the cloud type is only detected once. We'll likely expand it in
the future for other clouds, doing variants of this change for other
popular cloud environments.
Fixes#4911
RELNOTES=Google Cloud DNS improvements
Change-Id: I19f3c2075983669b2b2c0f29a548da8de373c7cf
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The goal here is to
1. make it so that the number doesn't diverge between the various places
we had it defined
2. not define the number in corp, only in oss
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The Dockerfile directions said:
But that failed with:
Step 14/15 : FROM ghcr.io/tailscale/alpine-base:3.14
Head "https://ghcr.io/v2/tailscale/alpine-base/manifests/3.14": denied: denied
So I guess the Dockerfile.base part was undocumented. But it only had
one line anyway, so move it here to avoid the intermediate layer's
published permissions problem entirely.
Also optimize the cachability a bit while here.
Change-Id: I846ad59fe7e88e6126925689fae78bfb80c279f0
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The iOS and macOS networking extension API only exposes a single setter
for the entire routing and DNS configuration, and does not appear to
do any kind of diffing or deltas when applying changes. This results
in spurious "network changed" errors in Chrome, even when the
`OneCGNATRoute` flag from df9ce972c7 is
used (because we're setting the same configuration repeatedly).
Since we already keep track of the current routing and DNS configuration
in CallbackRouter, use that to detect if they're actually changing, and
only invoke the platform setter if it's actually necessary.
Updates #3102
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
There appear to be devices out there which send only their
first descriptor in response to a discovery packet for
`ssdp:all`, for example the Sagemcom FAST3890V3 only sends
urn:schemas-wifialliance-org:device:WFADevice:1
Send both ssdp:all and a discovery frame for
InternetGatewayDevice specifically.
Updates https://github.com/tailscale/tailscale/issues/3557
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
... so callers can provide the AuthKey via mechanisms other than
environment variables which means multiple Servers can't be started
concurrently in the same process without coordination.
Change-Id: I7736ef4f59b7cc29637939e140e990613ce58e0d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Whenever the SSH policy changes we revaluate all open connections to
make sure they still have access. This check was using the wrong
timestamp and would match against expired policies, however this really
isn't a problem today as we don't have policy that would be impacted by
this check. Fixing it for future use.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
(breaking up parts of another change)
This adds a PacketFilter hashing benchmark with an input that both
contains every possible field, but also is somewhat representative in
the shape of what real packet filters contain.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
When there are group policy entries for the NRPT that do not belong to Tailscale,
we recognize that we need to add ourselves to group policy and use that registry
key instead of the local one. We also refresh the group policy settings as
necessary to ensure that our changes take effect immediately.
Fixes https://github.com/tailscale/tailscale/issues/4607
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
Link-local addresses on the Tailscale interface are not routable.
Ideally they would be removed, however, a concern exists that the
operating system will attempt to re-add them which would lead to
thrashing.
Setting SkipAsSource attempts to avoid production of packets using the
address as a source in any default behaviors.
Before, in powershell: `ping (hostname)` would ping the link-local
address of the Tailscale interface, and fail.
After: `ping (hostname)` now pings the link-local address on the next
highest priority metric local interface.
Fixes#4647
Signed-off-by: James Tucker <james@tailscale.com>
This is for an upcoming blogpost on how to manage Tailscale ACLs using a
GitOps flow. This tool is intended to be used in CI and will allow users
to have a git repository be the ultimate source of truth for their ACL
file. This enables ACL changes to be proposed, approved and discussed
before they are applied.
Signed-off-by: Xe <xe@tailscale.com>
Client.SetExpirySooner isn't part of the state machine. Remove it from
the Client interface.
And fix a use of LocalBackend.cc without acquiring the lock that
guards that field.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Step 1 of many, cleaning up the direct/auto client & restarting map
requests that leads to all the unnecessary map requests.
Updates tailscale/corp#5761
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Regression from 09afb8e35b, in which the
same reflect.Value scratch value was being used as the map iterator
copy destination.
Also: make nil and empty maps hash differently, add test.
Fixes#4871
Co-authored-by: Josh Bleecher Snyder <josharian@gmail.com>
Change-Id: I67f42524bc81f694c1b7259d6682200125ea4a66
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Otherwise we crash at startup with Go 1.19beta1.
Updates #4872
Change-Id: I371df4146735f7e066efd2edd48c1a305906c13d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Use the "tailscaled" prefix instead of "tsnet" for state file names:
1. It is consistent with the pre-existing {{Dir}}/tailscaled.state file.
2. It makes the file layout of `tsnet` and `tailscaled` identical,
so that they are compatible with each other.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
Start up a backend service, put a SOCKS5 server in front
of it, and verify that we can get data from the backend via
SOCKS5.
Signed-off-by: Denton Gentry <dgentry@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>
It is not idiomatic for Go code to panic for situations that
can be normal. For example, if a server receives PrivateID
from a client, it is normal for the server to call
PrivateID.PublicID to validate that the PublicID matches.
However, doing so would panic prior to this change.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit adds a helper to check if Tailscale SSH is enabled. We're
currently checking the SSH_HostKeys field in a few places, but later
plan to add an explicit bool. This helper makes the check and any future
changes easier.
Signed-off-by: Ross Zurowski <ross@rosszurowski.com>
refactor logpolicy config loading to make it easier to reuse from
outside the package. Within tsnet, setup a basic logtail config.
Signed-off-by: Will Norris <will@tailscale.com>
Fixes the current http://pkgs.tailscale.com/ redirect to https:///
as that server doesn't configure the Port80Handler.FQDN field.
Change-Id: Iff56e6127a46c306ca97738d91b217bcab32a582
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
On DSM7 as a non-root user it'll run into problems.
And we haven't tested on DSM6, even though it might work, but I doubt
it.
Updates #3802
Updates tailscale/corp#5468
Change-Id: I75729042e4788f03f9eb82057482a44b319f04f3
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This reverts commit 03e3e6abcd
in favor of #4785.
Change-Id: Ied65914106917c4cb8d15d6ad5e093a6299d1d48
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We weren't wiring up netstack.Impl to the LocalBackend in some cases
on Windows. This fixes Windows 7 when run as a service.
Updates #4750 (fixes after pull in to corp repo)
Change-Id: I9ce51b797710f2bedfa90545776b7628c7528e99
Signed-off-by: Brad Fitzpatrick <bradfitz@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>
Currently we only support "via-<site-id>.<IPv4>", however that does not
work with Google Chrome which parses `http://via-1.10.0.0.1` as a search
string and not as a URL. This commit introduces "<IPv4>.via-<site-id>"
(`http://10.0.0.1.via-1`) which is parsed correctly by Chrome.
Updates #3616
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Per post-submit code review feedback of 1336fb740b from @maisem.
Change-Id: Ic5c16306cbdee1029518448642304981f77ea1fd
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This makes it so that the user is notified that the action
they are about to take may result in them getting disconnected from
the machine. It then waits for 5s for the user to maybe Ctrl+C out of
it.
It also introduces a `--accept-risk=lose-ssh` flag for automation, which
allows the caller to pre-acknowledge the risk.
The two actions that cause this are:
- updating `--ssh` from `true` to `false`
- running `tailscale down`
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Use unix.ByteSliceToString in osVersionFreebsd and osVersionLinux to
convert the Utsname.Release []byte field to string.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
As already done in osVersionFreebsd. This will allow to use the Utsname
fields as []byte for easier conversion to string.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Also lazify SSHServer initialization to allow restarting the server on a
subsequent `tailscale up`
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Currently, killing a SCP copy with a Ctrl+C leaves the session hanging
even though the stdout copy goroutine fails with an io.EOF. Taking a
step back, when we are unable to send any more data back to the client
we should just terminate the session as the client will stop getting any
response from the server anyways.
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Ideally we would re-establish these sessions when tailscaled comes back
up, however we do not do that yet so this is better than leaking the
sessions.
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Saves some allocs. Not hot, but because we can now.
And a const instead of a var.
Change-Id: Ieb2b64534ed38051c36b2c0aa2e82739d9d0e015
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Fixes#4647
It seems that Windows creates a link-local address for the TUN driver, seemingly
based on the (fixed) adapter GUID. This results in a fixed MAC address, which
for some reason doesn't handle loopback correctly. Given the derived link-local
address is preferred for lookups (thanks LLMNR), traffic which addresses the
current node by hostname uses this broken address and never works.
To address this, we remove the broken link-local address from the wintun adapter.
Signed-off-by: Tom DNetto <tom@tailscale.com>
AFAICT this isn't documented on MSDN, but based on the issue referenced below,
NRPT rules are not working when a rule specifies > 50 domains.
This patch modifies our NRPT rule generator to split the list of domains
into chunks as necessary, and write a separate rule for each chunk.
For compatibility reasons, we continue to use the hard-coded rule ID, but
as additional rules are required, we generate new GUIDs. Those GUIDs are
stored under the Tailscale registry path so that we know which rules are ours.
I made some changes to winutils to add additional helper functions in support
of both the code and its test: I added additional registry accessors, and also
moved some token accessors from paths to util/winutil.
Fixes https://github.com/tailscale/coral/issues/63
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
c2b907c965 moved UBUNTU_VERSION out
of the ubuntu case and into linuxmint, but linuxmint wasn't the
only Ubuntu-based system which needed it. Restore UBUNTU_VERSION
handling in the ubuntu case.
Break elementaryOS out into its own handling so we can get the
version number handling correct for keyring support.
Tested on an elementaryOS 6.1 VM.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
I wrote this code way back at the beginning of my tenure at Tailscale when we
had concerns about needing to restore deleted machine keys from backups.
We never ended up using this functionality, and the code is now getting in the
way, so we might as well remove it.
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
For now just checks that we can build cmd/tailscale/cli, will be
broadened once we can actually build more things.
Updates #3157
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Adds a stub for syscall.Exec when GOOS=js. We also had a separate branch
for Windows, might as well use the same mechanism there too.
For #3157
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Broken by 3dedcd1640 but we don't have CI coverage yet.
Updates #3157
Change-Id: Ie8e95ebd36264887fdeed16fc9f25a857d48124b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Allows instances that are running with the same machine ID (due to
cloning) to be distinguished.
Also adds sequence numbers to detect duplicates.
For tailscale/corp#5244
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Fixes https://github.com/tailscale/corp/issues/5198
The upstream forwarder will block indefinitely on `udpconn.ReadFrom` if no
reply is recieved, due to the lack of deadline on the connection object.
There still isn't a deadline on the connection object, but the automatic closing
of the context on deadline expiry will close the connection via `closeOnCtxDone`,
unblocking the read and resulting in a normal teardown.
Signed-off-by: Tom DNetto <tom@tailscale.com>
This fixes the "tailscale up --authkey=... --ssh" path (or any "up"
path that used Start instead of EditPrefs) which wasn't setting the
bit.
Updates #3802
Change-Id: Ifca532ec58296fedcedb5582312dfee884367ed7
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Profiling identified this as a fairly hot path for growing a slice.
Given this is only used in control & when a new packet filter is received, this shouldnt be hot in the client.
The prefix is a signal to tsweb to treat this as a gauge metric when
generating the Prometheus version.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
We were marking them as gauges, but they are only ever incremented,
thus counter is more appropriate.
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Enables the behavior described in the statepath flag, where if only
statedir is passed, then state is statedir/tailscaled.state.
Signed-off-by: James Tucker <james@tailscale.com>
This has the added benefit of displaying the MOTD and reducing our
dependency on the DBus interface.
Fixes#4627
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
The hujson package transition to just being a pure AST
parser and formatter for HuJSON and not an unmarshaler.
Thus, parse HuJSON as such, convert it to JSON,
and then use the standard JSON unmarshaler.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
* net/dns, wgengine: implement DNS over TCP
Signed-off-by: Tom DNetto <tom@tailscale.com>
* wgengine/netstack: intercept only relevant port/protocols to quad-100
Signed-off-by: Tom DNetto <tom@tailscale.com>
It's unused and we've decided it's not what we want.
Change-Id: I425a0104e8869630b498a0adfd0f455876d6f92b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
There has been a lot of talk about Bees at Tailscale recently, and
naturally, with it being Tailscale, we thought to ourselves:
Do Bees have a tail and/or scales?
Tailscale has a long track record of scientific rigor around the
validity of the inclusions on the tails and scales list, and this time
will be no exception.
Our research has found that Bees, in particular the Honey Bee, produces
wax scales on their abdomens and thus should be included. As for tails;
'Stabby-tails' - Tailscale Employee, 2022
No further justification needed, it will be included.
This change includes Bee in both tails.txt and scales.txt.
Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
Currently, when SetNetInfo is called it sets the value on
hostinfo.NetInfo. However, when SetHostInfo is called it overwrites the
hostinfo field which may mean it also clears out the NetInfo it had just
received.
This commit stores NetInfo separately and combines it into Hostinfo as
needed so that control is always notified of the latest values.
Also, remove unused copies of Hostinfo from ipn.Status and
controlclient.Auto.
Updates #tailscale/corp#4824 (maybe fixes)
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This were intended to be pushed to #4408, but in my excitement I
forgot to git push :/ better late than never.
Signed-off-by: Tom DNetto <tom@tailscale.com>
This change wires netstack with a hook for traffic coming from the host
into the tun, allowing interception and handling of traffic to quad-100.
With this hook wired, magicDNS queries over UDP are now handled within
netstack. The existing logic in wgengine to handle magicDNS remains for now,
but its hook operates after the netstack hook so the netstack implementation
takes precedence. This is done in case we need to support platforms with
netstack longer than expected.
Signed-off-by: Tom DNetto <tom@tailscale.com>
A subsequent commit implements handling of magicDNS traffic via netstack.
Implementing this requires a hook for traffic originating from the host and
hitting the tun, so we make another hook to support this.
Signed-off-by: Tom DNetto <tom@tailscale.com>
Moves magicDNS-specific handling out of Resolver & into dns.Manager. This
greatly simplifies the Resolver to solely issuing queries and returning
responses, without channels.
Enforcement of max number of in-flight magicDNS queries, assembly of
synthetic UDP datagrams, and integration with wgengine for
recieving/responding to magicDNS traffic is now entirely in Manager.
This path is being kept around, but ultimately aims to be deleted and
replaced with a netstack-based path.
This commit is part of a series to implement magicDNS using netstack.
Signed-off-by: Tom DNetto <tom@tailscale.com>
Currently the ssh session isn't terminated cleanly, instead the packets
are just are no longer routed to the in-proc SSH server. This makes it
so that clients get a disconnection when the `RunSSH` pref changes to
`false`.
Updates #3802
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Once a stop request is received and the service updates its status to `svc.StopPending`,
it should continue running *until the shutdown sequence is complete*, and then
return out of `(*ipnService).Execute`, which automatically sends a `svc.Stopped`
notification to Windows.
To make this happen, I changed the loop so that it runs until `doneCh` is
closed, and then returns. I also removed a spurious `svc.StopPending` notification
that the Windows Service Control Manager might be interpreting as a request for
more time to shut down.
Finally, I added some optional logging that sends a record of service notifications
to the Windows event log, allowing us to more easily correlate with any Service
Control Manager errors that are sent to the same log.
Change-Id: I5b596122e5e89c4c655fe747a612a52cb4e8f1e0
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
The Mac client was using it, but it had the effect of the `RouteAll`
("Use Tailscale subnets") pref always being enabled at startup,
regardless of the persisted value.
enforceDefaults was added to handle cases from ~2 years ago where
we ended up with persisted `"RouteAll": false` values in the keychain,
but that should no longer be a concern. New users will get the default
of it being enabled via `NewPrefs`.
There will be a corresponding Mac client change to stop passing in
enforceDefaults.
For #3962
Signed-off-by: Mihai Parparita <mihai@tailscale.com>
Remove all global variables, and clean up tsnet and cmd/tailscale's usage.
This is in prep for using this package for the web API too (it has the
best package name).
RELNOTE=tailscale.com/client/tailscale package refactored w/ LocalClient type
Change-Id: Iba9f162fff0c520a09d1d4bd8862f5c5acc9d7cd
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
goimports is a superset of gofmt that also groups imports.
(the goimports tool also adds/removes imports as needed, but that
part is disabled here)
Change-Id: Iacf0408dfd9497f4ed3da4fa50e165359ce38498
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Well, goimports actually (which adds the normal import grouping order we do)
Change-Id: I0ce1b1c03185f3741aad67c14a7ec91a838de389
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This reverts commit dd6472d4e8.
Reason: it appears I was just really really wrong or confused.
We added it to the old internal API used by the website instead,
not to the "v2" API.
Updates #2120
Updates #4571
Change-Id: I744a72b9193aafa7b526fd760add52148a377e83
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This updates the fix from #4562 to pick the proxy based on the request
scheme.
Updates #4395, #2605, #4562
Signed-off-by: James Tucker <james@tailscale.com>
Currently we try to use `https://` when we see `https_host`, however
that doesn't work and results in errors like `Received error: fetch
control key: Get "https://controlplane.tailscale.com/key?v=32":
proxyconnect tcp: tls: first record does not look like a TLS handshake`
This indiciates that we are trying to do a HTTPS request to a HTTP
server. Googling suggests that the standard is to use `http` regardless
of `https` or `http` proxy
Updates #4395, #2605
Signed-off-by: Maisem Ali <maisem@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>
Setting keepalive ensures that idle connections will eventually be
closed. In userspace mode, any application configured TCP keepalive is
effectively swallowed by the host kernel, and is not easy to detect.
Failure to close connections when a peer tailscaled goes offline or
restarts may result in an otherwise indefinite connection for any
protocol endpoint that does not initiate new traffic.
This patch does not take any new opinion on a sensible default for the
keepalive timers, though as noted in the TODO, doing so likely deserves
further consideration.
Update #4522
Signed-off-by: James Tucker <james@tailscale.com>
In debugging #4541, I noticed this log print was always empty.
The value printed was always zero at this point.
Updates #4541
Change-Id: I0eef60c32717c293c1c853879446be65d9b2cef6
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
No CLI support yet. Just the curl'able version if you know the peerapi
port. (like via a TSMP ping)
Updates #306
Change-Id: I0662ba6530f7ab58d0ddb24e3664167fcd1c4bcf
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Still a little wonky, though. See the tcsetattr error and inability to
hit Ctrl-D, for instance:
bradfitz@laptop ~ % tailscale.app ssh foo@bar
tcsetattr: Operation not permitted
# Authentication checked with Tailscale SSH.
# Time since last authentication: 1h13m22s
foo@bar:~$ ^D
^D
^D
Updates #4518
Updates #4529
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For debugging what's visible inside the macOS sandbox.
But could also be useful for giving users portable commands
during debugging without worrying about which OS they're on.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Tested three macOS Tailscale daemons:
- App Store (Network Extension)
- Standalone (macsys)
- tailscaled
And two types of local IPC each:
- IPN
- HTTP
And two CLI modes:
- sandboxed (running the GUI binary as the CLI; normal way)
- open source CLI hitting GUI (with #4525)
Bonus: simplifies the code.
Fixestailscale/corp#4559
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I've done this a handful of times in the past and again today.
Time to make it a supported thing for the future.
Used while debugging tailscale/corp#4559 (macsys CLI issues)
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Updates #2067
This should help us determine if more robust control of edns parameters
+ implementing answer truncation is warranted, given its likely complexity.
Signed-off-by: Tom DNetto <tom@tailscale.com>
One current theory (among other things) on battery consumption is that
magicsock is resorting to using the IPv6 over LTE even on WiFi.
One thing that could explain this is that we do not get link change updates
for the LTE modem as we ignore them in this list.
This commit makes us not ignore changes to `pdp_ip` as a test.
Updates #3363
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This populates DNS suffixes ("ts.net", etc) in /etc/resolver/* files
to point to 100.100.100.100 so MagicDNS works.
It also sets search domains.
Updates #4276
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
There was a typo in the check it was doing `!ok` instead of `ok`, this
restructures it a bit to read better.
Fixes#4506
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This reverts commit 8d6793fd70.
Reason: breaks Android build (cgo/pthreads addition)
We can try again next cycle.
Change-Id: I5e7e1730a8bf399a8acfce546a6d22e11fb835d5
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Attempt to load the xt_mark kernel module when it is not present. If the
load fails, log error information.
It may be tempting to promote this failure to an error once it has been
in use for some time, so as to avoid reaching an error with the iptables
invocation, however, there are conditions under which the two stages may
disagree - this change adds more useful breadcrumbs.
Example new output from tailscaled running under my WSL2:
```
router: ensure module xt_mark: "/usr/sbin/modprobe xt_mark" failed: exit status 1; modprobe: FATAL: Module xt_mark not found in directory /lib/modules/5.10.43.3-microsoft-standard-WSL2
```
Background:
There are two places to lookup modules, one is `/proc/modules` "old",
the other is `/sys/module/` "new".
There was query_modules(2) in linux <2.6, alas, it is gone.
In a docker container in the default configuration, you would get
/proc/modules and /sys/module/ both populated. lsmod may work file,
modprobe will fail with EPERM at `finit_module()` for an unpriviliged
container.
In a priviliged container the load may *succeed*, if some conditions are
met. This condition should be avoided, but the code landing in this
change does not attempt to avoid this scenario as it is both difficult
to detect, and has a very uncertain impact.
In an nspawn container `/proc/modules` is populated, but `/sys/module`
does not exist. Modern `lsmod` versions will fail to gather most module
information, without sysfs being populated with module information.
In WSL2 modules are likely missing, as the in-use kernel typically is
not provided by the distribution filesystem, and WSL does not mount in a
module filesystem of its own. Notably the WSL2 kernel supports iptables
marks without listing the xt_mark module in /sys/module, and
/proc/modules is empty.
On a recent kernel, we can ask the capabilities system about SYS_MODULE,
that will help to disambiguate between the non-privileged container case
and just being root. On older kernels these calls may fail.
Update #4329
Signed-off-by: James Tucker <james@tailscale.com>
For tests.
Now that we can always listen (whereas we used to fail prior to
a2c330c496), some goroutine leak
checks were failing in tests in another repo after that change.
Change-Id: Id95a4b71167eca61962a48616d79741b9991e0bc
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The primary distribution for LinuxMint is based on Ubuntu,
but there is an alternate Debian-based distribution called
LMDE. Both variations identify themselves as "linuxmint"
We added UBUNTU_VERSION to the Ubuntu handling for linuxmint,
the only distribution so far found to do this. Instead, split
linuxmint out into its own case and use either UBUNTU_VERSION
or DEBIAN_VERSION, whichever is present.
Tested on an LMDE 5 (elsie) VM.
Updates https://github.com/tailscale/tailscale/issues/2915
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
$ tailscale debug via 0xb 10.2.0.0/16
fd7a:115c:a1e0:b1a:0:b:a02:0/112
$ tailscale debug via fd7a:115c:a1e0:b1a:0:b:a02:0/112
site 11 (0xb), 10.2.0.0/16
Previously: 3ae701f0eb
This adds a little debug tool to do CIDR math to make converting between
those ranges easier for now.
Updates #3616
Change-Id: I98302e95d17765bfaced3ecbb71cbd43e84bff46
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The previous commit (1b89662eff) this for Android, but we can also use
this on any platform if we we would otherwise fail.
Change-Id: I4cd78b40e9e77fca5cc8e717dd48ac173101bed4
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
It unfortuantely gets truncated because it's too long, split it into 3
different log lines to circumvent truncation.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Currently we ignore these interfaces in the darwin osMon but then would consider it
interesting when checking if anything had changed.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
We intercept the peerapi port in netstack anyway, so there's no reason
the linux kernel on Android needs to know about it. It's only getting
in the way and causing problems for reasons we don't fully understand.
But we don't even need to understand it because it's not relevant
anymore.
Instead, provide a dummy net.Listener that just sits and blocks to
pacify the rest of the code that assumes it can be stuck in a
Listener.Accept call and call Listener.Close and Listener.Addr.
We'll likely do this for all platforms in the future, if/when we also
link in netstack on iOS.
Updates #4449
Updates #4293
Updates #3986
Change-Id: Ic2d3fe2f3cee60fc527356a3368830f17aeb75ae
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit changes proxy-to-grafana to report errors while polling for
tailscaled status instead of terminating at the first sign of an error.
This allows tailscale some time to come up before the proxy decides to
give up.
Signed-off-by: Blake Mizerany <blake.mizerany@gmail.com>
In cases where tailscale is operating behind a MITM proxy, we need to consider
that a lot more of the internals of our HTTP requests are visible and may be
used as part of authorization checks. As such, we need to 'behave' as closely
as possible to ideal.
- Some proxies do authorization or consistency checks based the on Host header
or HTTP URI, instead of just the IP/hostname/SNI. As such, we need to
construct a `*http.Request` with a valid URI everytime HTTP is going to be
used on the wire, even if its over TLS.
Aside from the singular instance in net/netcheck, I couldn't find anywhere
else a http.Request was constructed incorrectly.
- Some proxies may deny requests, typically by returning a 403 status code. We
should not consider these requests as a valid latency check, so netcheck
semantics have been updated to consider >299 status codes as a failed probe.
Signed-off-by: Tom DNetto <tom@tailscale.com>
Two changes in one:
* make DoH upgrades an explicitly scheduled send earlier, when we come
up with the resolvers-and-delay send plan. Previously we were
getting e.g. four Google DNS IPs and then spreading them out in
time (for back when we only did UDP) but then later we added DoH
upgrading at the UDP packet layer, which resulted in sometimes
multiple DoH queries to the same provider running (each doing happy
eyeballs dialing to 4x IPs themselves) for each of the 4 source IPs.
Instead, take those 4 Google/Cloudflare IPs and schedule 5 things:
first the DoH query (which can use all 4 IPs), and then each of the
4 IPs as UDP later.
* clean up the dnstype.Resolver.Addr confusion; half the code was
using it as an IP string (as documented) as half was using it as
an IP:port (from some prior type we used), primarily for tests.
Instead, document it was being primarily an IP string but also
accepting an IP:port for tests, then add an accessor method on it
to get the IPPort and use that consistently everywhere.
Change-Id: Ifdd72b9e45433a5b9c029194d50db2b9f9217b53
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If all N queries failed, we waited until context timeout (in 5
seconds) to return.
This makes (*forwarder).forward fail fast when the network's
unavailable.
Change-Id: Ibbb3efea7ed34acd3f3b29b5fee00ba8c7492569
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Currently if the policy changes and the session is logged in with local
user "u1" and the new policy says they can only login with "u2" now, the
user doesn't get kicked out because they had requested
`rando@<ssh-host>` and the defaulting had made that go to `u1`.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
From the machines tab its hard to differenciate desktop Linux installs from
server Linux installs. Transmitting this information should make this
determination a lot easier.
Due to the reality that tailscaled is likely a system process, the standard
checks based on XDG_SESSION_TYPE or DISPLAY environment variables are not
possible (those variables won't be set). Instead, we look for listening
unix sockets that are typical of desktop installs.
Signed-off-by: Tom DNetto <tom@tailscale.com>
For people running self-hosted control planes who want a global
opt-out knob instead of running their own logcatcher.
Change-Id: I7f996c09f45850ff77b58bfd5a535e197971725a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Simplify the ability to reason about the DoH dialing code by reusing the
dnscache's dialer we already have.
Also, reduce the scope of the "ip" variable we don't want to close over.
This necessarily adds a new field to dnscache.Resolver:
SingleHostStaticResult, for when the caller already knows the IPs to be
returned.
Change-Id: I9f2aef7926f649137a5a3e63eebad6a3fffa48c0
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The default is still users can debug their own nodes. But like
cd916b728b did, this adds support for admins to grant additional
capabilities with the new tailcfg.CapabilityDebugPeer cap.
Updates #4217
Change-Id: Ifce3d9a1f8e8845797970a4f97b393194663d35f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Fail on unsupported platforms (must be Linux or macOS tailscaled with
WIP env) or when disabled by admin (with TS_DISABLE_SSH_SERVER=1)
Updates #3802
Change-Id: I5ba191ed0d8ba4ddabe9b8fc1c6a0ead8754b286
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In `(*Mon).Start` we don't run a timer to update `(*Mon).lastWall` on iOS and
Android as their sleep patterns are bespoke. However, in the debounce
goroutine we would notice that the the wall clock hadn't been updated
since the last event would assume that a time jump had occurred. This would
result in non-events being considered as major-change events.
This commit makes it so that `(*Mon).timeJumped` is never set to `true`
on iOS and Android.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
And rename to updateFilterLocked to prevent future mistakes.
Fixes#4427
Change-Id: I4d37b90027d5ff872a339ce8180f5723704848dc
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Controlled by server-sent capability policy.
To be initially used for SSH servers to record sessions to other
nodes. Not yet productized into something user-accessible. (Notably,
the list of Taildrop targets from the sender side isn't augmented
yet.) This purely permits expanding the set of expands a node will
accept a drop from.
Updates #3802
Updates #4217
Change-Id: Id7a5bccd686490f8ef2cdc7dae7c07c440dc0085
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
tailcfg.PingResponse formalizes the TSMP & disco response message, and
controlclient is wired to send POST responses containing
tailcfg.PingResponse for TSMP and disco PingRequests.
Updates tailscale/corp#754
Signed-off-by: James Tucker <james@tailscale.com>
Remove the weird netstack -> tailssh dependency and instead have tailssh
register itself with ipnlocal when linked.
This makes tailssh.server a singleton, so we can have a global map of
all sessions.
Updates #3802
Change-Id: Iad5caec3a26a33011796878ab66b8e7b49339f29
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This extracts DOH mapping of known public DNS providers in
forwarder.go into its own package, to be consumed by other repos
Signed-off-by: Jenny Zhang <jz@tailscale.com>
Usage of userspace-networking is increasing, and the aggressive GC
tuning causes a significant reduction in performance in that mode.
Signed-off-by: James Tucker <james@tailscale.com>
This conforms to the NGINX subrequest result authentication protocol[1]
using the NGINX module `ngx_http_auth_request_module`. This is based on
the example that @peterkeen provided on Twitter[2], but with several
changes to make things more tightly locked down:
* This listens over a UNIX socket instead of a TCP socket to prevent
leakage to the network
* This uses systemd socket activation so that systemd owns the socket
and can then lock down the service to the bare minimum required to do
its job without having to worry about dropping permissions
* This provides additional information in HTTP response headers that can
be useful for integrating with various services
* This has a script to automagically create debian and redhat packages
for easier distribution
This will be written about on the Tailscale blog. There is more
information in README.md.
[1]: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-subrequest-authentication/
[2]: https://github.com/peterkeen/tailscale/blob/main/cmd/nginx-auth-proxy/nginx-auth-proxy.go
Signed-off-by: Xe Iaso <xe@tailscale.com>
Currently peerIPs doesn't do any sorting of the routes it returns. This
is typically fine, however imagine the case of an HA subnet router
failover. When a route R moves from peer A to peer B, the output of
peerIPs changes. This in turn causes all the deephash check inside
wgengine to fail as the hashed value of [R1, R2] is different than
the hashed value of [R2, R1]. When the hash check failes, it causes
wgengine to reconfigure all routes in the OS. This is especially
problematic for macOS and iOS where we use the NetworkExtension.
This commit makes it that the peerIPs are always sorted when returned,
thus making the hash be consistent as long as the list of routes remains
static.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Updates #4377
Very smoky/high-level test to ensure that derphttp internals play well
with an agressive (stare + bump) meddler-in-the-middle proxy.
Signed-off-by: Tom DNetto <tom@tailscale.com>
This defines a new magic IPv6 prefix, fd7a:115c:a1e0:b1a::/64, a
subset of our existing /48, where the final 32 bits are an IPv4
address, and the middle 32 bits are a user-chosen "site ID". (which
must currently be 0000:00xx; the top 3 bytes must be zero for now)
e.g., I can say my home LAN's "site ID" is "0000:00bb" and then
advertise its 10.2.0.0/16 IPv4 range via IPv6, like:
tailscale up --advertise-routes=fd7a:115c:a1e0:b1a::bb:10.2.0.0/112
(112 being /128 minuse the /96 v6 prefix length)
Then people in my tailnet can:
$ curl '[fd7a:115c:a1e0:b1a::bb:10.2.0.230]'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ....
Updates #3616, etc
RELNOTE=initial support for TS IPv6 addresses to route v4 "via" specific nodes
Change-Id: I9b49b6ad10410a24b5866b9fbc69d3cae1f600ef
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
To "automatically receive taildrop files to my Downloads directory,"
user currently has to run 'tailscale file get' in a loop. Make
it easy to do this without shell.
Updates: #2312
Signed-off-by: David Eger <david.eger@gmail.com>
Ignoring the events at this layer is the simpler path for right now, a
broader change should follow to suppress irrelevant change events in a
higher layer so as to avoid related problems with other monitoring paths
on other platforms. This approach may also carry a small risk that it
applies an at-most-once invariant low in the chain that could be assumed
otherwise higher in the code.
I adjusted the newAddrMessage type to include interface index rather
than a label, as labels are not always supplied, and in particular on my
test hosts they were consistently missing for ipv6 address messages.
I adjusted the newAddrMessage.Addr field to be populated from
Attributes.Address rather than Attributes.Local, as again for ipv6
.Local was always empty, and with ipv4 the .Address and .Local contained
the same contents in each of my test environments.
Update #4282
Signed-off-by: James Tucker <james@tailscale.com>
While I trust the test behavior, I also want to assert the behavior in a
reproduction environment, this envknob gives me the log information I
need to do so.
Update #4282
Signed-off-by: James Tucker <james@tailscale.com>
I would like to do some more customized integration tests in the future,
(specifically, bringing up a mitm proxy and testing tailscaled through that)
so hoping to bring back the nixos wiring to support that.
Signed-off-by: Tom DNetto <tom@tailscale.com>
This will enable me to land tests for the upcoming monitor change in
PR #4385.
Update #4385
Update #4282
Signed-off-by: James Tucker <james@tailscale.com>
This change builds a derivation for tailscale-go and makes it available in the
users development environment. This is consistent with the shell.nix in corp/.
Once go1.18 is in a stable Nixpkgs release we can avoid relying on derivations
from nixpkgs head. For now, this works well, and the fetched derivations are
cached in the Nix store according to the usual rules.
Fixes#4231
Signed-off-by: Tom DNetto <tom@tailscale.com>
* net/dns, net/dns/resolver, wgengine: refactor DNS request path
Previously, method calls into the DNS manager/resolver types handled DNS
requests rather than DNS packets. This is fine for UDP as one packet
corresponds to one request or response, however will not suit an
implementation that supports DNS over TCP.
To support PRs implementing this in the future, wgengine delegates
all handling/construction of packets to the magic DNS endpoint, to
the DNS types themselves. Handling IP packets at this level enables
future support for both UDP and TCP.
Signed-off-by: Tom DNetto <tom@tailscale.com>
In tracking down issue #4144 and reading through the netstack code in
detail, I discovered that the packet buf Clone path did not reset the
packetbuf it was getting from the sync.Pool. The fix was sent upstream
https://github.com/google/gvisor/pull/7385, and this bump pulls that in.
At this time there is no known path that this fixes, however at the time
of upstream submission this reset at least one field that could lead to
incorrect packet routing if exercised, a situation that could therefore
lead to an information leak.
Signed-off-by: James Tucker <james@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>
In addition an envknob (TS_DEBUG_NETSTACK_LEAK_MODE) now provides access
to set leak tracking to more useful values.
Fixes#4309
Signed-off-by: James Tucker <james@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>
* shell.nix: rename goimports to gotools
Signed-off-by: Xe <xe@tailscale.com>
* cmd/mkpkg: allow specifying description and name in flag args
Signed-off-by: Xe <xe@tailscale.com>
Combine the code between `LocalBackend.CheckIPForwarding` and
`controlclient.ipForwardingBroken`.
Fixes#4300
Signed-off-by: Maisem Ali <maisem@tailscale.com>
While we rearrange/upstream things.
gliderlabs/ssh is forked into tempfork from our prior fork
at be8b7add40
x/crypto/ssh OTOH is forked at
https://github.com/tailscale/golang-x-crypto because it was gnarlier
to vendor with various internal packages, etc.
Its git history shows where it starts (2c7772ba30643b7a2026cbea938420dce7c6384d).
Updates #3802
Change-Id: I546e5cdf831cfc030a6c42557c0ad2c58766c65f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
When `setWgengineStatus` is invoked concurrently from multiple
goroutines, it is possible that the call invoked with a newer status is
processed before a call with an older status. e.g. a status that has
endpoints might be followed by a status without endpoints. This causes
unnecessary work in the engine and can result in packet loss.
This patch adds an `AsOf time.Time` field to the status to specifiy when the
status was calculated, which later allows `setWgengineStatus` to ignore
any status messages it receives that are older than the one it has
already processed.
Updates tailscale/corp#2579
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Currently if the passed in host is an IP, Lookup still attempts to
resolve it with a dns server. This makes it just return the IP directly.
Updates tailscale/corp#4475
Signed-off-by: Maisem Ali <maisem@tailscale.com>
When the context is canceled, dc.dialOne returns an error from line 345.
This causes the defer on line 312 to try to resolve the host again, which
triggers a dns lookup of "127.0.0.1" from derp.
Updates tailscale/corp#4475
Signed-off-by: Maisem Ali <maisem@tailscale.com>
And return an error if you use non-flag arguments.
Change-Id: I0dd6c357eb5cabd0f17020f21ba86406aea21681
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Adds missing file from fc12cbfcd3.
GitHub was having issues earlier and it was all green because the
checks never actually ran, but the DCO non-Actions check at least did,
so "green" and I merged, not realizing it hadn't really run anything.
Updates #3802
Change-Id: I29f605eebe5336f1f3ca28ebb78b092dd99d9fd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This adds a "tailscale nc" command that acts a bit like "nc", but
dials out via tailscaled via localapi.
This is a step towards a "tailscale ssh", as we'll use "tailscale nc"
as a ProxyCommand for in some cases (notably in userspace mode).
But this is also just useful for debugging & scripting.
Updates #3802
RELNOTE=tailscale nc
Change-Id: Ia5c37af2d51dd0259d5833d80264d3ad5f68446a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
prober: add labels to Probe instances.
This allows especially dynamically-registered probes to have a bunch
more dimensions along which they can be sliced in Prometheus.
Signed-off-by: David Anderson <danderson@tailscale.com>
Plumb the outbound injection path to allow passing netstack
PacketBuffers down to the tun Read, where they are decref'd to enable
buffer re-use. This removes one packet alloc & copy, and reduces GC
pressure by pooling outbound injected packets.
Fixes#2741
Signed-off-by: James Tucker <james@tailscale.com>
This enables the infrequent use of more complex Prometheus types, such as
timeseries with high/irregular label cardinality, without needing to
discover and implement generic abstracted type like LabelMap for each one.
Signed-off-by: David Anderson <danderson@tailscale.com>
Primarily this is for f375784d83852b1e3ff20cc9de0648b3c0cf8525 and the
related commits that provide buffer pooling for the endpoint code paths
we use.
Signed-off-by: James Tucker <james@tailscale.com>
Turns out, it's annoying to have to wait the entire interval
before getting any monitorable data, especially for very long
interval probes like hourly/daily checks.
Signed-off-by: David Anderson <danderson@tailscale.com>
Due to a bug in Go (golang/go#51778), cmd/go doesn't warn about your
Go version being older than the go.mod's declared Go version in that
case that package loading fails before the build starts, such as when
you use packages that are only in the current version of Go, like our
use of net/netip.
This change works around that Go bug by adding build tags and a
pre-Go1.18-only file that will cause Go 1.17 and earlier to fail like:
$ ~/sdk/go1.17/bin/go install ./cmd/tailscaled
# tailscale.com/cmd/tailscaled
./required_version.go:11:2: undefined: you_need_Go_1_18_to_compile_Tailscale
note: module requires Go 1.18
Change-Id: I39f5820de646703e19dde448dd86a7022252f75c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Incidentally, simplify the go generate CI workflow, by
marking the dnsfallback update non-hermetic (so CI will
skip it) rather than manually filter it out of `go list`.
Updates #4194
Signed-off-by: David Anderson <danderson@tailscale.com>
The docs say:
Note that while correct uses of TryLock do exist, they are rare,
and use of TryLock is often a sign of a deeper problem in a particular use of mutexes.
Rare code! Or bad code! Who can tell!
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Also make IPPrefixSliceOf use Slice[netaddr.IPPrefix] as it also
provides additional functions besides the standard ones provided by
Slice[T].
Signed-off-by: Maisem Ali <maisem@tailscale.com>
There is a Cosmic Background level of DERP Unreachability,
with individual nodes or regions becoming unreachable briefly
and returning a short time later. This is due to hosting provider
outages or just the Internet sloshing about.
Returning a 500 error pages a human. Being awoken at 3am for
a transient error is annoying.
For relatively small levels of badness don't page a human,
just post to Slack. If the outage impacts a significant fraction
of the DERP fleet, then page a human.
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
It includes a fix to allow us to use Go 1.18.
We can now remove our Tailscale-only build tags.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
The certstore code is impacted by golang/go#51726.
The Tailscale Go toolchain fork contains a temporary workaround,
so it can compile it. Once the upstream toolchain can compile certstore,
presumably in Go 1.18.1, we can revert this change.
Note that depaware runs with the upstream toolchain.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
As of Go 1.18, the register ABI list includes arm64, amd64,
ppc64, and ppc64le. This is a large enough percentage of the
architectures that it's not worth explaining.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This is required for staticcheck to process code
using Go 1.18.
This puts us on a random commit on the bleeding edge
of staticcheck, which isn't great, but there don't
appear to have been any releases yet that support 1.18.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
The version string changed slightly. Adapt.
And always check the current Go version to prevent future
accidental regressions. I would have missed this one had
I not explicitly manually checked it.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
A new flag --conflict=(skip|overwrite|rename) lets users specify
what to do when receiving files that match a same-named file in
the target directory.
Updates #3548
Signed-off-by: David Eger <david.eger@gmail.com>
- Remove the expanded module files, as Go can likely expand the zips
faster than tar can expand the extra copies.
- Add the go-build cache.
- Remove the extra restore key to avoid extra cache lookups on miss.
Signed-off-by: James Tucker <james@tailscale.com>
Co-authored-by: James Tucker <james@tailscale.com>
Still not sure the exact rules of how/when/who's supposed to set
these, but this works for now on making them match. Baby steps.
Will research more and adjust later.
Updates #4146 (but not enough to fix it, something's still wrong)
Updates #3802
Change-Id: I496d8cd7e31d45fe9ede88fc8894f35dc096de67
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We need to be able to provide the ability for the GUI clients to resolve and set
the exit node IP from an untrusted string, thus enabling the ability to specify
that information via enterprise policy.
This patch moves the relevant code out of the handler for `tailscale up`,
into a method on `Prefs` that may then be called by GUI clients.
We also update tests accordingly.
Updates https://github.com/tailscale/corp/issues/4239
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
Enable use of command line arguments with tailscale cli on gokrazy. Before
this change using arguments like "up" would cause tailscale cli to be
repeatedly restarted by gokrazy process supervisor.
We never want to have gokrazy restart tailscale cli, even if user would
manually start the process.
Expected usage is that user creates files:
flags/tailscale.com/cmd/tailscale/flags.txt:
up
flags/tailscale.com/cmd/tailscaled/flags.txt:
--statedir=/perm/tailscaled/
--tun=userspace-networking
Then tailscale prints URL for user to log in with browser.
Alternatively it should be possible to use up with auth key to allow
unattended gokrazy installs.
Signed-off-by: Joonas Kuorilehto <joneskoo@derbian.fi>
Currently `Write` returns the number of ciphertext bytes written.
According to the docs for io.Writer, Write should return the amount
of bytes consumed from the input.
```
// Write writes len(p) bytes from p to the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
// Write must not modify the slice data, even temporarily.
Write(p []byte) (n int, err error)
```
Fixes#4126
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Customer reported an issue where the connections were not closing, and
would instead just stay open. This commit makes it so that we close out
the connection regardless of what error we see. I've verified locally
that it fixes the issue, we should add a test for this.
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Fix regression from 21069124db caught by tests in another repo.
The HTTP/2 Transport that was being returned had a ConnPool that never
dialed.
Updates #3488
Change-Id: I3184d6393813448ae143d37ece14eb732334c05f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We want to close the connection after a minute of inactivity,
not heartbeat once a minute to keep it alive forever.
Updates #3488
Change-Id: I4b5275e8d1f2528e13de2d54808773c70537db91
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
And flesh out docs on the --http-port flag.
Change-Id: If9d42665f67409082081cb9a25ad74e98869337b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This was just cleanup for an ancient version of Tailscale. Any such machines
have upgraded since then.
Change-Id: Iadcde05b37c2b867f92e02ec5d2b18bf2b8f653a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
And add a CapabilityVersion type, primarily for documentation.
This makes MapRequest.Version, RegisterRequest.Version, and
SetDNSRequest.Version all use the same version, which will avoid
confusing in the future if Register or SetDNS ever changed their
semantics on Version change. (Currently they're both always 1)
This will requre a control server change to allow a
SetDNSRequest.Version value other than 1 to be deployed first.
Change-Id: I073042a216e0d745f52ee2dbc45cf336b9f84b7c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
In the future we'll probably want to run the "tailscale web"
server instead, but for now stop the infinite restart loop.
See https://gokrazy.org/userguide/process-interface/ for details.
Updates #1866
Change-Id: I4133a5fdb859b848813972620495865727fe397a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
One of the current few steps to run Tailscale on gokrazy is to
specify the --tun=userspace-networking flag:
https://gokrazy.org/userguide/install/tailscale/
Instead, make it the default for now. Later we can change the
default to kernel mode if available and fall back to userspace
mode like Synology, once #391 is done.
Likewise, set default paths for Gokrazy, as its filesystem hierarchy
is not the Linux standard one. Instead, use the conventional paths as
documented at https://gokrazy.org/userguide/install/tailscale/.
Updates #1866
RELNOTE=default to userspace-networking mode on gokrazy
Change-Id: I3766159a294738597b4b30629d2860312dbb7609
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If it's in a non-standard table, as it is on Unifi UDM Pro, apparently.
Updates #4038 (probably fixes, but don't have hardware to verify)
Change-Id: I2cb9a098d8bb07d1a97a6045b686aca31763a937
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Otherwise it would log warnings about an empty file.
```
stores.go:138: store.NewFileStore("/tmp/3777352782"): file empty; treating it like a missing file [warning]
```
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Also move KubeStore and MemStore into their own package.
RELNOTE: tsnet now supports providing a custom ipn.StateStore.
Signed-off-by: Maisem Ali <maisem@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>
Turns out we're pretty good already at init-time work in tailscaled.
The regexp/syntax shows up but it's hard to get rid of that; zstd even
uses regexp. *shrug*
Change-Id: I856aca056dcb7489f5fc22ef07f55f34ddf19bd6
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For ssh and maybe windows service babysitter later.
Updates #3802
Change-Id: I7492b98df98971b3fb72d148ba92c2276cca491f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For local dev testing initially. Product-wise, it'll probably only be
workable on the two unsandboxed builds.
Updates #3802
Change-Id: Ic352f966e7fb29aff897217d79b383131bf3f92b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
And add a private context type in the process.
Updates #3802
Change-Id: I257187f4cfb0f2248d95b81c1dfe0911ef203b60
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
So it's not confused for a context.Context and we can add contexts
later and not look like we have two.
Updates #3802
Change-Id: Icf229ae2c020d173f3cbf09a13ccd03a60cbb85e
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I introduced a bug in 8fe503057d when unifying oneConnListener
implementations.
The NewOneConnListenerFrom API was easy to misuse (its Close method
closes the underlying Listener), and we did (via http.Serve, which
closes the listener after use, which meant we were close the peerapi's
listener, even though we only wanted its Addr)
Instead, combine those two constructors into one and pass in the Addr
explicitly, without delegating through to any Listener.
Change-Id: I061d7e5f842e0cada416e7b2dd62100d4f987125
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The MSI installer sets a special sentinel value that we can use to detect it.
I also removed the code that bails out when the installation path is not
`Program Files`, as both the NSIS and MSI installers permit the user to install
to a different path.
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This unbreaks some downstream users of tailscale who end up
with build errors from importing a v0 indirect dependency.
Signed-off-by: David Anderson <danderson@tailscale.com>
Don't make users map their system's "caddy" (or whatever) system user
to its userid. We can do that. Support either a uid or a username.
RELNOTE=TS_PERMIT_CERT_UID can contain a uid or username
Change-Id: I7451b537a5e118b818addf1353882291d5f0d07f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
And also reject attempts to use other users.
Updates #3802
Change-Id: Iddc85f6ea2dba17d12be66a50408d24c1f92833e
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
e.g. the change to ipnlocal in this commit ultimately logs out:
{"logtail":{"client_time":"2022-02-17T20:40:30.511381153-08:00","server_time":"2022-02-18T04:40:31.057771504Z"},"type":"Hostinfo","val":{"GoArch":"amd64","Hostname":"tsdev","IPNVersion":"1.21.0-date.20220107","OS":"linux","OSVersion":"Debian 11.2 (bullseye); kernel=5.10.0-10-amd64"},"v":1}
Change-Id: I668646b19aeae4a2fed05170d7b279456829c844
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Otherwise omitempty doesn't work.
This is wire-compatible with a non-pointer type, so switching
is safe, now and in the future.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
(The name SSH_HostKeys is bad but SSHHostKeys is worse.)
Updates #3802
Change-Id: I2a889019c9e8b065b668dd58140db4fcab868a91
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Make tailssh ask LocalBackend for the SSH hostkeys, as we'll need to
distribute them to peers.
For now only the hacky use-same-as-actual-host mode is implemented.
Updates #3802
Change-Id: I819dcb25c14e42e6692c441186c1dc744441592b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
That way humans don't have to remember which is correct.
RELNOTE=--auth-key is the new --authkey, but --authkey still works
Updates tailscale/corp#3486
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
And log it when provided in map responses.
The test uses the date on which I joined Tailscale. :)
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Still largely incomplete, but in a better home now.
Updates #3802
Change-Id: I46c5ffdeb12e306879af801b06266839157bc624
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We need to capture some tailnet-related information for some Docker
features we're building. This exposes the tailnet name and MagicDNS
information via `tailscale status --json`.
Fixestailscale/corp#3670
Signed-off-by: Ross Zurowski <ross@rosszurowski.com>
If we've already connected to a certain name's IP in the past, don't
assume the problem was DNS related. That just puts unnecessarily load
on our bootstrap DNS servers during regular restarts of Tailscale
infrastructure components.
Also, if we do do a bootstrap DNS lookup and it gives the same IP(s)
that we already tried, don't try them again.
Change-Id: I743e8991a7f957381b8e4c1508b8e9d0df1782fe
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
When running this script against a totally fresh out of the box Debian
11 image, sometimes it will fail to run because it doesn't have a
package list cached. This patch adds an `apt-get update` to ensure that
the local package cache is up to date.
Signed-off-by: Xe Iaso <xe@tailscale.com>
Our previous Hostinfo logging was all as a side effect of telling
control. And it got marked as verbose (as it was)
This adds a one-time Hostinfo logging that's not verbose, early in
start-up.
Change-Id: I1896222b207457b9bb12ffa7cf361761fa4d3b3a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Spell hamster correctly, and add the name of a teeny tiny type of
hamster, the Roborovski dwarf hamster.
Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
No behavior changes (intended, at least).
This is in prep for future changes to this package, which would get
too complicated in the current style.
Change-Id: Ic260f8e34ae2f64f34819d4a56e38bee8d8ac5ce
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This TODO was both added and fixed in 506c727e3.
As I recall, I wasn't originally going to do it because it seemed
annoying, so I wrote the TODO, but then I felt bad about it and just
did it, but forgot to remove the TODO.
Change-Id: I8f3514809ad69b447c62bfeb0a703678c1aec9a3
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I was about to add a third copy, so unify them now instead.
Change-Id: I3b93896aa1249b1250a6b1df4829d57717f2311a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
For analysis of log spam.
Bandwidth is ~unchanged from had we not stripped the "[vN] " from
text; it just gets restructed intot he new "v":N, field. I guess it
adds one byte.
Updates #1548
Change-Id: Ie00a4e0d511066a33d10dc38d765d92b0b044697
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The strconv errors already stringified with the same.
Change-Id: I6938c5653e9aafa6d9028d45fc26e39eb9ccbaea
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The TODO is done. Magicsock doesn't require any endpoints to create an
*endpoint now. Verified both in code and empirically: I can use the
env knob and access everything.
Change-Id: I4fe7ed5b11c5c5e94b21ef3d77be149daeab998a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If multiple certificates match when selecting a certificate, use the one
issued the most recently (as determined by the NotBefore timestamp).
This also adds some tests for the function that performs that
comparison.
Updates tailscale/coral#6
Signed-off-by: Adrian Dewhurst <adrian@tailscale.com>
The commit b9c92b90db earlier today
caused a regression of serving an empty map always, as it was
JSON marshalling an atomic.Value instead of the DNS entries map
it just built.
Change-Id: I9da3eeca132c6324462dedeaa7d002908557384b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Didn't help enough. We are setting another header anyway. Restore it.
This reverts commit 60abeb027b.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Avoid some work when D-Bus isn't running.
Change-Id: I6f89bb75fdb24c13f61be9b400610772756db1ef
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If systemd-resolved is enabled but not running (or not yet running,
such as early boot) and resolv.conf is old/dangling, we weren't
detecting systemd-resolved.
This moves its ping earlier, which will trigger it to start up and
write its file.
Updates #3362 (likely fixes)
Updates #3531 (likely fixes)
Change-Id: I6392944ac59f600571c43b8f7a677df224f2beed
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
No one really cares. Its cost outweighs its usefulness.
name old time/op new time/op delta
HandleBootstrapDNS-10 105ns ± 4% 65ns ± 2% -37.68% (p=0.000 n=15+14)
name old alloc/op new alloc/op delta
HandleBootstrapDNS-10 416B ± 0% 0B -100.00% (p=0.000 n=15+15)
name old allocs/op new allocs/op delta
HandleBootstrapDNS-10 3.00 ± 0% 0.00 -100.00% (p=0.000 n=15+15)
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Do json formatting once, rather than on every request.
Use an atomic.Value.
name old time/op new time/op delta
HandleBootstrapDNS-10 6.35µs ± 0% 0.10µs ± 4% -98.35% (p=0.000 n=14+15)
name old alloc/op new alloc/op delta
HandleBootstrapDNS-10 3.20kB ± 0% 0.42kB ± 0% -86.99% (p=0.000 n=12+15)
name old allocs/op new allocs/op delta
HandleBootstrapDNS-10 41.0 ± 0% 3.0 ± 0% -92.68% (p=0.000 n=15+15)
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
A large influx of new connections can bring down DERP
since it spins off a new goroutine for each connection,
where each routine may do significant amount of work
(e.g., allocating memory and crunching numbers for TLS crypto).
The momentary spike can cause the process to OOM.
This commit sets the groundwork for limiting connections,
but leaves the limit at infinite by default.
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
It makes the most sense to have all our utility functions reside in one place.
There was nothing in corp that could not reasonably live in OSS.
I also updated `StartProcessAsChild` to no longer depend on `futureexec`,
thus reducing the amount of code that needed migration. I tested this change
with `tswin` and it is working correctly.
I have a follow-up PR to remove the corresponding code from corp.
The migrated code was mostly written by @alexbrainman.
Sourced from corp revision 03e90cfcc4dd7b8bc9b25eb13a26ec3a24ae0ef9
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This patch adds new functions to be used when accessing system policies,
and revises callers to use the new functions. They first attempt the new
registry path for policies, and if that fails, attempt to fall back to the
legacy path.
We keep non-policy variants of these functions because we should be able to
retain the ability to read settings from locations that are not exposed to
sysadmins for group policy edits.
The remaining changes will be done in corp.
Updates https://github.com/tailscale/tailscale/issues/3584
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
We don't use it anyway, so be explicit that we're not using it.
Change-Id: Iec953271ef0169a2e227811932f5b65b479624af
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-02-07 13:55:42 -08:00
666 changed files with 54043 additions and 10983 deletions
If all the tests pass, the response will be empty, with an http status code of 200.
Failed test error response:
A 400 http status code and the errors in the response body.
The HTTP status code will be 200 if the request was well formed and there were no server errors, even in the case of failing tests or an invalid ACL. Look at the response body to determine whether there was a problem within your ACL or tests.
If there's a problem, the response body will be a JSON object with a non-empty `message` property and optionally additional details in `data`:
```
{
"message":"test(s) failed",
@@ -655,6 +675,8 @@ A 400 http status code and the errors in the response body.
}
```
An empty body or a JSON object with no `message` is returned on success.
<a name=tailnet-devices></a>
### Devices
@@ -662,7 +684,7 @@ A 400 http status code and the errors in the response body.
<a name=tailnet-devices-get></a>
#### <a name="getdevices"></a> `GET /api/v2/tailnet/:tailnet/devices` - list the devices for a tailnet
Lists the devices in a tailnet.
Lists the devices in a tailnet.
Supply the tailnet of interest in the path.
Use the `fields` query parameter to explicitly indicate which fields are returned.
@@ -671,7 +693,7 @@ Use the `fields` query parameter to explicitly indicate which fields are returne
###### Query Parameters
`fields` - Controls which fields will be included in the returned response.
dev=flag.Bool("dev",false,"run in localhost development mode")
addr=flag.String("a",":443","server HTTPS listen address, in form \":port\", \"ip:port\", or for IPv6 \"[ip]:port\". If the IP is omitted, it defaults to all interfaces.")
httpPort=flag.Int("http-port",80,"The port on which to serve HTTP. Set to -1 to disable")
configPath=flag.String("c","","config file path")
certMode=flag.String("certmode","letsencrypt","mode for getting a cert. possible options: manual, letsencrypt")
certDir=flag.String("certdir",tsweb.DefaultCertDir("derper-certs"),"directory to store LetsEncrypt certs, if addr's port is :443")
hostname=flag.String("hostname","derp.tailscale.com","LetsEncrypt host name, if addr's port is :443")
logCollection=flag.String("logcollection","","If non-empty, logtail collection to log to")
runSTUN=flag.Bool("stun",true,"whether to run a STUN server. It will bind to the same IP (if any) as the --addr flag value.")
dev=flag.Bool("dev",false,"run in localhost development mode")
addr=flag.String("a",":443","server HTTPS listen address, in form \":port\", \"ip:port\", or for IPv6 \"[ip]:port\". If the IP is omitted, it defaults to all interfaces.")
httpPort=flag.Int("http-port",80,"The port on which to serve HTTP. Set to -1 to disable. The listener is bound to the same IP (if any) as specified in the -a flag.")
stunPort=flag.Int("stun-port",3478,"The UDP port on which to serve STUN. The listener is bound to the same IP (if any) as specified in the -a flag.")
configPath=flag.String("c","","config file path")
certMode=flag.String("certmode","letsencrypt","mode for getting a cert. possible options: manual, letsencrypt")
certDir=flag.String("certdir",tsweb.DefaultCertDir("derper-certs"),"directory to store LetsEncrypt certs, if addr's port is :443")
hostname=flag.String("hostname","derp.tailscale.com","LetsEncrypt host name, if addr's port is :443")
runSTUN=flag.Bool("stun",true,"whether to run a STUN server. It will bind to the same IP (if any) as the --addr flag value.")
runDERP=flag.Bool("derp",true,"whether to run a DERP server. The only reason to set this false is if you're decommissioning a server but want to keep its bootstrap DNS functionality still running.")
meshPSKFile=flag.String("mesh-psk-file",defaultMeshPSKFile(),"if non-empty, path to file containing the mesh pre-shared key file. It should contain some hex string; whitespace is trimmed.")
meshWith=flag.String("mesh-with","","optional comma-separated list of hostnames to mesh with; the server's own hostname can be in the list")
bootstrapDNS=flag.String("bootstrap-dns-names","","optional comma-separated list of hostnames to make available at /bootstrap-dns")
verifyClients=flag.Bool("verify-clients",false,"verify clients to this DERP server through a local tailscaled instance.")
meshPSKFile=flag.String("mesh-psk-file",defaultMeshPSKFile(),"if non-empty, path to file containing the mesh pre-shared key file. It should contain some hex string; whitespace is trimmed.")
meshWith=flag.String("mesh-with","","optional comma-separated list of hostnames to mesh with; the server's own hostname can be in the list")
bootstrapDNS=flag.String("bootstrap-dns-names","","optional comma-separated list of hostnames to make available at /bootstrap-dns")
unpublishedDNS=flag.String("unpublished-bootstrap-dns-names","","optional comma-separated list of hostnames to make available at /bootstrap-dns and not publish in the list")
verifyClients=flag.Bool("verify-clients",false,"verify clients to this DERP server through a local tailscaled instance.")
acceptConnLimit=flag.Float64("accept-connection-limit",math.Inf(+1),"rate limit for accepting new connection")
acceptConnBurst=flag.Int("accept-connection-burst",math.MaxInt,"burst limit for accepting new connection")
)
var(
@@ -91,7 +98,7 @@ func loadConfig() config {
}
log.Printf("no config path specified; using %s",*configPath)
fmt.Printf("::warning file=%s,line=1,col=1,title=Policy File Modified Externally::The policy file was modified externally in the admin console.\n",*policyFname)
}else{
fmt.Printf("The policy file was modified externally in the admin console.\n")
The authentication service provides the following headers to decorate your
proxied requests:
| Header | Example Value | Description |
| :------ | :-------------- | :---------- |
| `Tailscale-User` | `azurediamond@hunter2.net` | The Tailscale username the remote machine is logged in as in user@host form |
| `Tailscale-Login` | `azurediamond` | The user portion of the Tailscale username the remote machine is logged in as |
| `Tailscale-Name` | `Azure Diamond` | The "real name" of the Tailscale user the machine is logged in as |
| `Tailscale-Profile-Picture` | `https://i.kym-cdn.com/photos/images/newsfeed/001/065/963/ae0.png` | The profile picture provided by the Identity Provider your tailnet uses |
| `Tailscale-Tailnet` | `hunter2.net` | The tailnet name |
Most of the time you can set `X-Webauth-User` to the contents of the
`Tailscale-User` header, but some services may not accept a username with an `@`
symbol in it. If this is the case, set `X-Webauth-User` to the `Tailscale-Login`
header.
The `Tailscale-Tailnet` header can help you identify which tailnet the session
is coming from. If you are using node sharing, this can help you make sure that
you aren't giving administrative access to people outside your tailnet.
### Allow Requests From Only One Tailnet
If you want to prevent node sharing from allowing users to access a service, add
the `Expected-Tailnet` header to your auth request:
```nginx
location/auth{
# ...
proxy_set_headerExpected-Tailnet"tailscale.com";
}
```
If a user from a different tailnet tries to use that service, this will return a
generic "forbidden" error page:
```html
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
```
## Building
Install `cmd/mkpkg`:
```
cd .. && go install ./mkpkg
```
Then run `./mkdeb.sh`. It will emit a `.deb` and `.rpm` package for amd64
machines (Linux uname flag: `x86_64`). You can add these to your deployment
fs.StringVar(&certArgs.certFile,"cert-file","","output cert file or \"-\" for stdout; defaults to DOMAIN.crt if --cert-file and --key-file are both unset")
fs.StringVar(&certArgs.keyFile,"key-file","","output cert file or \"-\" for stdout; defaults to DOMAIN.key if --cert-file and --key-file are both unset")
fs.StringVar(&certArgs.keyFile,"key-file","","output key file or \"-\" for stdout; defaults to DOMAIN.key if --cert-file and --key-file are both unset")
fs.BoolVar(&certArgs.serve,"serve-demo",false,"if true, serve on port :443 using the cert as a demo, instead of writing out the files to disk")
returnfmt.Errorf("too many non-flag arguments: %q",args)
}
st,err:=tailscale.Status(ctx)
ifisSSHOverTailscale(){
iferr:=presentRiskToUser(riskLoseSSH,`You are connected over Tailscale; this action will disable Tailscale and result in your session disconnecting.`,downArgs.acceptedRisks);err!=nil{
returnerr
}
}
st,err:=localClient.Status(ctx)
iferr!=nil{
returnfmt.Errorf("error fetching current status: %w",err)
upf.StringVar(&upArgs.exitNodeIP,"exit-node","","Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node")
upf.BoolVar(&upArgs.exitNodeAllowLANAccess,"exit-node-allow-lan-access",false,"Allow direct access to the local network when routing traffic via an exit node")
upf.BoolVar(&upArgs.runSSH,"ssh",false,"run an SSH server, permitting access per tailnet admin's declared policy")
}
upf.BoolVar(&upArgs.runSSH,"ssh",false,"run an SSH server, permitting access per tailnet admin's declared policy")
upf.StringVar(&upArgs.advertiseTags,"advertise-tags","","comma-separated ACL tags to request; each must start with \"tag:\" (e.g. \"tag:eng,tag:montreal,tag:ssh\")")
upf.StringVar(&upArgs.authKeyOrFile,"authkey","",`node authorization key; if it begins with "file:", then it's a path to a file containing the authkey`)
upf.StringVar(&upArgs.authKeyOrFile,"auth-key","",`node authorization key; if it begins with "file:", then it's a path to a file containing the authkey`)
upf.StringVar(&upArgs.hostname,"hostname","","hostname to use instead of the one provided by the OS")
upf.StringVar(&upArgs.advertiseRoutes,"advertise-routes","","routes to advertise to other nodes (comma-separated, e.g. \"10.0.0.0/8,192.168.0.0/24\") or empty string to not advertise routes")
upf.BoolVar(&upArgs.advertiseDefaultRoute,"advertise-exit-node",false,"offer to be an exit node for internet traffic for the tailnet")
upf.BoolVar(&upArgs.forceDaemon,"unattended",false,"run in \"Unattended Mode\" where Tailscale keeps running even after the current GUI user logs out (Windows-only)")
}
upf.DurationVar(&upArgs.timeout,"timeout",0,"maximum amount of time to wait for tailscaled to enter a Running state; default (0s) blocks forever")
registerAcceptRiskFlag(upf,&upArgs.acceptedRisks)
returnupf
}
@@ -149,6 +149,8 @@ type upArgsT struct {
hostnamestring
opUserstring
jsonbool
timeouttime.Duration
acceptedRisksstring
}
func(aupArgsT)getAuthKey()(string,error){
@@ -177,15 +179,16 @@ var upArgs upArgsT
// JSON block will be output. The AuthURL and QR fields will not be present, the
// BackendState and Error fields will give the result of the authentication.
returnnil,fmt.Errorf("--exit-node-allow-lan-access can only be used with --exit-node")
}
ifupArgs.exitNodeIP!=""{
for_,ip:=rangest.TailscaleIPs{
ifexitNodeIP==ip{
returnnil,fmt.Errorf("cannot use %s as the exit node as it is a local IP address to this machine, did you mean --advertise-exit-node?",upArgs.exitNodeIP)
err=presentRiskToUser(riskLoseSSH,`You are connected over Tailscale; this action will reroute SSH traffic to Tailscale SSH and will result in your session disconnecting.`,env.upArgs.acceptedRisks)
}else{
err=presentRiskToUser(riskLoseSSH,`You are connected using Tailscale SSH; this action will result in your session disconnecting.`,env.upArgs.acceptedRisks)
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.