💾
ITmatic101
  • ITmatic101 - Tech Blog
  • 🧙‍♂️Linux
    • SSH certificate authentication
    • SSH key authentication for LDAP login
    • Using GPG to encrypt/decrypt files or messages
    • Understanding SUID, SGID and Sticky Bit
    • Unleashing VIM
  • 🐍Python
    • Setting up a Python developer environment
  • 🚀Ansible
    • Setting up LXD Lab with Ansible
    • Ansible Vault
    • Ansible WireGuard workflow on Linode
  • 🍨Virtualisation
    • SSH key management in LXD
    • Customise VM template with cloud-init on Proxmox
  • ⚒️Homelab
    • Setting up AdGuard Home
    • SSH key authentication on Windows
  • 🧲Networking
    • MikroTik networking lab setup with Containerlab
    • Mikrotik IPsec Tunnel Setup
    • Mikrotik VLAN Trunking
    • Mikrotik QinQ VLAN trunking and policy based routing
    • Mikrotik Use Cases - PPPoE, ECMP, Failover, Recursive Routing and WireGuard
    • Mikrotik RouterOS Hardening for your home internet connection
  • 💀OffSec
    • Kali Linux with Vagrant for HTB
    • HTB: Lame Write-Up
    • HTB: Bank Write-Up
Powered by GitBook
On this page
  • Certificate Authority
  • Lab environment setup with LXD
  • Server-side setup
  • Client-side setup

Was this helpful?

  1. Linux

SSH certificate authentication

My increasing reliance on SSH key authentication has highlighted its scalability challenges. Although a substantial improvement over password authentication, the inherent difficulties in managing and distributing keys prevent quick and efficient scaling. Consequently, I've been researching more scalable SSH authentication solutions. This is how I came across SSH certificate authentication, and I'm particularly intrigued by it due to its numerous advantages.

Certificate Authority

For the Certificate Authority (CA), I will use my host machine so that I don't need to spin up another dedicated LXC container for CA functionality. Here is how I prepare my CA setup.

# Generate a ssh private/public key pair for CA
tyla@e32:~/ssh/ca$ sh-keygen -t rsa -f homelab_ssh_ca -C "Homelab SSH CA"
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in homelab_ssh_ca
Your public key has been saved in homelab_ssh_ca.pub
The key fingerprint is:
SHA256:UKnsJE3QJQPfrEe2+P6BVz9SNN1wIq3b3FGdIQ0hpk8 Homelab SSH CA
The key's randomart image is:
+---[RSA 3072]----+
|    o+o.o. o.=*.=|
|     .o*. o ..oB+|
|     +o.=. E .o +|
|    . =* .o .. o |
|     +o S  ..+...|
|      .o . ..oo .|
|        o o . o  |
|       . . . . . |
|        ...      |
+----[SHA256]-----+
tyla@e32:~/ssh/ca$ ll
total 16
drwxrwxr-x 2 tyla tyla 4096 May 25 21:18 ./
drwxr--r-- 3 tyla tyla 4096 May 25 12:51 ../
-rw------- 1 tyla tyla 2602 May 25 21:18 homelab_ssh_ca
-rw-r--r-- 1 tyla tyla  568 May 25 21:18 homelab_ssh_ca.pub
tyla@e32:~/ssh/ca$ cat homelab_ssh_ca.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCd1bStWHNLF5fJqNFxCwcsFv9NWXnhgA2tvkWIQHeVHe8b3Hen9710i8083sq/gwKXQJpQ4gywdDVjsRsn6QIZGZ6iqqSZ0sEHS4zRzFCzRqTq5iPQ7TvWLzPabXo/AYY8ia/QtXu9Wigq2ePMA76WykCkg4LCz0DaSfQ59BvAi5iupEbyUQul4FULyI9fb3zO2CuFDnCzKC+g0iXKWpYC30edsr3qAIQvO2VK+qPK7xictEEkjDAQX+FqlqWOuobz+qc/hfm7y1rH8nikCoZ9lbS3ZDiOEBxtJH8thukGFnwdF6jueol+skpiKWSPq7MpxJ3YvN1QoQGKV/vaeBIFEmUVl8wR8Qb6SSqq44OBqyju7Z4aaCn94sIXTEHjTzuFEj1eaOXinygYW3RiwF6HHmythVWac7qnkw0uXIOQPlqYqt6HrYjRtFTbuTXFf9srhO5cjben/lllqjMUZcQu/RRC/Wz8anGDPmk/t78bUo3qch6MTo9vPqXgAixFD58= Homelab SSH CA

