ssh/tailssh: add back a fake public key handler to support buggy clients

Some clients don't support 'none' authentication and insist on supplying
a public key. This change allows them to do so. It ignores the public key
and uses Tailscale to authenticate.

Updates #14922

Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:
Percy Wegmann 2025-02-10 11:01:51 -06:00 committed by Percy Wegmann
parent b9dc617dda
commit aff27451b9

View File

@ -199,7 +199,8 @@ func (srv *server) OnPolicyChange() {
// - ServerConfigCallback
//
// Do the user auth
// - NoClientAuthHandler
// - NoClientAuthHandler or publicKeyHandler
// - fakePasswordHandler if forcing password auth with the `+password` username suffix
//
// Once auth is done, the conn can be multiplexed with multiple sessions and
// channels concurrently. At which point any of the following can be called
@ -337,6 +338,21 @@ func (c *conn) fakePasswordHandler(ctx ssh.Context, password string) bool {
return c.anyPasswordIsOkay
}
// publicKeyHandler is our implementation of the PublicKeyHandler hook that
// checks whether the user's public key is correct. It exists for clients that
// don't support "none" auth and instead insist on supplying a public key.
// This ignores the supplied public key and authenticates with Tailscale auth
// in the same way as NoClientAuthCallback.
func (c *conn) publicKeyHandler(ctx ssh.Context, pubKey ssh.PublicKey) error {
if err := c.doPolicyAuth(ctx); err != nil {
return err
}
if err := c.isAuthorized(ctx); err != nil {
return err
}
return nil
}
// doPolicyAuth verifies that conn can proceed.
// It returns nil if the matching policy action is Accept or
// HoldAndDelegate. Otherwise, it returns errDenied.
@ -413,6 +429,14 @@ func (srv *server) newConn() (*conn, error) {
NoClientAuthHandler: c.NoClientAuthCallback,
PasswordHandler: c.fakePasswordHandler,
// The below handler exists for clients that don't support "none" auth
// and insist on supplying a public key. It ignores the supplied key
// and instead uses the same Tailscale auth as NoClientAuthCallback.
//
// As of 2025-02-10, tailssh_integration_test does not exercise this functionality.
// See tailscale/tailscale#14969.
PublicKeyHandler: c.publicKeyHandler,
Handler: c.handleSessionPostSSHAuth,
LocalPortForwardingCallback: c.mayForwardLocalPortTo,
ReversePortForwardingCallback: c.mayReversePortForwardTo,