Phone:
 +947 601 49595
Email:
 mail[at]pasindudissan.xyz
Secondary Email:
 pasindudissan[at]proton.me

PGP key (Ed22519)
3300 B645 19CA C101 A0DD
D030 E40F 4B15 095C C7AF

© 2025 Pasindu Dissanayaka.

Posted by:

Pasindu Dissanayaka

Category:

Posted on:

Mar 23, 2015

Strengthening SSH Security: Certificate-Based Authentication (mTLS) for SSH

Introduction

Unlike regular SSH keys, certificate-based authentication signs a user’s public key using a CA key. Then servers are told to trust this CA. Clients authenticate with short-lived certificates.

  • Servers do not need to know each individual key β€” only the CA.

  • When access needs to be revoked, you invalidate the cert or CA, not each key.

This is scalable, secure, and automatable β€” like mTLS, but for SSH. Hence making it a very versatile tool for securely managing multiple Linux servers organisation across a large Ops Team.

What you need:
  • An SSH Certificate Authority (A CA server or admin machine to sign certificates)
  • A set of client key pairs (Your Ops Team can generate their own)
  • Access to your servers that run OpenSSH 6.2+ (To implement the CA Validation)

πŸ”₯ Pro Tip: Start by self-hosting an open-source solution like Smallstep CA, it offers a secure, scalable foundation for managing both SSH and x.509 certificates from day one.

Step 1: Create the SSH CA Key

On your admin machine:

ssh-keygen -f /etc/ssh/ca_companyname_key -t ed25519 -C "SSH User CA"

This gives you:

  • /etc/ssh/ca_companyname_key (CA private key)

  • /etc/ssh/ca_companyname_key.pub (CA public key - to share with servers)

Step 2: Trust the CA on All Servers

Copy the CA public key (ca_companyname_key.pub) to each server and configure:

Edit /etc/ssh/sshd_config:

TrustedUserCAKeys /etc/ssh/ca_companyname_key.pub

Then reload SSH:

sudo systemctl reload sshd

πŸ” All SSH user certs signed by this CA will now be trusted on that server.

Step 3: Create User Key Pair on Client

On the user/client machine generate a key pair for the client (this can be done by your team member):

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "user@domain"

This generates:

~/.ssh/id_ed25519 (their private key)

~/.ssh/id_ed25519.pub (their public key)

Step 4: Sign the User Key with the CA

On the CA/admin machine use the client's public key to generate a certificate:

ssh-keygen -s /etc/ssh/ca_companyname_key \
-I user-cert \
-n username \
-V +52w \
~/.ssh/id_ed25519.pub

Explanation:

-s: CA private key used to sign

-I: certificate identity

-n: valid principals (team member's username on server)

-V: validity (e.g., +52w = 1 year)

As you guessed it this creates ~/.ssh/id_ed25519-cert.pub

Step 5: SSH With the Certificate

You can now share the signed certificate with your team member:

~/.ssh/
β”œβ”€β”€ id_ed25519
β”œβ”€β”€ id_ed25519-cert.pub

And they can use SSH as usual:

ssh -i ~/.ssh/id_ed25519 user@server

SSH will automatically use the corresponding -cert.pub file.

Server Hardening

Now that your team is using the certificates to login, you can modify all server's SSH configs To require certificate-based authentication only (no raw keys), disable public key auth:

In /etc/ssh/sshd_config:

PubkeyAuthentication yes
AuthenticationMethods publickey
AuthorizedKeysFile none
...
PermitRootLogin prohibit-password
PasswordAuthentication no

Restart SSH:

sudo systemctl reload sshd