Lab environment setup with LXD

Prior to outlining the configuration steps, there are two preparatory actions I'd like to take. The first is to launch three LXC containers, specifically named server1, server2, and client1. The second is to retrieve the IP addresses of these containers to facilitate DNS configuration via the /etc/hosts file.

  • Spin up server1, server2 and client1 LXC containers.

# Spin up 2 LXC containers for server1 and server2
tyla@e32:~$ for i in {1..2}; do lxc launch ubuntu:24.04 server$i; done
Launching server1
Launching server2

# Spin up a LXC container for client1
tyla@e32:~$ lxc launch ubuntu:24.04 client1
Launching client1

# Check the IP Addresses
tyla@e32:~$ lxc list 
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
|  NAME   |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| client1 | RUNNING | 10.18.34.46 (eth0)  | fd42:2751:df65:31e1:216:3eff:fea7:ec91 (eth0) | CONTAINER | 0         |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| server1 | RUNNING | 10.18.34.5 (eth0)   | fd42:2751:df65:31e1:216:3eff:fec6:b1ec (eth0) | CONTAINER | 0         |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| server2 | RUNNING | 10.18.34.232 (eth0) | fd42:2751:df65:31e1:216:3eff:fe4b:6237 (eth0) | CONTAINER | 0         |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+

# Update /etc/hosts file accordingly
tyla@e32:~$ sudo vi /etc/hosts
127.0.0.1       localhost
127.0.1.1       e32
10.18.34.5      server1 server1.home.lab
10.18.34.232    server2 server2.home.lab
10.18.34.46     client1 client1.home.lab

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# Verify if the DNS names work
tyla@e32:~$ ping server1.home.lab
PING server1 (10.18.34.5) 56(84) bytes of data.
64 bytes from server1 (10.18.34.5): icmp_seq=1 ttl=64 time=0.047 ms
^C
--- server1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.047/0.047/0.047/0.000 ms

tyla@e32:~$ ping server2.home.lab
PING server2 (10.18.34.232) 56(84) bytes of data.
64 bytes from server2 (10.18.34.232): icmp_seq=1 ttl=64 time=0.051 ms
^C
--- server2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.051/0.051/0.051/0.000 ms

tyla@e32:~$ ping client1.home.lab
PING client1 (10.18.34.46) 56(84) bytes of data.
64 bytes from client1 (10.18.34.46): icmp_seq=1 ttl=64 time=0.050 ms
^C
--- client1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.050/0.050/0.050/0.000 ms

Server-side setup

Here is how we configure server-side ssh setup.

  • Fetch the server1's /etc/ssh/ssh_host_rsa_key.pub

tyla@e32:~/ssh/ca$ scp ubuntu@server1:/etc/ssh/ssh_host_rsa_key.pub .
ssh_host_rsa_key.pub                                                    100%  566     1.1MB/s   00:00    
  • Sign the host public key with CA's private key.

tyla@e32:~/ssh/ca$ ssh-keygen -s homelab_ssh_ca -I server1 -V +52w -h -n server1.home.lab ssh_host_rsa_key.pub
Signed host key ssh_host_rsa_key-cert.pub: id "server1" serial 0 for server1.home.lab valid from 2025-05-25T21:22:00 to 2026-05-24T21:23:51
  • Move the signed host public key and CA public key back to server1's /etc/ssh/ directory, and configure ssh daemon.

