summaryrefslogtreecommitdiffhomepage
path: root/ssh/tailssh
AgeCommit message (Collapse)AuthorFilesLines
2025-09-28util/backoff: rename logtail/backoff package to util/backoffBrad Fitzpatrick1-1/+1
It has nothing to do with logtail and is confusing named like that. Updates #cleanup Updates #17323 Change-Id: Idd34587ba186a2416725f72ffc4c5778b0b9db4a Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-17ssh/tailssh: mark TestSSHRecordingCancelsSessionsOnUploadFailure as flakyAlex Chan1-0/+3
Updates https://github.com/tailscale/tailscale/issues/7707 Signed-off-by: Alex Chan <alexc@tailscale.com>
2025-09-16health,ipn/ipnlocal: introduce eventbus in heath.Tracker (#17085)Claus Lensbøl1-1/+1
The Tracker was using direct callbacks to ipnlocal. This PR moves those to be triggered via the eventbus. Additionally, the eventbus is now closed on exit from tailscaled explicitly, and health is now a SubSystem in tsd. Updates #15160 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-07-16ssh/tailssh: fix path of "true" on Darwin (#16569)M. J. Fromberger1-11/+14
This is a follow-up to #15351, which fixed the test for Linux but not for Darwin, which stores its "true" executable in /usr/bin instead of /bin. Try both paths when not running on Windows. In addition, disable CGo in the integration test build, which was causing the linker to fail. These tests do not need CGo, and it appears we had some version skew with the base image on the runners. In addition, in error cases the recover step of the permissions check was spuriously panicking and masking the "real" failure reason. Don't do that check when a command was not produced. Updates #15350 Change-Id: Icd91517f45c90f7554310ebf1c888cdfd109f43a Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
2025-06-03ssh/tailssh: display more useful error messages when authentication failsPercy Wegmann2-30/+73
Also add a trailing newline to error banners so that SSH client messages don't print on the same line. Updates tailscale/corp#29138 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-05-22ssh/tailssh: exclude Android from Linux build tagsBrad Fitzpatrick4-4/+4
As noted in #16048, the ./ssh/tailssh package failed to build on Android, because GOOS=android also matches the "linux" build tag. Exclude Android like iOS is excluded from macOS (darwin). This now works: $ GOOS=android go install ./ipn/ipnlocal ./ssh/tailssh The original PR at #16048 is also fine, but this stops the problem earlier. Updates #16048 Change-Id: Ie4a6f6966a012e510c9cb11dd0d1fa88c48fac37 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-05-10ssh/tailssh: fix data race during execution of testNick Khyl1-10/+10
In tailssh.go:1284, (*sshSession).startNewRecording starts a fire-and-forget goroutine that can outlive the test that triggered its creation. Among other things, it uses ss.logf, and may call it after the test has already returned. Since we typically use (*testing.T).Logf as the logger, this results in a data race and causes flaky tests. Ideally, we should fix the root cause and/or use a goroutines.Tracker to wait for the goroutine to complete. But with the release approaching, it's too risky to make such changes now. As a workaround, we update the tests to use tstest.WhileTestRunningLogger, which logs to t.Logf while the test is running and disables logging once the test finishes, avoiding the race. While there, we also fix TestSSHAuthFlow not to use log.Printf. Updates #15568 Updates #7707 (probably related) Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-05-09ssh/tailssh: chdir to user's homedir when directly running a command (#15351)Simon Law1-5/+63
Commit 4b525fdda (ssh/tailssh: only chdir incubator process to user's homedir when necessary and possible, 2024-08-16) defers changing the working directory until the incubator process drops its privileges. However, it didn't account for the case where there is no incubator process, because no tailscaled was found on the PATH. In that case, it only intended to run `tailscaled be-child` in the root directory but accidentally ran everything there. Fixes: #15350 Signed-off-by: Simon Law <sfllaw@sfllaw.ca>
2025-04-16net/netmon: publish events to event busDavid Anderson1-1/+1
Updates #15160 Signed-off-by: David Anderson <dave@tailscale.com>
2025-04-16all: update the tsd.System constructor name (#15372)M. J. Fromberger1-1/+1
Replace NewSystemWithEventBus with plain NewSystem, and update all usage. See https://github.com/tailscale/tailscale/pull/15355#discussion_r2003910766 Updates #15160 Change-Id: I64d337f09576b41d9ad78eba301a74b9a9d6ebf4 Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
2025-04-16all: construct new System values with an event bus pre-populatedM. J. Fromberger1-1/+1
Although, at the moment, we do not yet require an event bus to be present, as we start to add more pieces we will want to ensure it is always available. Add a new constructor and replace existing uses of new(tsd.System) throughout. Update generated files for import changes. Updates #15160 Change-Id: Ie5460985571ade87b8eac8b416948c7f49f0f64b Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
2025-04-02ssh/tailssh: add Plan 9 support for Tailscale SSHBrad Fitzpatrick3-3/+430
Updates #5794 Change-Id: I7b05cd29ec02085cb503bbcd0beb61bf455002ac Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-03-10ssh/tailssh: fix typo in forwardedEnviron method, add docsBrad Fitzpatrick1-13/+25
And don't return a comma-separated string. That's kinda weird signature-wise, and not needed by half the callers anyway. The callers that care can do the join themselves. Updates #cleanup Change-Id: Ib5ad51a3c6b663d868eba14fe9dc54b2609cfb0d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-02-13ssh/tailssh: accept passwords and public keysPercy Wegmann4-107/+271
Some clients don't request 'none' authentication. Instead, they immediately supply a password or public key. This change allows them to do so, but ignores the supplied credentials and authenticates using Tailscale instead. Updates #14922 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-02-11tempfork/sshtest/ssh: add fork of golang.org/x/crypto/ssh for testing onlyBrad Fitzpatrick1-0/+3
This fork golang.org/x/crypto/ssh (at upstream x/crypto git rev e47973b1c1) into tailscale.com/tempfork/sshtest/ssh so we can hack up the client in weird ways to simulate other SSH clients seen in the wild. Two changes were made to the files when they were copied from x/crypto: * internal/poly1305 imports were replaced by the non-internal version; no code changes otherwise. It didn't need the internal one. * all decode-with-passphrase funcs were deleted, to avoid using the internal package x/crypto/ssh/internal/bcrypt_pbkdf Then the tests passed. Updates #14969 Change-Id: Ibf1abebfe608c75fef4da0255314f65e54ce5077 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-02-05ssh: don't use -l option for shells on OpenBSDPercy Wegmann1-2/+2
Shells on OpenBSD don't support the -l option. This means that when handling SSH in-process, we can't give the user a login shell, but this change at least allows connecting at all. Updates #13338 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-02-05ssh: refactor OS names into constantsPercy Wegmann1-10/+17
Updates #13338 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-02-05ssh: don't use -l option for shells on FreeBSDPercy Wegmann1-0/+4
Shells on FreeBSD don't support the -l option. This means that when handling SSH in-process, we can't give the user a login shell, but this change at least allows connecting at all. Updates #13338 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-01-31ssh,tempfork/gliderlabs/ssh: replace ↵Percy Wegmann3-187/+130
github.com/tailscale/golang-x-crypto/ssh with golang.org/x/crypto/ssh The upstream crypto package now supports sending banners at any time during authentication, so the Tailscale fork of crypto/ssh is no longer necessary. github.com/tailscale/golang-x-crypto is still needed for some custom ACME autocert functionality. tempfork/gliderlabs is still necessary because of a few other customizations, mostly related to TTY handling. Originally implemented in 46fd4e58a27495263336b86ee961ee28d8c332b7, which was reverted in b60f6b849af1fae1cf343be98f7fb1714c9ea165 to keep the change out of v1.80. Updates #8593 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-01-29Revert "ssh,tempfork/gliderlabs/ssh: replace ↵Percy Wegmann3-130/+187
github.com/tailscale/golang-x-crypto/ssh with golang.org/x/crypto/ssh" This reverts commit 46fd4e58a27495263336b86ee961ee28d8c332b7. We don't want to include this in 1.80 yet, but can add it back post 1.80. Updates #8593 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-01-28ssh,tempfork/gliderlabs/ssh: replace ↵Percy Wegmann3-187/+130
github.com/tailscale/golang-x-crypto/ssh with golang.org/x/crypto/ssh The upstream crypto package now supports sending banners at any time during authentication, so the Tailscale fork of crypto/ssh is no longer necessary. github.com/tailscale/golang-x-crypto is still needed for some custom ACME autocert functionality. tempfork/gliderlabs is still necessary because of a few other customizations, mostly related to TTY handling. Updates #8593 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2025-01-07all: fix golangci-lint errorsWill Norris1-4/+4
These erroneously blocked a recent PR, which I fixed by simply re-running CI. But we might as well fix them anyway. These are mostly `printf` to `print` and a couple of `!=` to `!Equal()` Updates #cleanup Signed-off-by: Will Norris <will@tailscale.com>
2024-12-12ssh/tailssh: remove unused public key supportBrad Fitzpatrick2-337/+28
When we first made Tailscale SSH, we assumed people would want public key support soon after. Turns out that hasn't been the case; people love the Tailscale identity authentication and check mode. In light of CVE-2024-45337, just remove all our public key code to not distract people, and to make the code smaller. We can always get it back from git if needed. Updates tailscale/corp#25131 Updates golang/go#70779 Co-authored-by: Percy Wegmann <percy@tailscale.com> Change-Id: I87a6e79c2215158766a81942227a18b247333c22 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-11-18sessionrecording: implement v2 recording endpoint support (#14105)Andrew Lytvynov2-26/+48
The v2 endpoint supports HTTP/2 bidirectional streaming and acks for received bytes. This is used to detect when a recorder disappears to more quickly terminate the session. Updates https://github.com/tailscale/corp/issues/24023 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
2024-11-05types/result, util/lineiter: add package for a result type, use itBrad Fitzpatrick2-17/+14
This adds a new generic result type (motivated by golang/go#70084) to try it out, and uses it in the new lineutil package (replacing the old lineread package), changing that package to return iterators: sometimes over []byte (when the input is all in memory), but sometimes iterators over results of []byte, if errors might happen at runtime. Updates #12912 Updates golang/go#70084 Change-Id: Iacdc1070e661b5fb163907b1e8b07ac7d51d3f83 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-11ssh/tailssh: calculate passthrough environment at latest possible stagePercy Wegmann1-15/+37
This allows passing through any environment variables that we set ourselves, for example DBUS_SESSION_BUS_ADDRESS. Updates #11175 Co-authored-by: Mario Minardi <mario@tailscale.com> Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-10-03ssh/tailssh: pass window size pixels in IoctlSetWinsize eventsBrad Fitzpatrick1-2/+4
Fixes #13669 Change-Id: Id44cfbb83183f1bbcbdc38c29238287b9d288707 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-09-30ssh: Add logic to set accepted environment variables in SSH session (#13559)Mario Minardi6-55/+294
Add logic to set environment variables that match the SSH rule's `acceptEnv` settings in the SSH session's environment. Updates https://github.com/tailscale/corp/issues/22775 Signed-off-by: Mario Minardi <mario@tailscale.com>
2024-09-25ssh/tailssh: add logic for matching against AcceptEnv patterns (#13466)Mario Minardi2-0/+250
Add logic for parsing and matching against our planned format for AcceptEnv values. Namely, this supports direct matches against string values and matching where * and ? are treated as wildcard characters which match against an arbitrary number of characters and a single character respectively. Actually using this logic in non-test code will come in subsequent changes. Updates https://github.com/tailscale/corp/issues/22775 Signed-off-by: Mario Minardi <mario@tailscale.com>
2024-09-25util/usermetrics: make usermetrics non-globalKristoffer Dalby1-1/+1
this commit changes usermetrics to be non-global, this is a building block for correct metrics if a go process runs multiple tsnets or in tests. Updates #13420 Updates tailscale/corp#22075 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-09-11util/slicesx: add FirstElementEqual and LastElementEqualBrad Fitzpatrick1-1/+2
And update a few callers as examples of motivation. (there are a couple others, but these are the ones where it's prettier) Updates #cleanup Change-Id: Ic8c5cb7af0a59c6e790a599136b591ebe16d38eb Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-08-29ssh/tailssh: add ability to force V2 behavior using new feature flagPercy Wegmann1-1/+2
Introduces ssh-behavior-v2 node attribute to override ssh-behavior-v1. Updates #11854 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-08-22all: fix new lint warnings from bumping staticcheckBrad Fitzpatrick1-0/+1
In prep for updating to new staticcheck required for Go 1.23. Updates #12912 Change-Id: If77892a023b79c6fa798f936fc80428fd4ce0673 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-08-21ssh/tailssh: only chdir incubator process to user's homedir when necessary ↵Percy Wegmann4-16/+22
and possible Instead of changing the working directory before launching the incubator process, this now just changes the working directory after dropping privileges, at which point we're more likely to be able to enter the user's home directory since we're running as the user. For paths that use the 'login' or 'su -l' commands, those already take care of changing the working directory to the user's home directory. Fixes #13120 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-08-21ssh/tailssh: fix SSH on busybox systemsPercy Wegmann3-36/+55
This involved the following: 1. Pass the su command path as first of args in call to unix.Exec to make sure that busybox sees the correct program name. Busybox is a single executable userspace that implements various core userspace commands in a single binary. You'll see it used via symlinking, so that for example /bin/su symlinks to /bin/busybox. Busybox knows that you're trying to execute /bin/su because argv[0] is '/bin/su'. When we called unix.Exec, we weren't including the program name for argv[0], which caused busybox to fail with 'applet not found', meaning that it didn't know which command it was supposed to run. 2. Tell su to whitelist the SSH_AUTH_SOCK environment variable in order to support ssh agent forwarding. 3. Run integration tests on alpine, which uses busybox. 4. Increment CurrentCapabilityVersion to allow turning on SSH V2 behavior from control. Fixes #12849 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-07-29cmd/k8s-operator,k8s-operator/sessionrecording,sessionrecording,ssh/tailssh: ↵Irbe Krumina3-194/+5
refactor session recording functionality (#12945) cmd/k8s-operator,k8s-operator/sessionrecording,sessionrecording,ssh/tailssh: refactor session recording functionality Refactor SSH session recording functionality (mostly the bits related to Kubernetes API server proxy 'kubectl exec' session recording): - move the session recording bits used by both Tailscale SSH and the Kubernetes API server proxy into a shared sessionrecording package, to avoid having the operator to import ssh/tailssh - move the Kubernetes API server proxy session recording functionality into a k8s-operator/sessionrecording package, add some abstractions in preparation for adding support for a second streaming protocol (WebSockets) Updates tailscale/corp#19821 Signed-off-by: Irbe Krumina <irbe@tailscale.com>
2024-07-08cmd/k8s-operator,ssh/tailssh,tsnet: optionally record 'kubectl exec' ↵Irbe Krumina2-125/+137
sessions via Kubernetes operator's API server proxy (#12274) cmd/k8s-operator,ssh/tailssh,tsnet: optionally record kubectl exec sessions The Kubernetes operator's API server proxy, when it receives a request for 'kubectl exec' session now reads 'RecorderAddrs', 'EnforceRecorder' fields from tailcfg.KubernetesCapRule. If 'RecorderAddrs' is set to one or more addresses (of a tsrecorder instance(s)), it attempts to connect to those and sends the session contents to the recorder before forwarding the request to the kube API server. If connection cannot be established or fails midway, it is only allowed if 'EnforceRecorder' is not true (fail open). Updates tailscale/corp#19821 Signed-off-by: Irbe Krumina <irbe@tailscale.com> Co-authored-by: Maisem Ali <maisem@tailscale.com>
2024-06-20ssh/tailssh: fix integration test (#12562)Irbe Krumina1-1/+1
Updates#cleanup Signed-off-by: Irbe Krumina <irbe@tailscale.com>
2024-06-20ssh/tailssh: replace incubator process with su instead of running su as childPercy Wegmann3-49/+177
This allows the SSH_AUTH_SOCK environment variable to work inside of su and agent forwarding to succeed. Fixes #12467 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-06-18proxymap, various: distinguish between different protocolsAndrew Dunham2-3/+7
Previously, we were registering TCP and UDP connections in the same map, which could result in erroneously removing a mapping if one of the two connections completes while the other one is still active. Add a "proto string" argument to these functions to avoid this. Additionally, take the "proto" argument in LocalAPI, and plumb that through from the CLI and add a new LocalClient method. Updates tailscale/corp#20600 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I35d5efaefdfbf4721e315b8ca123f0c8af9125fb
2024-06-12ssh/tailssh: check IsSELinuxEnforcing in tailscaled processPercy Wegmann2-16/+38
Checking in the incubator as this used to do fails because the getenforce command is not on the PATH. Updates #12442 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-05-29ssh/tailssh: fall back to using su when no TTY available on LinuxPercy Wegmann5-246/+613
This allows pam authentication to run for ssh sessions, triggering automation like pam_mkhomedir. Updates #11854 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-05-03ssh/tailssh: plumb health.Tracker in testBrad Fitzpatrick1-1/+1
In prep for it being required in more places. Updates #11874 Change-Id: Ib743205fc2a6c6ff3d2c4ed3a2b28cac79156539 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-05-03ssh/tailssh: use ptr.To in testBrad Fitzpatrick1-3/+2
Updates #cleanup Change-Id: Ic98ba1b63c8205084b30f59f0ca343788edea5b0 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-05-01ssh/tailssh: add integration testPercy Wegmann3-1/+430
Updates tailscale/corp#11854 Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-04-23ssh/tailssh: try fetching group IDs for user with the 'id' commandAndrew Dunham1-8/+2
Since the tailscaled binaries that we distribute are static and don't link cgo, we previously wouldn't fetch group IDs that are returned via NSS. Try shelling out to the 'id' command, similar to how we call 'getent', to detect such cases. Updates #11682 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I9bdc938bd76c71bc130d44a97cc2233064d64799
2024-04-22ipn/ipnlocal,ssh/tailssh: reject c2n /update if SSH conns are active (#11820)Andrew Lytvynov1-0/+7
Since we already track active SSH connections, it's not hard to proactively reject updates until those finish. We attempt to do the same on the control side, but the detection latency for new connections is in the minutes, which is not fast enough for common short sessions. Handle a `force=true` query parameter to override this behavior, so that control can still trigger an update on a server where some long-running abandoned SSH session is open. Updates https://github.com/tailscale/corp/issues/18556 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
2024-04-16all: use Go 1.22 range-over-intBrad Fitzpatrick1-1/+1
Updates #11058 Change-Id: I35e7ef9b90e83cac04ca93fd964ad00ed5b48430 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-02-08all: use reflect.TypeFor now available in Go 1.22 (#11078)Joe Tsai1-1/+1
Updates #cleanup Signed-off-by: Joe Tsai <joetsai@digital-static.net>
2024-01-05ssh/tailssh: use a local error instead of gossh.ErrDenied (#10743)Andrew Lytvynov1-9/+13
ErrDenied was added in [our fork of x/crypto/ssh](https://github.com/golang/crypto/commit/acc6f8fe8d618cba34d44e89fdde304f98c576df) to short-circuit auth attempts once one fails. In the case of our callbacks, this error is returned when SSH policy check determines that a connection should not be allowed. Both `NoClientAuthCallback` and `PublicKeyHandler` check the policy and will fail anyway. The `fakePasswordHandler` returns true only if `NoClientAuthCallback` succeeds the policy check, so it checks it indirectly too. The difference here is that a client might attempt all 2-3 auth methods instead of just `none` but will fail to authenticate regardless. Updates #8593 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>