visual-studio-codesshremote-accessssh-keys

VSCode Remote-SSH Refuses to Use ssh-agent on Local Machine and Continuously Asks for Passphrase


Seems like most people that are having this problem are experiencing the issue on the remote server (i.e. running Git on the remote). I am having this problem at the local level (no AgentForwarding involved).

When I attempt to connect to my server with SSH-Remote, I am immediately prompted with an "Enter your passphrase" text box at the top (followed by a second immediately after I connect to the server). If I open my local terminal:

After all this confirmation, if I open up VSCode and run SSH-Remote to connect to server, I am again immediately prompted for a passphrase (again, twice--once before connection and once after).

I have no extensions installed, this isn't for Git, nor am I trying to use my ssh-agent on the remote. I just don't want to be asked for a passphrase multiple times every single time I open the connection, open a new folder, etc...

Any advice is appreciated. Thanks!

Additional Context:

I am using zsh as my default shell (its also set as the default shell in VSCode) and the ssh-agent zsh plugin to start ssh-agent and automatically add keys.

This is the content of my ~/.ssh/config:

AddKeysToAgent yes

Host server
  HostName 192.168.1.155
  User user
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

Host github.com
  HostName github.com
  IdentityFile ~/.ssh/id_ed25519_git
  IdentitiesOnly yes

Debug Level 2 Logs

I tried to get as much logging as possible from VSCode's SSH startup process, and I couldn't even find a reference to the use of ssh-agent or $SSH_AUTH_SOCK.

[22:26:29.832] stderr> debug1: Found key in /home/user/.ssh/known_hosts:1
[22:26:29.834] stderr> debug1: rekey out after 134217728 blocks
[22:26:29.834] stderr> debug1: SSH2_MSG_NEWKEYS sent
[22:26:29.834] stderr> debug1: expecting SSH2_MSG_NEWKEYS
[22:26:29.834] stderr> debug1: SSH2_MSG_NEWKEYS received
[22:26:29.835] stderr> debug1: rekey in after 134217728 blocks
[22:26:29.835] stderr> debug1: Will attempt key: /home/user/.ssh/id_ed25519 ED25519 XXXXXXXXXXXXXXXXXXXXXXXXXX explicit
[22:26:29.835] stderr> debug1: SSH2_MSG_EXT_INFO received
[22:26:29.835] stderr> debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,webauthn-sk-ecdsa-sha2-nistp256@openssh.com,ssh-dss,ssh-rsa,rsa-sha2-256,rsa-sha2-512>
[22:26:29.835] stderr> debug1: kex_ext_info_check_ver: publickey-hostbound@openssh.com=<0>
[22:26:29.880] stderr> debug1: SSH2_MSG_SERVICE_ACCEPT received
[22:26:29.892] stderr> debug1: Authentications that can continue: publickey
[22:26:29.892] stderr> debug1: Next authentication method: publickey
[22:26:29.892] stderr> debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 XXXXXXXXXXXXXXXXXXXXXXXXXX explicit
[22:26:29.893] stderr> debug1: Server accepts key: /home/user/.ssh/id_ed25519 ED25519 XXXXXXXXXXXXXXXXXXXXXXXXXX explicit
[22:26:29.893] stderr> debug1: read_passphrase: can't open /dev/tty: No such device or address
[22:26:29.956] Got askpass request: {"request":"Enter passphrase for key '/home/user/.ssh/id_ed25519':"}
[22:26:29.956] Detected passphrase message
[22:26:29.957] Listening for interwindow password on /run/user/1000/vscode-ssh-askpass-a712a2dfc9c305b1ae74bbab98be91ebec02eafd.sock
[22:26:29.957] Writing password prompt to globalState
[22:26:31.870] Got passphrase response
[22:26:31.870] Interactor gave response: ********************
[22:26:31.870] Cleaning up other-window auth server
[22:26:32.000] stderr> Authenticated to 192.168.1.120 ([192.168.1.120]:22) using "publickey".

Debug Level 3 Logs

Finally managed to figure out a way to force -vvv. They do not make it easy for absolutely 0 reason whatsoever. In this block, I found one mention of agent and it was a log entry saying there isn't one. Not sure how it decides that (which environment variable).

