SSL/TLS certificates for websites and servers are just one component of a Chain of Trust, a fundamental concept to ensure the security and data integrity of online communications. It involves various elements, including certificate authorities, public and private keys, and digital signatures, to establish and verify the legitimacy of secure connections.

All certificates are backed by a Certificate Authority and optional intermediary certificates as well.

Creating a self-signed certificate guarantees encryption of the communication, but it does not protect against MITM (Man-In-The-Middle) attacks.

By generating a Certificate Authority certificate and key, then installing the CA cert on all devices in a network, the Chain of Trust is completed.


LOCAL CHAIN OF TRUST

openssl genpkey -algorithm RSA -out local-ca.key
chmod 400 local-ca.key
openssl req -new -x509 -key local-ca.key -out local-ca.crt

Create a CSR (Certificate Signing Request) for a FQDN or Hostname (e.g. domain.local):

openssl req -new -key local-ca.key -out domain.local.csr

Create the signed certificate for the CSR with the CA key:

openssl x509 -req -in domain.local.csr -signkey local-ca.key -out domain.local.crt

For the FQDN / Hostname certificate to be trusted, the CA certificate must be installed on all hosts in the local network.

Add the CA certificate on Ubuntu/Debian:

cat /etc/ssl/certs/ca-certificates.crt | grep BEGIN | wc -l
sudo mv local-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
cat /etc/ssl/certs/ca-certificates.crt | grep BEGIN | wc -l

Add the CA certificate on RHEL/CentOS:

cat /etc/ssl/certs/ca-certificates.crt | grep BEGIN | wc -l
sudo mv local-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
cat /etc/ssl/certs/ca-certificates.crt | grep BEGIN | wc -l

Note: The first and last commands count how many CA certificates are already installed. The number should increase after the update.

The curl command and other applications should now trust certificates issued by that CA.


CHAIN OF TRUST FOR PURCHASED CERTIFICATE

Some certificate vendors require that the full chain of trust be provided to work correctly:

  • Purchased Certificate
    • domain.com.crt
    • domain.com.key
  • CA Certificate
    • CA.crt

Virtual Host configuration on Apache (or any other web server):

SSLCertificateFile /etc/ssl/certs/domain.com.crt
SSLCertificateKeyFile /etc/ssl/private/domain.com.key

Add the CA certificate on Ubuntu/Debian:

sudo mv CA.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

Add the CA certificate on RHEL/CentOS:

sudo mv CA.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust

CHAIN OF TRUST WITH BUNDLE CERTIFICATE

To serve the same domain over the internet without issues for remote clients that do not have the CA certificate installed:

SSLCertificateFile /etc/ssl/certs/domain.com.crt
SSLCertificateKeyFile /etc/ssl/private/domain.com.key
SSLCACertificateFile /etc/ssl/ca/CA.crt

Optionally, both .crt files can be combined into one:

cat /etc/ssl/certs/domain.com.crt > /etc/ssl/certs/bundle_domain.com.crt
cat /etc/ssl/ca/CA.crt >> /etc/ssl/certs/bundle_domain.com.crt

This bundle certificate provides clients with everything they need to verify the purchased certificate.


LAZY LOCALHOST SELF-SIGNED

sudo apt install libnss3-tools mkcert -y
sudo mkcert --install

BONUS

On Debian-based systems, this command will wipe and re-add all CA certificates:

sudo update-ca-certificates --fresh

If needed, clear all cached certificates:

sudo rm -rf /etc/ssl/certs/*
sudo update-ca-certificates

SEE ALSO

A post about LIGHTtpd with Self-signed Cert [Link].