tyla@e32:~/ssh/ca$ scp ssh_host_rsa_key-cert.pub ubuntu@server1:
ssh_host_rsa_key-cert.pub                                               100% 1855     4.8MB/s   00:00    
tyla@e32:~/ssh/ca$ scp homelab_ssh_ca.pub ubuntu@server1:
homelab_ssh_ca.pub                                                      100%  568     1.5MB/s   00:00 
tyla@e32:~/ssh/ca$ ssh ubuntu@server1
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 11:25:02 UTC 2025

  System load:           0.16
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           40.0 C
  Processes:             28
  Users logged in:       1
  IPv4 address for eth0: 10.18.34.5
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fec6:b1ec


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 11:19:56 2025 from 10.18.34.1
ubuntu@server1:~$ ll
total 14
drwxr-x--- 4 ubuntu ubuntu   11 May 25 11:25 ./
drwxr-xr-x 3 root   root      3 May 25 09:52 ../
-rw------- 1 ubuntu ubuntu  628 May 25 11:25 .bash_history
-rw-r--r-- 1 ubuntu ubuntu  220 Mar 31  2024 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu 3771 Mar 31  2024 .bashrc
drwx------ 2 ubuntu ubuntu    3 May 25 10:19 .cache/
-rw-r--r-- 1 ubuntu ubuntu  807 Mar 31  2024 .profile
drwx------ 2 ubuntu ubuntu    3 May 25 09:52 .ssh/
-rw-r--r-- 1 ubuntu ubuntu    0 May 25 10:26 .sudo_as_admin_successful
-rw-r--r-- 1 ubuntu ubuntu   96 May 25 11:13 homelab_ssh_ca.pub
-rw-r--r-- 1 ubuntu ubuntu 1855 May 25 11:25 ssh_host_rsa_key-cert.pub
-rw-r--r-- 1 ubuntu ubuntu  568 May 25 11:27 homelab_ssh_ca.pub
ubuntu@server1:~$ sudo mv *.pub /etc/ssh/
ubuntu@server1:~$ cd /etc/ssh/
ubuntu@server1:/etc/ssh$ ll
total 65
drwxr-xr-x   4 root   root       16 May 25 11:28 ./
drwxr-xr-x 104 root   root      196 May 25 10:58 ../
-rw-r--r--   1 ubuntu ubuntu    568 May 25 11:27 homelab_ssh_ca.pub
-rw-r--r--   1 root   root   620042 Apr 22 11:51 moduli
-rw-r--r--   1 root   root     1649 Apr 22 11:51 ssh_config
drwxr-xr-x   2 root   root        2 Apr 22 11:51 ssh_config.d/
-rw-------   1 root   root      505 May 25 09:52 ssh_host_ecdsa_key
-rw-r--r--   1 root   root      174 May 25 09:52 ssh_host_ecdsa_key.pub
-rw-------   1 root   root      399 May 25 09:52 ssh_host_ed25519_key
-rw-r--r--   1 root   root       94 May 25 09:52 ssh_host_ed25519_key.pub
-rw-------   1 root   root     2602 May 25 09:52 ssh_host_rsa_key
-rw-r--r--   1 ubuntu ubuntu   1855 May 25 11:25 ssh_host_rsa_key-cert.pub
-rw-r--r--   1 root   root      566 May 25 09:52 ssh_host_rsa_key.pub
-rw-r--r--   1 root   root      342 Dec  7  2020 ssh_import_id
-rw-r--r--   1 root   root     3349 May 25 11:14 sshd_config
drwxr-xr-x   2 root   root        3 May 16 12:54 sshd_config.d/
ubuntu@server1:/etc/ssh$ sudo chown root:root homelab_ssh_ca.pub
ubuntu@server1:/etc/ssh$ sudo chown root:root ssh_host_rsa_key-cert.pub
ubuntu@server1:/etc/ssh$ ll
total 65
drwxr-xr-x   4 root root     16 May 25 11:28 ./
drwxr-xr-x 104 root root    196 May 25 10:58 ../
-rw-r--r--   1 root root    568 May 25 11:27 homelab_ssh_ca.pub
-rw-r--r--   1 root root 620042 Apr 22 11:51 moduli
-rw-r--r--   1 root root   1649 Apr 22 11:51 ssh_config
drwxr-xr-x   2 root root      2 Apr 22 11:51 ssh_config.d/
-rw-------   1 root root    505 May 25 09:52 ssh_host_ecdsa_key
-rw-r--r--   1 root root    174 May 25 09:52 ssh_host_ecdsa_key.pub
-rw-------   1 root root    399 May 25 09:52 ssh_host_ed25519_key
-rw-r--r--   1 root root     94 May 25 09:52 ssh_host_ed25519_key.pub
-rw-------   1 root root   2602 May 25 09:52 ssh_host_rsa_key
-rw-r--r--   1 root root   1855 May 25 11:25 ssh_host_rsa_key-cert.pub
-rw-r--r--   1 root root    566 May 25 09:52 ssh_host_rsa_key.pub
-rw-r--r--   1 root root    342 Dec  7  2020 ssh_import_id
-rw-r--r--   1 root root   3349 May 25 11:14 sshd_config
drwxr-xr-x   2 root root      3 May 16 12:54 sshd_config.d/
ubuntu@server1:/etc/ssh$ sudo -i
root@server1:~# echo "HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub" >> /etc/ssh/sshd_config
root@server1:~# echo "TrustedUserCAKeys /etc/ssh/homelab_ssh_ca.pub" >> /etc/ssh/sshd_config
root@server1:~# cat /etc/ssh/sshd_config

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#	X11Forwarding no
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server

HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
TrustedUserCAKeys /etc/ssh/homelab_ssh_ca.pub
root@server1:~# systemctl restart ssh
root@server1:~# systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled)
     Active: active (running) since Sun 2025-05-25 11:36:47 UTC; 5s ago
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 1112 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 1114 (sshd)
      Tasks: 1 (limit: 38326)
     Memory: 1.2M (peak: 1.6M)
        CPU: 21ms
     CGroup: /system.slice/ssh.service
             └─1114 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

May 25 11:36:47 server1 systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
May 25 11:36:47 server1 sshd[1114]: Server listening on :: port 22.
May 25 11:36:47 server1 systemd[1]: Started ssh.service - OpenBSD Secure Shell server.
root@server1:~# vi /etc/hosts
127.0.0.1 localhost
10.18.34.5      server1 server1.home.lab
10.18.34.232    server2 server2.home.lab
10.18.34.46     client1 client1.home.lab

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
root@server1:~# 
logout
ubuntu@server1:/etc/ssh$ 
logout
Connection to server1 closed.

# Cleanup host public key from server1
tyla@e32:~/ssh/ca$ rm ssh_host*
  • Repeat the same configuration process on server2.

tyla@e32:~/ssh/ca$ scp ubuntu@server2:/etc/ssh/ssh_host_rsa_key.pub .
ssh_host_rsa_key.pub                                                    100%  566     1.0MB/s   00:00    
tyla@e32:~/ssh/ca$ ssh-keygen -s homelab_ssh_ca -I server2 -V +52w -h -n server2.home.lab ssh_host_rsa_key.pub
Signed host key ssh_host_rsa_key-cert.pub: id "server2" serial 0 for server2.home.lab valid from 2025-05-25T21:40:00 to 2026-05-24T21:40:59
tyla@e32:~/ssh/ca$ scp ssh_host_rsa_key-cert.pub ubuntu@server2:
ssh_host_rsa_key-cert.pub                                               100% 1855     5.2MB/s   00:00    
tyla@e32:~/ssh/ca$ scp homelab_ssh_ca.pub  ubuntu@server2:
homelab_ssh_ca.pub                                                      100%  568     1.9MB/s   00:00    
tyla@e32:~/ssh/ca$ ssh ubuntu@server2
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 11:42:37 UTC 2025

  System load:           1.03
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           38.0 C
  Processes:             22
  Users logged in:       0
  IPv4 address for eth0: 10.18.34.232
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fe4b:6237


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 10:53:27 2025 from 10.18.34.1
ubuntu@server2:~$ ll
total 15
drwxr-x--- 4 ubuntu ubuntu   11 May 25 11:42 ./
drwxr-xr-x 3 root   root      3 May 25 09:52 ../
-rw------- 1 ubuntu ubuntu  223 May 25 10:57 .bash_history
-rw-r--r-- 1 ubuntu ubuntu  220 Mar 31  2024 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu 3771 Mar 31  2024 .bashrc
drwx------ 2 ubuntu ubuntu    3 May 25 10:38 .cache/
-rw-r--r-- 1 ubuntu ubuntu  807 Mar 31  2024 .profile
drwx------ 2 ubuntu ubuntu    3 May 25 09:52 .ssh/
-rw-r--r-- 1 ubuntu ubuntu    0 May 25 10:39 .sudo_as_admin_successful
-rw-r--r-- 1 ubuntu ubuntu  568 May 25 11:42 homelab_ssh_ca.pub
-rw-r--r-- 1 ubuntu ubuntu 1855 May 25 11:42 ssh_host_rsa_key-cert.pub
ubuntu@server2:~$ sudo mv *.pub /etc/ssh/
ubuntu@server2:~$ cd /etc/ssh
ubuntu@server2:/etc/ssh$ ll
total 66
drwxr-xr-x   4 root   root       17 May 25 11:43 ./
drwxr-xr-x 104 root   root      196 May 25 10:57 ../
-rw-r--r--   1 ubuntu ubuntu    568 May 25 11:42 homelab_ssh_ca.pub
-rw-r--r--   1 root   root   620042 Apr 22 11:51 moduli
-rw-r--r--   1 root   root     1649 Apr 22 11:51 ssh_config
drwxr-xr-x   2 root   root        2 Apr 22 11:51 ssh_config.d/
-rw-------   1 root   root      505 May 25 09:52 ssh_host_ecdsa_key
-rw-r--r--   1 root   root      174 May 25 09:52 ssh_host_ecdsa_key.pub
-rw-------   1 root   root      399 May 25 09:52 ssh_host_ed25519_key
-rw-r--r--   1 root   root       94 May 25 09:52 ssh_host_ed25519_key.pub
-rw-------   1 root   root     2602 May 25 09:52 ssh_host_rsa_key
-rw-r--r--   1 ubuntu ubuntu   1855 May 25 11:42 ssh_host_rsa_key-cert.pub
-rw-r--r--   1 root   root      566 May 25 09:52 ssh_host_rsa_key.pub
-rw-r--r--   1 root   root      342 Dec  7  2020 ssh_import_id
-rw-r--r--   1 root   root     3310 May 25 10:47 sshd_config
drwxr-xr-x   2 root   root        3 May 16 12:54 sshd_config.d/
ubuntu@server2:/etc/ssh$ sudo chown root:root homelab_ssh_ca.pub
ubuntu@server2:/etc/ssh$ sudo chown root:root ssh_host_rsa_key-cert.pub
ubuntu@server2:/etc/ssh$ ll
total 66
drwxr-xr-x   4 root   root       17 May 25 11:43 ./
drwxr-xr-x 104 root   root      196 May 25 10:57 ../
-rw-r--r--   1 root   root      568 May 25 11:42 homelab_ssh_ca.pub
-rw-r--r--   1 root   root   620042 Apr 22 11:51 moduli
-rw-r--r--   1 root   root     1649 Apr 22 11:51 ssh_config
drwxr-xr-x   2 root   root        2 Apr 22 11:51 ssh_config.d/
-rw-------   1 root   root      505 May 25 09:52 ssh_host_ecdsa_key
-rw-r--r--   1 root   root      174 May 25 09:52 ssh_host_ecdsa_key.pub
-rw-------   1 root   root      399 May 25 09:52 ssh_host_ed25519_key
-rw-r--r--   1 root   root       94 May 25 09:52 ssh_host_ed25519_key.pub
-rw-------   1 root   root     2602 May 25 09:52 ssh_host_rsa_key
-rw-r--r--   1 root   root     1855 May 25 11:42 ssh_host_rsa_key-cert.pub
-rw-r--r--   1 root   root      566 May 25 09:52 ssh_host_rsa_key.pub
-rw-r--r--   1 root   root      342 Dec  7  2020 ssh_import_id
-rw-r--r--   1 root   root     3310 May 25 10:47 sshd_config
drwxr-xr-x   2 root   root        3 May 16 12:54 sshd_config.d/
ubuntu@server2:/etc/ssh$ sudo -i
root@server2:~# echo "HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub" >> /etc/ssh/sshd_config
root@server2:~# echo "TrustedUserCAKeys /etc/ssh/homelab_ssh_ca.pub" >> /etc/ssh/sshd_config
root@server2:~# cat /etc/ssh/sshd_config

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#	X11Forwarding no
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server

HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
TrustedUserCAKeys /etc/ssh/homelab_ssh_ca.pub
root@server2:~# systemctl restart ssh
root@server2:~# systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled)
     Active: active (running) since Sun 2025-05-25 11:51:22 UTC; 3s ago
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 814 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 816 (sshd)
      Tasks: 1 (limit: 38326)
     Memory: 1.2M (peak: 1.5M)
        CPU: 22ms
     CGroup: /system.slice/ssh.service
             └─816 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

May 25 11:51:22 server2 systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
May 25 11:51:22 server2 sshd[816]: Server listening on :: port 22.
May 25 11:51:22 server2 systemd[1]: Started ssh.service - OpenBSD Secure Shell server.
root@server2:~# vi /etc/hosts
127.0.0.1 localhost
10.18.34.5      server1 server1.home.lab
10.18.34.232    server2 server2.home.lab
10.18.34.46     client1 client1.home.lab

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

# Cleanup host public key from server2
tyla@e32:~/ssh/ca$ rm ssh_host*

Client-side setup

Here is how the client-side configured.

  • Generate RSA key pair on client1 and sign its public key with CA private key, then moved the signed public key back to the client1.

tyla@e32:~/ssh/ca$ ssh ubuntu@client1
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 11:54:49 UTC 2025

  System load:           0.88
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           41.0 C
  Processes:             22
  Users logged in:       0
  IPv4 address for eth0: 10.18.34.46
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fea7:ec91


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 11:17:19 2025 from 10.18.34.1
ubuntu@client1:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/ubuntu/.ssh/id_rsa
Your public key has been saved in /home/ubuntu/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:y46bZgUA0tE+ISoOVDTOT/k1NAI8di5rMngpNsDn2wk ubuntu@client1
The key's randomart image is:
+---[RSA 3072]----+
|..=B.... o       |
| o= =+..o .      |
|o. =.=+  o       |
|=. .=.o.. .      |
|= + .oooS        |
| * E o ...       |
|. + B ..o        |
|   . oo+         |
|     o+..        |
+----[SHA256]-----+
ubuntu@client1:~$ 
logout
Connection to client1 closed.
tyla@e32:~/ssh/ca$ scp ubuntu@client1:.ssh/id_rsa.pub .
id_rsa.pub                                                              100%  568     1.3MB/s   00:00    
tyla@e32:~/ssh/ca$ ll
total 20
drwxrwxr-x 2 tyla tyla 4096 May 25 21:57 ./
drwxr--r-- 3 tyla tyla 4096 May 25 12:51 ../
-rw------- 1 tyla tyla 2602 May 25 21:18 homelab_ssh_ca
-rw-r--r-- 1 tyla tyla  568 May 25 21:18 homelab_ssh_ca.pub
-rw-r--r-- 1 tyla tyla  568 May 25 21:57 id_rsa.pub
tyla@e32:~/ssh/ca$ ssh-keygen -s homelab_ssh_ca -I client1 -n ubuntu -V +52w id_rsa.pub
Signed user key id_rsa-cert.pub: id "client1" serial 0 for ubuntu valid from 2025-05-25T22:00:00 to 2026-05-24T22:01:24
tyla@e32:~/ssh/ca$ ll
total 24
drwxrwxr-x 2 tyla tyla 4096 May 25 22:01 ./
drwxr--r-- 3 tyla tyla 4096 May 25 12:51 ../
-rw------- 1 tyla tyla 2602 May 25 21:18 homelab_ssh_ca
-rw-r--r-- 1 tyla tyla  568 May 25 21:18 homelab_ssh_ca.pub
-rw-r--r-- 1 tyla tyla 2017 May 25 22:01 id_rsa-cert.pub
-rw-r--r-- 1 tyla tyla  568 May 25 21:57 id_rsa.pub
tyla@e32:~/ssh/ca$ scp id_rsa-cert.pub ubuntu@client1:.ssh/
id_rsa-cert.pub                                                         100% 2017     5.4MB/s   00:00    
  • Create /etc/ssh/ssh_known_hosts file with CA public key for Trust On First Use (TOFU) identity verification process.