[13:41:11.503] > local-server-1> Running ssh connection command: "-vvv -T -D 33699 -o ConnectTimeout=15 -F /home/user/.ssh/config server bash"
[13:41:11.505] > local-server-1> Spawned ssh, pid=51235
[13:41:11.508] stderr> OpenSSH_9.5p1, OpenSSL 3.1.4 24 Oct 2023
[13:41:11.508] stderr> debug1: Reading configuration data /home/user/.ssh/config
[13:41:11.508] stderr> debug1: /home/user/.ssh/config line 3: Applying options for *
[13:41:11.508] stderr> debug1: /home/user/.ssh/config line 6: Applying options for server
[13:41:11.508] stderr> debug2: resolve_canonicalize: hostname 192.168.1.120 is address
[13:41:11.508] stderr> debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> '/home/user/.ssh/known_hosts'
[13:41:11.508] stderr> debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> '/home/user/.ssh/known_hosts2'
[13:41:11.508] stderr> debug3: ssh_connect_direct: entering
[13:41:11.508] stderr> debug1: Connecting to 192.168.1.120 [192.168.1.120] port 22.
[13:41:11.508] stderr> debug3: set_sock_tos: set socket 3 IP_TOS 0x48
[13:41:11.508] stderr> debug2: fd 3 setting O_NONBLOCK
[13:41:11.508] stderr> debug1: fd 3 clearing O_NONBLOCK
[13:41:11.508] stderr> debug1: Connection established.
[13:41:11.508] stderr> debug3: timeout: 15000 ms remain after connect
[13:41:11.508] stderr> debug1: identity file /home/user/.ssh/id_ed25519 type 3
[13:41:11.508] stderr> debug1: identity file /home/user/.ssh/id_ed25519-cert type -1
[13:41:11.508] stderr> debug1: Local version string SSH-2.0-OpenSSH_9.5
[13:41:11.519] stderr> debug1: Remote protocol version 2.0, remote software version OpenSSH_9.2p1 Debian-2+deb12u1
[13:41:11.519] stderr> debug1: compat_banner: match: OpenSSH_9.2p1 Debian-2+deb12u1 pat OpenSSH* compat 0x04000000
[13:41:11.519] stderr> debug2: fd 3 setting O_NONBLOCK
[13:41:11.519] stderr> debug1: Authenticating to 192.168.1.120:22 as 'ssh-user'
[13:41:11.519] stderr> debug3: record_hostkey: found key type ED25519 in file /home/user/.ssh/known_hosts:1
[13:41:11.519] stderr> debug3: record_hostkey: found key type RSA in file /home/user/.ssh/known_hosts:2
[13:41:11.519] stderr> debug3: record_hostkey: found key type ECDSA in file /home/user/.ssh/known_hosts:3
[13:41:11.519] stderr> debug3: load_hostkeys_file: loaded 3 keys from 192.168.1.120
[13:41:11.519] stderr> debug1: load_hostkeys: fopen /home/user/.ssh/known_hosts2: No such file or directory
[13:41:11.519] stderr> debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
[13:41:11.519] stderr> debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
[13:41:11.519] stderr> debug3: order_hostkeyalgs: have matching best-preference key type ssh-ed25519-cert-v01@openssh.com, using HostkeyAlgorithms verbatim
[13:41:11.519] stderr> debug3: send packet: type 20
[13:41:11.519] stderr> debug1: SSH2_MSG_KEXINIT sent
[13:41:11.520] stderr> debug3: receive packet: type 20
[13:41:11.520] stderr> debug1: SSH2_MSG_KEXINIT received
[13:41:11.520] stderr> debug2: local client KEXINIT proposal
[13:41:11.520] stderr> debug2: KEX algorithms: sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,ext-info-c
[13:41:11.520] stderr> debug2: host key algorithms: ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256
[13:41:11.520] stderr> debug2: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
[13:41:11.520] stderr> debug2: ciphers stoc: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
[13:41:11.520] stderr> debug2: MACs ctos: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
[13:41:11.520] stderr> debug2: MACs stoc: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
[13:41:11.520] stderr> debug2: compression ctos: none,zlib@openssh.com,zlib
[13:41:11.520] stderr> debug2: compression stoc: none,zlib@openssh.com,zlib
[13:41:11.520] stderr> debug2: languages ctos: 
[13:41:11.520] stderr> debug2: languages stoc: 
[13:41:11.520] stderr> debug2: first_kex_follows 0 
[13:41:11.520] stderr> debug2: reserved 0 
[13:41:11.520] stderr> debug2: peer server KEXINIT proposal
[13:41:11.520] stderr> debug2: KEX algorithms: curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
[13:41:11.520] stderr> debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519
[13:41:11.520] stderr> debug2: ciphers ctos: chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
[13:41:11.520] stderr> debug2: ciphers stoc: chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
[13:41:11.520] stderr> debug2: MACs ctos: hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
[13:41:11.520] stderr> debug2: MACs stoc: hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
[13:41:11.520] stderr> debug2: compression ctos: none
[13:41:11.520] stderr> debug2: compression stoc: none
[13:41:11.521] stderr> debug2: languages ctos: 
[13:41:11.521] stderr> debug2: languages stoc: 
[13:41:11.521] stderr> debug2: first_kex_follows 0 
[13:41:11.521] stderr> debug2: reserved 0 
[13:41:11.521] stderr> debug1: kex: algorithm: curve25519-sha256@libssh.org
[13:41:11.521] stderr> debug1: kex: host key algorithm: ssh-ed25519
[13:41:11.521] stderr> debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
[13:41:11.521] stderr> debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
[13:41:11.521] stderr> debug3: send packet: type 30
[13:41:11.521] stderr> debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
[13:41:11.526] stderr> debug3: receive packet: type 31
[13:41:11.526] stderr> debug1: SSH2_MSG_KEX_ECDH_REPLY received
[13:41:11.526] stderr> debug1: Server host key: ssh-ed25519 SHA256:+wYnNtg/GzeBjkCVw2VW+1KuZHq1808nstVdkZh1+bU
[13:41:11.526] stderr> debug3: record_hostkey: found key type ED25519 in file /home/user/.ssh/known_hosts:1
[13:41:11.526] stderr> debug3: record_hostkey: found key type RSA in file /home/user/.ssh/known_hosts:2
[13:41:11.526] stderr> debug3: record_hostkey: found key type ECDSA in file /home/user/.ssh/known_hosts:3
[13:41:11.526] stderr> debug3: load_hostkeys_file: loaded 3 keys from 192.168.1.120
[13:41:11.526] stderr> debug1: load_hostkeys: fopen /home/user/.ssh/known_hosts2: No such file or directory
[13:41:11.526] stderr> debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
[13:41:11.526] stderr> debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
[13:41:11.526] stderr> debug1: Host '192.168.1.120' is known and matches the ED25519 host key.
[13:41:11.526] stderr> debug1: Found key in /home/user/.ssh/known_hosts:1
[13:41:11.528] stderr> debug3: send packet: type 21
[13:41:11.528] stderr> debug2: ssh_set_newkeys: mode 1
[13:41:11.528] stderr> debug1: rekey out after 134217728 blocks
[13:41:11.528] stderr> debug1: SSH2_MSG_NEWKEYS sent
[13:41:11.528] stderr> debug1: expecting SSH2_MSG_NEWKEYS
[13:41:11.528] stderr> debug3: receive packet: type 21
[13:41:11.528] stderr> debug1: SSH2_MSG_NEWKEYS received
[13:41:11.528] stderr> debug2: ssh_set_newkeys: mode 0
[13:41:11.528] stderr> debug1: rekey in after 134217728 blocks
[13:41:11.528] stderr> debug1: Will attempt key: /home/user/.ssh/id_ed25519 ED25519 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXX explicit
[13:41:11.528] stderr> debug2: pubkey_prepare: done
[13:41:11.528] stderr> debug3: send packet: type 5
[13:41:11.528] stderr> debug3: receive packet: type 7
[13:41:11.528] stderr> debug1: SSH2_MSG_EXT_INFO received
[13:41:11.528] stderr> debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,webauthn-sk-ecdsa-sha2-nistp256@openssh.com,ssh-dss,ssh-rsa,rsa-sha2-256,rsa-sha2-512>
[13:41:11.528] stderr> debug1: kex_ext_info_check_ver: publickey-hostbound@openssh.com=<0>
[13:41:11.575] stderr> debug3: receive packet: type 6
[13:41:11.576] stderr> debug2: service_accept: ssh-userauth
[13:41:11.576] stderr> debug1: SSH2_MSG_SERVICE_ACCEPT received
[13:41:11.576] stderr> debug3: send packet: type 50
[13:41:11.599] stderr> debug3: receive packet: type 51
[13:41:11.599] stderr> debug1: Authentications that can continue: publickey
[13:41:11.599] stderr> debug3: start over, passed a different list publickey
[13:41:11.599] stderr> debug3: preferred publickey,keyboard-interactive,password
[13:41:11.599] stderr> debug3: authmethod_lookup publickey
[13:41:11.599] stderr> debug3: remaining preferred: keyboard-interactive,password
[13:41:11.599] stderr> debug3: authmethod_is_enabled publickey
[13:41:11.599] stderr> debug1: Next authentication method: publickey
[13:41:11.599] stderr> debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXX explicit
[13:41:11.599] stderr> debug3: send packet: type 50
[13:41:11.599] stderr> debug2: we sent a publickey packet, wait for reply
[13:41:11.599] stderr> debug3: receive packet: type 60
[13:41:11.599] stderr> debug1: Server accepts key: /home/user/.ssh/id_ed25519 ED25519 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXX explicit
[13:41:11.600] stderr> debug3: sign_and_send_pubkey: using publickey-hostbound-v00@openssh.com with ED25519 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXX
[13:41:11.600] stderr> debug3: sign_and_send_pubkey: signing using ssh-ed25519 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXX
[13:41:11.600] stderr> debug1: read_passphrase: can't open /dev/tty: No such device or address
[13:41:11.663] Got askpass request: {"request":"Enter passphrase for key '/home/user/.ssh/id_ed25519':"}
[13:41:11.663] Detected passphrase message
[13:41:11.663] Listening for interwindow password on /run/user/1000/vscode-ssh-askpass-3c669b661bf05bd38516123cc0c4977123a4eed3.sock
[13:41:11.663] Writing password prompt to globalState
[13:41:23.598] Got passphrase response
[13:41:23.599] Interactor gave response: ********************
[13:41:23.599] Cleaning up other-window auth server
[13:41:23.724] stderr> debug3: no authentication agent, not adding key
[13:41:23.724] stderr> debug3: send packet: type 50
[13:41:23.731] stderr> debug3: receive packet: type 52
[13:41:23.731] stderr> Authenticated to 192.168.1.120 ([192.168.1.120]:22) using "publickey".

