Creating a Bastion for SSH access on GCP

in Google Cloud (GCP) with discrimiNAT

On some occasions you may want a bastion host present in your VPC. For example:

  • accessing a discrimiNAT instance over SSH
  • accessing a host without a public IP

psst… should you ever need a great alternative to a swarm of squid proxies for outbound filtering, consider discrimiNAT for a cloud-native solution

Table of Contents

Creating a Bastion Host

GCP Create a Bastion Host VM

Let’s create a new instance pretty much as usual, taking care that:

  • it’s in the right region
  • it doesn’t need too much grunt as it will only pass minimal traffic through

We will need to add a small detail in the networking section, though. See the next image.

GCP VM Network Tags to bypass discrimiNAT

Add the network tag bypass-discriminat to this instance. The presence of this network tag enables the traffic to and from this instance to have higher precedence than the control laid out by the discrimiNAT firewall, therefore bypassing it. This will allow you to directly connect to this instance, from your public IP to its public IP.

Your bastion host on GCP is now ready!

Accessing a discrimiNAT instance through the Bastion

The discrimiNAT image is hardened per CIS Benchmark for Ubuntu Linux 18.04 LTS Benchmark v1.0.0 Level 2 Server. Therefore, SSH access to it requires your posture to be sound and secure. Let’s check with a few commands on your machine:

  1. The SSH Agent should have only one identity loaded. This is to prevent it from trying one identity after another to the server, causing the server to block the user after too many failures. So it’s safer to just have the one identity that will work.

    ssh-add -L

    If the output shows more than one line, you may clear all of them out with the command ssh-add -D. If the previous command still shows some lines, check the .ssh directory in your home directory for unexpected private key files.

  2. To add a specific private key to the SSH Agent, run the command:

    ssh-add /path/to/private-key

    And then check with ssh-add -L whether only one line in the output is present.

  3. Check the Compute Metadata -> SSH Keys in Google Cloud (GCP) console for the username of the key loaded above.

GCP VM External and Internal IPs

  1. Finally, SSH into the discrimiNAT instance using the bastion host as ProxyJump. This is needed because discrimiNAT will only allow SSH connections from private IPs (i.e. within the VPC), so you cannot connect to it from a public IP.

    You will need the public IP address of the bastion, the private IP address of the target discrimiNAT instance, and this command:

    ssh -J <username>@<public IP of bastion> <username>@<private IP of discriminat instance>

    An example of a fully formed command from the example deployment in the screenshots is:

    ssh -J [email protected] [email protected]

If you manage to lock yourselves out of a discrimiNAT instance due to repeated authentication failures, either terminate the instance and let the managed instance group bring back a new one, or wait 15 minutes.

Accessing a host without a public IP through the Bastion

This could be much simpler if your target instances are not fussy about where you connect from and how many keys you present. However, since the targets do not have a public IP address at all in this case, you still need to use a bastion host, so there is connectivity to and from them. The commands are the same as above:

  1. Verify the right keys are loaded in your SSH Agent:

    ssh-add -L

  2. Connect using the bastion host as ProxyJump:

    ssh -J <username>@<public IP of bastion> <username>@<private IP of target instance>