5 June 2025

Secure SSH with Host and User CAs

recap

how things works:

ssh-keygen -f /etc/ssh/ssh_ca -C "Certificate Authority" -N ""

The flags -C and -N mean:

-C “Certificate Authority”: This adds a comment to the key. It’s typically used to help identify the purpose of the key. In this case, the comment is “Certificate Authority”. This is just metadata and doesn’t affect functionality.

-N “”: This sets the passphrase for the private key. An empty string “” means no passphrase is set, so the private key will not be encrypted. This is often used for automation, but it has security implications anyone who gets the private key can use it without needing a password.

/etc/ssh/ssh_ca: Path to the CA private key. /etc/ssh/ssh_ca.pub: CA public key.

2. Configure Machines to Trust the CA:

On both machines (Machine 1 and Machine 2):

TrustedUserCAKeys /etc/ssh/ssh_ca.pub
sudo systemctl restart sshd
3. Create the User’s Key Pair:

On the user’s machine:

ssh-keygen -f ~/.ssh/id_rsa_user -C "user@yourdomain.com"

/.ssh/id_rsa_user: User’s private key. /.ssh/id_rsa_user.pub: User’s public key.

4. Sign the User’s Public Key:

On the CA machine:

ssh-keygen -s /etc/ssh/ssh_ca -I user_certificate -n <username> -V +30d ~/.ssh/id_rsa_user.pub

-s /etc/ssh/ssh_ca: Path to the CA private key. -I user_certificate: Certificate Identifier. -n : Restrict the certificate to on the remote machine.(optional for example user@yourdomain.com) -V +30d: Valid for 30 days.

Host machine1
    Hostname <machine1-ip>
    User <username>
    IdentityFile ~/.ssh/id_rsa_user
    CertificateFile ~/.ssh/id_rsa_user-cert.pub

Host machine2
    Hostname <machine2-ip>
    User <username>
    IdentityFile ~/.ssh/id_rsa_user
    CertificateFile ~/.ssh/id_rsa_user-cert.pub


6. Test the Connection:

From the user’s machine, connect to Machine 1:

ssh machine1
              ┌────────────────┐        ┌────────────────┐
              │ User Machine   │        │ CA Machine     │
              │                │        │                │
              │ Generate       │        │ Generate CA Key│
              │ Key Pair       │        │ Sign User Key  │
              └─────┬──────────┘        └──────┬─────────┘
                    │                           │
                    │ Provide Public Key        │
                    │                           │
                    ▼                           ▼
    ┌──────────────────────────────────────────────────────┐
    │                      Machines (SSH Servers)          │
    │                                                      │
    │ Trust CA Public Key (TrustedUserCAKeys /etc/ssh_ca)  │
    │ Verify User Cert (id_rsa_user-cert.pub)              │
    └──────────────────────────────────────────────────────┘

Setting Up SSH with Two Certificate Authorities (User CA and Host CA)

this is the best practice

Overview of Workflow

  1. User CA: Signs user public keys to authenticate users
  2. Host CA: Signs host public keys to authenticate servers
  3. Machines trust the Host CA for server authentication, and the User CA for user authentication

Steps to Implement

1. Set Up the Certificate Authorities (CAs)

On the User CA machine:

ssh-keygen -f /etc/ssh/user_ca -C "User Certificate Authority" -N ""

This creates:

On the Host CA machine:

ssh-keygen -f /etc/ssh/host_ca -C "Host Certificate Authority" -N ""

This creates:

2. Sign Host Keys with Host CA

On each host machine (Machine 1 and Machine 2):

  1. Generate a host key pair:

    ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N ""
    
  2. Copy the host’s public key (ssh_host_rsa_key.pub) to the Host CA machine

  3. Sign the host key with the Host CA: “`bash sudo ssh-keygen -s /etc/ssh/host_ca -I pi -h -V +1w /etc/ssh/pi_ssh_host_rsa_key.pub

   - `-h`: Indicates this is a host certificate
   - `-I host_machine1`: Identifier for the host
   - `-V +1y`: Certificate is valid for 1 year

4. Place the signed certificate (`ssh_host_rsa_key-cert.pub`) back on the host machine at `/etc/ssh/`

5. Configure sshd on each host machine:
   ```bash
   # Update /etc/ssh/sshd_config
   HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
   
   # Restart SSH
   sudo systemctl restart sshd

you can configure principal,host user ca’s certs in ssd config

TrustedUserCAKeys /etc/ssh/AuditCue_Tech_cert.pub
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u