At this point, the only thing I can imagine, given that the local-server can't find the agent, is that (despite setting the shell to ZSH in VSCode settings), Remote SSH is still using bash or sh, and because of that, has no access to the environment variables.

Not sure how I can tell if this is the case. Even more unsure of how I would change that.

Anywhere else I should look for logs to diagnose the root cause of this issue?

Update

Probably will be my last update, since I found a somewhat workable solution, but I would like to still understand why this is giving me trouble and fix it if possible.

If I make sure that no other VSCode instances are running, and run code from the command line, that specific VSCode instance can interface with the ssh-agent and doesn't ask for passphrases. If I run it from KRunner (on Arch Linux KDE), it can not. Not sure if this is a permissions or environment variable thing at this point.

Given this new information, any ideas on next step troubleshooting? Thanks again.


Solution

  • TL;DR

    Resolved. I was using the oh-my-zsh ssh-agent plugin which initialized and exported the ssh-agent environment variables for individual interactive shell instances on shell startup, since it was sourced in .zshrc. VSCode can't access that if it is run via xdg-open/kde-open. Running it in the console actually allowed it to work which was the hint I needed to resolve the issue.

    The important lesson is understanding the differences between interactive, non-interactive, and login shells and how environment variables may or may not be set in one context or another. Depending on the functionality you are aiming for, you should be using one of (not exhaustive): .zshrc, .zprofile, OR .bashrc, .bash_profile. I recommend you initialize your ssh-agent in a profile file for your respective shell IF you plan to use ssh from beyond the shell. That way, even those programs can access the necessary env variables.

    Solution Details

    It was somewhat disappointing. Heres the solution plus reasoning and sources in case others run into this:

    1. If I have NO other instances of code open and opened it via the console (code) instead of the code.desktop, it actually worked with the ssh-agent! I had tried this before, but I suspect it was done incorrectly for two reasons:
    1. This meant it must have been an environment variable issue. To confirm, I added to the .desktop the current SSH_AUTH_SOCK and SSH_AGENT_PID env variables. Lo and behold, it worked.

    2. Quick Google search regarding why the terminal might have access to env variables and not xdg-open (or possibly kde-open in my case) yielded this thread. In my case, I am using the oh-my-zsh ssh-agent plugin that is started in .zshrc--which is only run for interactive terminals, on each terminal instance startup. My guess was that xdg-open/kde-open are not interactive terminals, as they only run the Exec portion of the .desktop with no user input. Thus, the plugin wasn't starting and the variables were not being exported for the VSCode startup. Rather, if I run code at the terminal, since it was born from that terminal, it inherits the environment variables the terminal initialized which is why it was working in that context. Ugh.

    3. More research pointed to moving ssh-agent initialization out to .zprofile. So, I moved the ssh-agent initialization out to $HOME/.zprofile and made an equivalent initialization (checks if ssh-agent is running first before so they don't each start their own instance) in $HOME/.bash_profile.

    4. It worked at last.

    This was the result of ~4 hours of debugging/researching each day for the last 4 or 5 days, so kinda pathetic it was a relatively simple issue lol.