I am trying to connect from VS Code on Windows to a Linux VM on Google Cloud.
I can ssh to the VM successfully from Google Cloud SDK Shell using gcloud compute ssh vm tunnel-through-iap
. However, when I try using using gcloud compute start-iap-tunnel
, the connection doesn't work. When I check sshd logs on the VM, I see:
error: kex_exchange_identification: Connection closed by remote host
Connection closed by 35.235.244.xx port xxxxx
The problem occurs also when I set up the VM as a host in the config file in VS Code and try to connect. If I use ProxyCommand cmd /c "gcloud compute start-iap-tunnel etc..."
I hit sshd on the VM, but it says:
error: kex_exchange_identification: Connection closed by remote host
Connection closed by 35.235.244.xx port xxxxx
Since the user can ssh successfully through the tunnel from the SDK shell, we can rule out permission and firewall issues. I gave the user Compute Admin permissions anyway just to rule out such problems while I troubleshoot this connection issue.
Any idea how I can get it to work? Thank you.
I have finally found the solution to this issue. To recap, if using OS Login and IAP, there's a bit of set-up involved, but it should be very easy if you keep these things in mind:
1. By default, when installing the Google Cloud SDK, there is a space between "Cloud" and SDK" in the path on Windows. Pay attention to this as it might cause issues. In case of trouble, re-install it but change the path to CloudSDK to eliminate that space.
2. When you use gcloud compute ssh
with --tunnel-through-iap
, gcloud
manages keys and credentials under the hood so everything works very smoothly. But in VS Code, you need to create a non-interactive shell with start-iap-tunnel
. So in your ssh config file, you should have something like:
ProxyCommand gcloud compute start-iap-tunnel myhostname 22 --listen-on-stdin --zone us-central1-a --project myproject
Note: if you use %h and %p instead of specifying the hostname and port explicitly, you might have trouble, even if you've already defined them in the config file. Remember that you're using the "Remote - SSH" extension (or similar), so things might have to be specified explicitly.
3. if the gcloud
command is not in your path, you need to find gcloud.cmd
on your system and specify the path to it. So in your config file, you'd have:
ProxyCommand "C:\Users\YourName\AppData\Local\Google\CloudSDK\google-cloud-sdk\bin\gcloud.cmd\gcloud.cmd" compute start-iap-tunnel myhostname 22 --listen-on-stdin --zone us-central1-a --project myproject
4. Remember that you're manually managing all aspects of the connection, so you must also specify the IdentityFile. So in your config file, once your log in to the Google Cloud SDK with gcloud auth login
, run gcloud compute config-ssh
. This adds the needed entries, including the IdentityFile.
Now if your config file in VS Code, add this line:
IdentityFile C:\Users\YourName.ssh\google_compute_engine
5. If you use OS Login, your username is email-derived. So when specifying your username in the config file, do not use your email. Use the username derived from it. This is your username on the host, and should look like username_domain_com
.
That should be it. VS Code should now connect to your remote host without any problem!
For reference, your complete config file in VS Code should look like this:
Host myhost
Hostname <IP or hostname>
User username_domain_com
Port 22
IdentityFile C:\Users\YourName.ssh\google_compute_engine
ProxyCommand gcloud compute start-iap-tunnel myhostname 22 --listen-on-stdin --zone us-central1-a --project myproje
You can access the config file by clicking on the Remote Explorer icon then the little gear that appears next to SSH.