@cert-authority *.home.lab ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCd1bStWHNLF5fJqNFxCwcsFv9NWXnhgA2tvkWIQHeVHe8b3Hen9710i8083sq/gwKXQJpQ4gywdDVjsRsn6QIZGZ6iqqSZ0sEHS4zRzFCzRqTq5iPQ7TvWLzPabXo/AYY8ia/QtXu9Wigq2ePMA76WykCkg4LCz0DaSfQ59BvAi5iupEbyUQul4FULyI9fb3zO2CuFDnCzKC+g0iXKWpYC30edsr3qAIQvO2VK+qPK7xictEEkjDAQX+FqlqWOuobz+qc/hfm7y1rH8nikCoZ9lbS3ZDiOEBxtJH8thukGFnwdF6jueol+skpiKWSPq7MpxJ3YvN1QoQGKV/vaeBIFEmUVl8wR8Qb6SSqq44OBqyju7Z4aaCn94sIXTEHjTzuFEj1eaOXinygYW3RiwF6HHmythVWac7qnkw0uXIOQPlqYqt6HrYjRtFTbuTXFf9srhO5cjben/lllqjMUZcQu/RRC/Wz8anGDPmk/t78bUo3qch6MTo9vPqXgAixFD58= Homelab SSH CA
  • Verify the ssh certification authentication from client1 to server1 and server2.