## in terminal
[ec2-user@ip-172-128-8-102 ssh]$ cd auth_principals/
[ec2-user@ip-172-128-8-102 auth_principals]$ ls -
ls: cannot access '-': No such file or directory
[ec2-user@ip-172-128-8-102 auth_principals]$ ls -l
total 4
-rw-r--r--. 1 root root 7 Feb 22  2024 ec2-user
[ec2-user@ip-172-128-8-102 auth_principals]$ cat ec2-user 
devops
[ec2-user@ip-172-128-8-102 auth_principals]$

3. Configure Hosts to Trust the Host CA

On all machines, including the User CA machine:

  1. Copy the Host CA’s public key (host_ca.pub) to each machine
  2. Add it to /etc/ssh/ssh_known_hosts for server authentication:
    
    @cert-authority * ssh-rsa AAAAB3... host_ca.pub
    

4. Sign User Keys with User CA

On the User CA machine:

  1. Receive the user’s public key (id_rsa_user.pub)

  2. Sign the user key:

    ssh-keygen -s /etc/ssh/user_ca -I user_certificate -n <username> -V +30d ~/.ssh/id_rsa_user.pub
    
    • -s /etc/ssh/user_ca: Path to User CA private key
    • -n <username>: Restrict certificate to specific username
    • -V +30d: Certificate is valid for 30 days
  3. Provide the signed certificate (id_rsa_user-cert.pub) to the user

5. Configure Machines to Trust the User CA

On Machine 1 and Machine 2:

  1. Copy the User CA’s public key (user_ca.pub) to each machine
  2. Update /etc/ssh/sshd_config:
    
    TrustedUserCAKeys /etc/ssh/user_ca.pub
    
  3. Restart SSH:
    
    sudo systemctl restart sshd
    

6. Configure the User’s SSH Client

On the user’s machine:

  1. Add the host CA to ~/.ssh/known_hosts:

    @cert-authority * ssh-rsa AAAAB3... host_ca.pub
    

    this step is optional and it is automatically done when you try to ssh into the machine

  2. Configure the user’s ~/.ssh/config:

   Host machine1
       Hostname <machine1-ip>
       User <username>
       IdentityFile ~/.ssh/id_rsa_user
       CertificateFile ~/.ssh/id_rsa_user-cert.pub

   Host machine2
       Hostname <machine2-ip>
       User <username>
       IdentityFile ~/.ssh/id_rsa_user
       CertificateFile ~/.ssh/id_rsa_user-cert.pub

this step is optinal as well so ssh quickly. all you need to do after configuring this is to run Host machine2

echo "next we will look into architecture..."

System Architecture

architecture

Best Practices for Two CAs

Key Segmentation

Key Protection

Key Rotation

Short-lived Certificates

Auditing and Logging


config example:

Host machine1
    Hostname 192.168.1.10
    User ubuntu
    IdentityFile ~/.ssh/id_rsa_user
    CertificateFile ~/.ssh/id_rsa_user-cert.pub

Host machine2
    Hostname 192.168.1.20
    User root
    IdentityFile ~/.ssh/id_rsa_user
    CertificateFile ~/.ssh/id_rsa_user-cert.pub

his configuration ensures:

1. Host

Each Host block specifies the settings for connecting to a particular remote server. The term “host” here refers to a remote machine you are connecting to using SSH. Each block is dedicated to one machine (e.g., machine1 or machine2).

2. Components of the Configuration

a. Host

Specifies the alias or name used in the configuration to identify a remote machine. Example: Host machine1 or Host machine2. When you run ssh machine1 or ssh machine2, the settings in the corresponding block will apply.

b. Hostname

Specifies the actual IP address or domain name of the remote machine. Example: is the IP address or FQDN (e.g., 192.168.1.10 or example.com).

How the Configuration Works Together

Authentication Flow:

The legitimacy of the hostname (<machine1-ip> or example.com) is verified using the host certificate issued by the Host CA. Here’s a detailed explanation:

Verification of Host Legitimacy

1. Host Key and Certificate

2. Trusted Host CA

3. During Connection

4. Legitimacy Checks

The SSH client performs the following checks:

5. Trust Decision


How This Prevents Attacks

1. Man-in-the-Middle (MITM) Attack Prevention

2. Impersonation Protection


Key Configuration on the Client

To trust the Host CA, add the following entry to your ~/.ssh/known_hosts file:

@cert-authority *.example.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArandomHostCAPublicKey