gravitational / teleport

The easiest, and most secure way to access and protect all of your infrastructure.
https://goteleport.com
GNU Affero General Public License v3.0
17.44k stars 1.74k forks source link

`tsh proxy ssh` with a username that contains backslash results in password prompt #18424

Open hakontonne opened 1 year ago

hakontonne commented 1 year ago

Expected behavior:

Connecting to a host using the ssh command with a username that contains a backslash should work just as using the tsh ssh command.

ssh machineid\\user@hostname.cluster.domain.com should work the same way tsh ssh machineid\\user@hostname does.

Current behavior:

Calling ssh machineid\\user@hostname.cluster.domain.com results in the following message:

Enter password for Teleport user user:
ERROR: failed reading prompt response
underlying reader is not a terminal

kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

Calling tsh ssh machineid\\user@hostname works fine, also calling ssh machineid\\user@hostname works fine, its when going through the cluster that this bug appears.

While backslashes in usernames are not recommended, its completely possible and Teleport should support it, if it wants true 1 to 1 compatibility with ssh.

Also this bug appeared when deploying Teleport to access Amazon Workspace machines, where users are generated by the system with backslashes in them and access through the SSH command is required to get VS Code support.

Bug details:

Teleport v11.0.1 git: go1.19.2 Proxy version: 11.0.1

Assuming fresh host:

  1. Create user on host system with backslash: useradd -m -g sudo 'Machine1\user'
  2. Ensure that user has access to the local user created: sudo tctl get users/dev_user > dev_user.yaml and then update.
  3. On a client, ensure that the .ssh/config is updated with the auto-generated config from tsh config --proxy proxy.foo.example.com
  4. On a client, attempt connection ssh machineid\\user@hostname.cluster.domain.com

Doing tsh ssh machineid\\user@hostname should work just fine from the same client.

(base) client.user@mac ~ % ssh -v Machine1\\user@hostname.cluster.domain.com
OpenSSH_8.6p1, LibreSSL 3.3.6
debug1: Reading configuration data /Users/user/.ssh/config
debug1: /Users/user/.ssh/config line 24: Applying options for *.cluster.domain.com
debug1: /Users/user/config line 32: Applying options for *.cluster.domain.com
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 21: include /etc/ssh/ssh_config.d/* matched no files
debug1: /etc/ssh/ssh_config line 54: Applying options for *
debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling
debug1: Executing proxy command: exec /opt/homebrew/bin/tsh proxy ssh --cluster=cluster.domain.com --proxy=cluster.domain.com Machine1\\user@hostname.cluster.domain.com:3022
debug1: identity file /Users/user/.tsh/keys/cluster.domain.com/teleport_user type 0
debug1: certificate file /Users/user/.tsh/keys/cluster.domain.com/teleport_user/cluster.domain.com-cert.pub type 4
debug1: Local version string SSH-2.0-OpenSSH_8.6
Enter password for Teleport user teleport_user:
ERROR: failed reading prompt response
underlying reader is not a terminal

kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

I'll be happy to contribute to this issue.

espadolini commented 1 year ago

As per this community slack thread, the problem is in tsh proxy ssh misbehaving with a username that includes backslashes (as it would be necessary for netbios-prefixed usernames).

martgra commented 1 year ago

Have verified that running the command also prompts for password:

$ /opt/homebrew/bin/tsh proxy ssh --cluster=teleport.xxx.xx --proxy=teleport.xxx.xx NETBIOS_PREFIX\martin@jasonbourne.teleport.xxxx.xx:3022

# Outputs
Enter password for Teleport user martin_dev:
webvictim commented 1 year ago

Does tsh proxy ssh support providing the login via -l?

tsh proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx -l "NETBIOS_PREFIX\martin" jasonbourne.teleport.xx.xx:3022

It also might be possible to do:

TELEPORT_USER="NETBIOS_PREFIX\martin" tsh proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx jasonbourne.teleport.xx.xx:3022

The code that splits user@host in tsh is... interesting so providing the username explicitly via some other method is likely to work better.

hakontonne commented 1 year ago

@webvictim that results in a "SSH-2.0-Teleport" line in response!

$ tsh proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx -l "Machine1\user" alice.teleport.xx.xx:3022
SSH-2.0-Teleport

Altering the proxy command in the config to


# Flags for all teleport.xx.xx hosts except the proxy
Host *.teleport.xx.xx !teleport.xx.xx
    Port 3022
    ProxyCommand /opt/homebrew/bin/tsh proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx -l "%r" %h:%p

# End generated Teleport configuration

Changed proxy command from /opt/homebrew/bin/tsh proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx %r@%h:%p

So current workaround is to specify the -l flag in the porxy command config and seperate + surround the %r in double quotes.

espadolini commented 1 year ago

We should probably do that in tsh config, I don't see any drawbacks. I wonder if it's even a tsh proxy ssh issue instead of just a shell quoting issue in ~/.ssh/config. 🤔

hakontonne commented 1 year ago

@espadolini I can create a PR for that, seems like its just changing the string for the SSH config template in openssh.go file.

hakontonne commented 1 year ago

Now have a working version of tsh that gives the following:

./tsh config --proxy teleport.xx.xx
# Begin generated Teleport configuration for teleport.xx.xx by tsh

# Common flags for all teleport.xx.xx hosts
Host *.teleport.xx.xx teleport.xx.xx
    UserKnownHostsFile "/Users/user/.tsh/known_hosts"
    IdentityFile "/Users/user/.tsh/keys/teleport.xx.xx/teleport_user"
    CertificateFile "/Users/user/.tsh/keys/teleport.xx.xx/teleport_user-ssh/teleport.xx.xx-cert.pub"
    PubkeyAcceptedAlgorithms +ssh-rsa-cert-v01@openssh.com
    HostKeyAlgorithms rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com

# Flags for all teleport.xx.xx hosts except the proxy
Host *.teleport.xx.xx !teleport.xx.xx
    Port 3022
    ProxyCommand "/Users/user/GolandProjects/teleport/build/tsh" proxy ssh --cluster=teleport.xx.xx --proxy=teleport.xx.xx -l "%r" %h:%p

# End generated Teleport configuration

PR is here: https://github.com/gravitational/teleport/pull/18447

webvictim commented 1 year ago

We should probably do that in tsh config, I don't see any drawbacks.

Agreed, it'll also enable easier support of usernames containing @ signs.

hakontonne commented 1 year ago

@espadolini Be aware, we found a bug with VS Code, where whenever VS Code edits and saves the .ssh/config file itself (through the "Add New SSH host" dialog), it removes double quotes and breaks this until you manually edits the SSH config again.

I'll raise this with the VS Code and I can have a look and see if we can use the single quotes instead.