tyla@e32:~/ssh/ca$ ssh ubuntu@client1
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 12:03:25 UTC 2025

  System load:           0.22
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           38.0 C
  Processes:             22
  Users logged in:       0
  IPv4 address for eth0: 10.18.34.46
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fea7:ec91


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 11:54:50 2025 from 10.18.34.1

# Verify server1 login from client1
ubuntu@client1:~$ ssh ubuntu@server1.home.lab
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 12:03:43 UTC 2025

  System load:           0.17
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           40.0 C
  Processes:             22
  Users logged in:       0
  IPv4 address for eth0: 10.18.34.5
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fec6:b1ec


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 11:36:37 2025 from 10.18.34.1
ubuntu@server1:~$ 
logout
Connection to server1.home.lab closed.


# Verify server2 login from client1
ubuntu@client1:~$ ssh ubuntu@server2.home.lab
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 12:04:37 UTC 2025

  System load:           0.36
  Usage of /:            2.8% of 17.60GB
  Memory usage:          0%
  Swap usage:            0%
  Temperature:           38.0 C
  Processes:             22
  Users logged in:       0
  IPv4 address for eth0: 10.18.34.232
  IPv6 address for eth0: fd42:2751:df65:31e1:216:3eff:fe4b:6237


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Sun May 25 11:43:07 2025 from 10.18.34.1
ubuntu@server2:~$ 

In summary, while the initial setup of an SSH certificate authority may require some effort, the long-term benefits in terms of simplified management, enhanced security, and improved scalability make SSH certificate authentication a worthwhile investment for any organisation or individual managing multiple SSH connections.

PreviousITmatic101 - Tech BlogNextSSH key authentication for LDAP login

Last updated 3 days ago

Was this helpful?

🧙‍♂️
Page cover image