Introduction
One of the more frequent problems on Stackoverflow is Compute Engine SSH. This article will dive into how SSH is configured on Compute Engine and how to connect using various SSH tools. I will also cover how to create SSH key pairs and install them on Compute Engine.
Note: I am in the process of writing this article. I decided to release the first part early for everyone’s benefit.
Last Update: February 10, 2020
Initial Setup
In this step, we will set some defaults to minimize the number of command parameters required.
I will be using the Windows Command Prompt syntax. To switch to Linux usually means change the line continuation character ^ to \ and modifying command line parameter quoting.
Set the default region to us-central1
1 |
gcloud config set compute/region us-central1 |
Se the default zone to us-central1-a
1 |
gcloud config set compute/zone us-central1-a |
Double-check the default configuration
1 |
gcloud config list |
Which displays on my system as:
1 2 3 4 5 6 7 8 |
[compute] region = us-central1 zone = us-central1-a [core] account = john.hanley@example.com disable_usage_reporting = False project = fiery-stars-999999 show_structured_logs = always |
I removed extra information. Check that the account and project are set correctly.
Check for existing Google SSH Key Pair
The CLI will use an existing Google SSH Key Pair if they already exist. On Windows, several files are stored in the directory c:\Users\username\.ssh
. The Google Key Pair filenames are:
- google_compute_engine – This is the private key.
- google_compute_engine.ppk – This is the PuTTY file format containing both the private and public key.
- google_compute_engine.pub – This is the public key.
Note: The private key contains everything required. The public key can be extracted from the private key. The PPK is just a different file format containing both the private and public keys.
If these files exist, create a backup directory and move these files there so you can follow along with this tutorial. Do a file move instead of copy/delete so that the file permissions are not changed.
SSH Configuration on a New Compute Engine VM Instance
Create a new instance using the CLI with the minimum number of parameters. Use this command as the basis for future commands. To keep costs low, specify the machine type as f1-micro instead of the default which is n1-standard-1. This article uses Ubuntu 18.04 (Bionic) as the VM instance operating system.
Fetch a list of machine types for a zone
1 |
gcloud compute machine-types list --zones=us-central1-a |
A truncated list looks like this:
1 2 3 4 5 |
NAME ZONE CPUS MEMORY_GB DEPRECATED f1-micro us-central1-a 1 0.60 g1-small us-central1-a 1 1.70 n1-standard-1 us-central1-a 1 3.75 n1-standard-2 us-central1-a 2 7.50 |
Create the first test instance
1 2 3 4 |
gcloud compute instances create ssh-test-1 ^ --machine-type=f1-micro ^ --image=ubuntu-1804-bionic-v20200129a ^ --image-project=ubuntu-os-cloud |
The output from the command:
1 2 3 |
Created [https://www.googleapis.com/compute/v1/projects/fiery-stars-999999/zones/us-central1-a/instances/ssh-test-1]. NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS ssh-test-1 us-central1-a f1-micro 10.128.0.5 104.155.169.104 RUNNING |
Connect to the instance
1 |
gcloud compute ssh ssh-test-1 |
The output from the command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{"version": "0.0.1", "verbosity": "WARNING", "timestamp": "2020-02-11T00:27:37.532Z", "message": "The PuTTY PPK SSH key file for gcloud does not exist."} {"version": "0.0.1", "verbosity": "WARNING", "timestamp": "2020-02-11T00:27:37.534Z", "message": "The public SSH key file for gcloud does not exist."} {"version": "0.0.1", "verbosity": "WARNING", "timestamp": "2020-02-11T00:27:37.535Z", "message": "The private SSH key file for gcloud does not exist."} {"version": "0.0.1", "verbosity": "WARNING", "timestamp": "2020-02-11T00:27:37.536Z", "message": "You do not have an SSH key for gcloud."} {"version": "0.0.1", "verbosity": "WARNING", "timestamp": "2020-02-11T00:27:37.537Z", "message": "SSH keygen will be executed to generate a key."} Updating project ssh metadata...\Updated [https://www.googleapis.com/compute/v1/projects/fiery-stars-999999]. Updating project ssh metadata...done. Waiting for SSH key to propagate. WARNING - POTENTIAL SECURITY BREACH! The server's host key does not match the one PuTTY has cached in the registry. This means that either the server administrator has changed the host key, or you have actually connected to another computer pretending to be the server. The new ssh-ed25519 key fingerprint is: ssh-ed25519 255 b8:6c:96:c6:91:df:96:e4:d1:5e:a3:89:61:84:ee:b1 If you were expecting this change and trust the new key, enter "y" to update PuTTY's cache and continue connecting. If you want to carry on connecting but without updating the cache, enter "n". If you want to abandon the connection completely, press Return to cancel. Pressing Return is the ONLY guaranteed safe choice. Update cached key? (y/n, Return cancels connection) |
On Windows, this command launches a PuTTY SSH terminal window. You will either think this is normal or if you know SSH well, magical. For some clouds, the first SSH connection setup is complicated. Now let’s investigate what really happened.
To connect to a system via SSH, three items are necessary:
- username
- SSH private key on the client computer
- SSH public key on the remote computer setup with the SSH server
This means that the CLI did something on both the local computer and the Compute Engine VM instance.
In the PuTTY SSH terminal window type this command:
1 |
cat ~/.ssh/authorized_keys |
The output will look like this:
1 |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/NkM3YA3Sabq0l0KrN/xxmNrBaLz5U6WS6dZyxvWjb3svMHvfjm7CegBO43vkbNwLIO0irzDpB+AjaCPlAGTqep8fIrjt9xuQso0sihDShm+uAMceEwn/7xrksANSdJKfPRV676RPVGMvMx35cDEIxzGEjvMZeCeJ/Wu7uTmZQfaLpU5Uj9bMo7vgLwTc49eudeV0JEMVd16VUG3DW2i0wz52ne+IRDjqOT7MhBjIlMJjMpHgmLJ16rz1J7whN+s2Thbop/YcufoaJrxWrq+Xno4AS6oEiuNnWgRPMEka3DzYGKhtFfNeOssAhEEQM7r1vf/1E0kp+oR5hFzNLuPB john.hanley@DESKTOP |
Notice a few items about the format:
- Begins with the string “ssh-rsa”. This is the key type.
- PEM-encoded data starting with “AAAAB3N”.
- A comment at the end which happens to be the username/computer-name of my system.
For the previous command, I specified the ~ directory. This is the home directory for the logged-in user. What user is that? How did the CLI choose the username?
Get the logged-in username
In the PuTTY SSH terminal window type this command:
1 |
whoami |
On my system, this results in:
1 |
john.hanley |
How did the CLI choose the username?
In the output from gcloud config list
one of the lines is account = john.hanley@example.com
. The CLI uses the username part of the email address for the Linux username.
This means that if you use different Google Cloud credentials to SSH into an instance, you will log in as different users.
Specify the username
Maybe I prefer to use the username john
instead of john.hanley
. To do that specify the username in front of the instance name in the format username@instance_name
.
1 |
gcloud compute ssh john@ssh-test-1 |
Where does the CLI store the SSH key pair?
The CLI will generate a new Google SSH Key Pair if they do not already exist. On Windows, several files are stored in the directory c:\Users\username\.ssh
. The Google Key Pair filenames are:
- google_compute_engine – This is the private key.
- google_compute_engine.ppk – This is the PuTTY file format containing both the private and public key.
- google_compute_engine.pub – This is the public key.
Note: The key pair private key contains everything required. The public key can be extracted from the private key. The PPK is just a different file format containing both the private and public keys.
The CLI will reuse the existing key pair when creating a new instance. The public key is set up on the remote instance.
Delete the test instance
We are now finished with this test instance. Delete it so that we can go to the next step.
1 |
gcloud compute instances delete ssh-test-1 |
Improving Google Compute Engine SSH security
Host Keys
A host key is a key pair that identifies a remote system. The host key is used to verify that you are connecting to the intended system and to prevent man-in-the-middle (MITM) attacks.
SSH host keys are stored as guest attributes. If guest attributes are enabled on the initial boot, Compute Engine stores the generated host keys as guest attributes. To enable guest attributes, add the command line parameter --metadata enable-guest-attributes=TRUE
.
Create a new test VM instance
1 2 3 4 5 |
gcloud compute instances create ssh-test-1 ^ --machine-type=f1-micro ^ --image=ubuntu-1804-bionic-v20200129a ^ --image-project=ubuntu-os-cloud ^ --metadata enable-guest-attributes=TRUE |
Read the VM instance host keys
1 2 |
gcloud compute instances get-guest-attributes ssh-test-1 ^ --query-path "hostkeys/" |
Command output:
1 2 3 4 |
NAMESPACE KEY VALUE hostkeys ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC0MpMPASbd+rPllL0LpM34a70VLYomo/d4T59wx73ZBeigCRVhfPhsmF2W+oDQw8S/lramFUIUw43j+09Y89NU= hostkeys ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDOgXOdySmE6WZPOnlQTl/KHeNtT9XCP9tOYsbABxqxz hostkeys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKnc0jZ+o6klGNxLWlQ3Z1EPcfAzTsHgK+z9Y3QNFOgppk+gf3CDxIvu7fUBi8SksP5WdOrwlsVXIeF0mAbw7pk/niTwyTQXZji2E3hkxzQsbrJZIKm/gdsLMCV8E0KzYKLnDWZEPsW0Nq9nBGw3W4/LAT5hYl37ldk55m9JsZ9z4G96XyJrYV/L4IwfCQUpsiUlJHvHQ65BmyFROb+2Ck7TLluf74eXEnstY9CyP9xv7CpQChLprPkW5R2ZC1NGZeH0v32EovOVx1Aw+2sXwVW3Ph+O3Io6Aa6QKUPKMU2rXQfgmyQ+e5LfdKwbxNZ01H0BoHh29T6W5hjMgRtcYf |
Connect to the instance
1 |
gcloud compute ssh ssh-test-1 |
The output from the command:
1 |
Writing 3 keys to C:\Users\john.hanley\.ssh\google_compute_known_hosts |
Enable project-wide guest attributes
1 2 |
gcloud compute project-info add-metadata ^ --metadata enable-guest-attributes=TRUE |
Display project info
The output includes guest attributes and remembered SSH public keys.
1 |
gcloud compute project-info describe |
Summary
More Information
Credits
I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Piet Bakker at Pexels.
I design software for enterprise-class systems and data centers. My background is 30+ years in storage (SCSI, FC, iSCSI, disk arrays, imaging) virtualization. 20+ years in identity, security, and forensics.
For the past 14+ years, I have been working in the cloud (AWS, Azure, Google, Alibaba, IBM, Oracle) designing hybrid and multi-cloud software solutions. I am an MVP/GDE with several.
February 15, 2020 at 7:24 PM
Great content! Super high-quality! Keep it up! 🙂
December 14, 2020 at 5:33 AM
I wrote a post about this myself a couple of years ago because the docs weren’t clear. Thanks!