AuthN / authZ
Client certificate authentication
Client certificate authentication means that the client sends an X.509 certificate when they connect over TLS. The load balancer verifies the client’s identity based on the certificate. Typically, client certificates are digitally signed with your organization’s CA certificate. When a client presents one, you can verify whether it was indeed signed by your CA. If not, deny the request. You would give a unique certificate to each client to which you want to grant access.
Create a Certificate Authority Jump to heading
Creating a client certificate that’s signed by your organization’s self-signed CA (Certificate Authority) is deemed secure in this scenario, as opposed to procuring one from an external CA. Your organization acts as the Certificate Authority, authenticating these certificates when they are presented through HTTPS requests by clients.
Creating a Certificate Authority involves generating a CA key pair, creating a self-signed CA certificate, and configuring the CA to sign other certificates. You can accomplish it all with a single openssl
command.
-
Generate a CA key pair and self-signed certificate:
nixopenssl req \-newkey rsa:2048 \-nodes \-x509 \-days 3650 \-keyout privateCA.pem \-out ca.crtnixopenssl req \-newkey rsa:2048 \-nodes \-x509 \-days 3650 \-keyout privateCA.pem \-out ca.crtLearn more about this command
The options of this command break down as follows:
openssl req
creates and processes certificate signing requests (CSRs) and certificates.-newkey rsa:2048
specifies the generation of a new RSA key pair with a key size of 2048 bits.-nodes
indicates that the private key should not be encrypted with a passphrase and will be saved in an unencrypted format.-x509
tells OpenSSL to generate a self-signed certificate instead of a CSR.-days 3650
specifies the validity period of the certificate as 3650 days (approximately 10 years).-keyout
designates the file name ofprivateCA.pem
for the private key.-out ca.crt
sets the certificate.
The command will also prompt you to enter information for the certificate, such as the Common Name (CN), organization details, and so on. Fill in the required fields accordingly.
nixYou are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [AU]:State or Province Name (full name) [Some-State]:Locality Name (eg, city) []:Organization Name (eg, company) [Internet Widgits Pty Ltd]:Organizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:Email Address []:nixYou are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [AU]:State or Province Name (full name) [Some-State]:Locality Name (eg, city) []:Organization Name (eg, company) [Internet Widgits Pty Ltd]:Organizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:Email Address []: -
To display the details of the CA certificate and verify its information, use the
openssl x509
command:nixopenssl x509 -in ca.crt -text -nooutnixopenssl x509 -in ca.crt -text -nooutAfter following these steps, you should have the self-signed certificate
ca.crt
. Remember to adjust the file names and paths according to your specific setup. Keep the CA keyprivateCA.pem
secret.
Create a client certificate Jump to heading
A client certificate is a type of digital certificate used to verify the identity of a user or device trying to access server resources.
To create a client certificate:
-
Create a certificate signing request with the following command, replacing the
-subj
values with the name and organization of the user or device:nixopenssl req \-newkey rsa:2048 \-nodes \-days 3650 \-subj "/CN=exampleUser/O=exampleOrganization" \-keyout clientKey.pem \-out client.csrnixopenssl req \-newkey rsa:2048 \-nodes \-days 3650 \-subj "/CN=exampleUser/O=exampleOrganization" \-keyout clientKey.pem \-out client.csr -
Create a certificate extensions file named
client-cert-extensions.cnf
, which sets extensions fields likebasicConstraints
to prevent the certificate from acting as a CA andkeyUsage
to indicate the purpose of the certificate. Add the following values:client-cert-extensions.cnftextbasicConstraints = CA:FALSEkeyUsage = digitalSignatureextendedKeyUsage = clientAuthsubjectKeyIdentifier = hashauthorityKeyIdentifier = keyid,issuerclient-cert-extensions.cnftextbasicConstraints = CA:FALSEkeyUsage = digitalSignatureextendedKeyUsage = clientAuthsubjectKeyIdentifier = hashauthorityKeyIdentifier = keyid,issuer -
Use the following command to sign the certificate signing request. This uses our previously generated CSR
client.csr
, CA certificateca.crt
, and CA keyprivateCA.pem
to create a client certificate,client.crt
.nixopenssl x509 \-req \-in client.csr \-out client.crt \-CA ca.crt \-CAkey privateCA.pem \-CAcreateserial \-days 3650 \-extfile client-cert-extensions.cnfnixopenssl x509 \-req \-in client.csr \-out client.crt \-CA ca.crt \-CAkey privateCA.pem \-CAcreateserial \-days 3650 \-extfile client-cert-extensions.cnfSuccessful confirmation output will look something like this, with an ‘OK’ statement above your Common Name and Organization:
outputtextCertificate request self-signature oksubject=CN = exampleUser, O = exampleOrganizationoutputtextCertificate request self-signature oksubject=CN = exampleUser, O = exampleOrganizationYour client certificate is now ready to use.
-
To display the details of the client certificate and verify its information, use the
openssl x509
command:nixopenssl x509 -in client.crt -text -nooutnixopenssl x509 -in client.crt -text -noout
Verify client certificates Jump to heading
In your load balancer configuration, enable verification of client certificates by setting verify
to required
on a bind
line. The ca-file
parameter specifies the CA file to use to verify:
haproxy
frontend wwwbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt
haproxy
frontend wwwbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt
Note that the certificate provided by the client must contain both the public certificate and its associated private key.
Send a client certificate to servers Jump to heading
The load balancer can also send its own client certificate to backend servers. The servers would then be responsible for verifying it.
-
In the
backend
, add thecrt
argument to theserver
directive. Thecrt
parameter points to your load balancer’s client certificate file:haproxybackend webserversserver web1 10.0.0.5:443 ssl crt /certs/load-balancer-client.crthaproxybackend webserversserver web1 10.0.0.5:443 ssl crt /certs/load-balancer-client.crt
Certificate Revocation Lists Jump to heading
A Certificate Revocation List (CRL) contains a list of the certificates that have been revoked.
Create a CRL Jump to heading
To create a CRL:
-
Create the directory structure and necessary files. You can choose different directory paths, however ensure all created files are in the proper locations:
nixmkdir -p ./databaseCA/certs ./databaseCA/private ./databaseCA/crltouch ./databaseCA/index.txt ./databaseCA/serial ./databaseCA/crlnumberecho 01 > ./databaseCA/serialecho 1000 > ./databaseCA/crlnumbernixmkdir -p ./databaseCA/certs ./databaseCA/private ./databaseCA/crltouch ./databaseCA/index.txt ./databaseCA/serial ./databaseCA/crlnumberecho 01 > ./databaseCA/serialecho 1000 > ./databaseCA/crlnumber -
Copy your CA certificate and private key into the
databaseCA
directory.nixcp ca.crt ./databaseCAcp privateCA.pem ./databaseCAnixcp ca.crt ./databaseCAcp privateCA.pem ./databaseCA -
You’ll need a configuration file for OpenSSL. An example file named
openssl.cnf
can usually be found in the directories/usr/lib/ssl/
or/etc/ssl/
. Copy this to the current directory. Below is an example snippet from the file, modified for the certificates we created:openssl.cnfini# OpenSSL example configuration file.# See doc/man5/config.pod for more info.####################################################################[ ca ]default_ca = CA_default # The default ca section####################################################################[ CA_default ]dir = ./databaseCA # Where everything is keptcerts = $dir/certs # Where the issued certs are keptcrl_dir = $dir/crl # Where the issued crl are keptdatabase = $dir/index.txt # database index file.new_certs_dir = $dir/newcerts # default place for new certs.certificate = $dir/ca.crt # The CA certificateserial = $dir/serial # The current serial numbercrlnumber = $dir/crlnumber # the current crl numbercrl = $dir/crl.pem # The current CRLprivate_key = $dir/privateCA.pem # The private keyx509_extensions = usr_cert # The extensions to add to the certcrl_extensions = crl_extdefault_days = 3650 # how long to certify fordefault_crl_days = 30 # how long before next CRLdefault_md = sha256 # use SHA-256 by defaultpreserve = no # keep passed DN ordering[ crl_ext ]authorityKeyIdentifier=keyid:alwaysopenssl.cnfini# OpenSSL example configuration file.# See doc/man5/config.pod for more info.####################################################################[ ca ]default_ca = CA_default # The default ca section####################################################################[ CA_default ]dir = ./databaseCA # Where everything is keptcerts = $dir/certs # Where the issued certs are keptcrl_dir = $dir/crl # Where the issued crl are keptdatabase = $dir/index.txt # database index file.new_certs_dir = $dir/newcerts # default place for new certs.certificate = $dir/ca.crt # The CA certificateserial = $dir/serial # The current serial numbercrlnumber = $dir/crlnumber # the current crl numbercrl = $dir/crl.pem # The current CRLprivate_key = $dir/privateCA.pem # The private keyx509_extensions = usr_cert # The extensions to add to the certcrl_extensions = crl_extdefault_days = 3650 # how long to certify fordefault_crl_days = 30 # how long before next CRLdefault_md = sha256 # use SHA-256 by defaultpreserve = no # keep passed DN ordering[ crl_ext ]authorityKeyIdentifier=keyid:alwaysThe above is just the
CA_default
portion of a default OpenSSL configuration, not the entireopenssl.cnf
file.In this configuration,
./databaseCA
is the directory where OpenSSL will store its database of certificates,./privateCA.pem
is the CA’s private key, and./ca.crt
is the CA’s certificate.- Ensure the directory and file paths match your environment, which we created in Step 1.
- Consult the openssl ca documentation for a complete list of configuration options.
-
Generate the file
revoked.crl
, which will contain the list of revoked certificates:nixsudo openssl ca -config openssl.cnf -gencrl -out /certs/revoked.crlnixsudo openssl ca -config openssl.cnf -gencrl -out /certs/revoked.crlYou can create a CRL file even before a certificate has been revoked; the revocation list will be empty inside the CRL.
Configure the load balancer Jump to heading
By using Certificate Revocation Lists, you can revoke client certificates in your load balancer environment. Revoked certificates will be denied access based on your configured CRL file.
Here is an example snippet in which we add the crl-file
argument to deny access to clients who have revoked certificates:
haproxy
frontend wwwmode httpbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt crl-file /certs/revoked.crl
haproxy
frontend wwwmode httpbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt crl-file /certs/revoked.crl
Revoke a certificate Jump to heading
To revoke a client certificate:
-
Invoke the
openssl ca
command with the-revoke
argument:nixsudo openssl ca -config openssl.cnf -revoke client.crtnixsudo openssl ca -config openssl.cnf -revoke client.crtThis will immediately revoke the certificate
client.crt
as confirmed by the output:outputtextUsing configuration from openssl.cnfRevoking Certificate 01.Data Base UpdatedoutputtextUsing configuration from openssl.cnfRevoking Certificate 01.Data Base Updated -
Update the CRL file:
nixsudo openssl ca -config openssl.cnf -gencrl -out /certs/revoked.crlnixsudo openssl ca -config openssl.cnf -gencrl -out /certs/revoked.crl -
Reload the load balancer configuration.
Show error pages for certificate errors Jump to heading
By utilizing the configuration options below, you can show users an error page based on a certificate error.
-
Configure HTML pages on your load balancer, for example
certexpired.html
andcertrevoked.html
pages.- The file
/certexpired.html
could present a dedicated page to users whose certificate has expired, providing guidance on how to renew or request a new certificate. - Those with revoked certificates could be directed to the dedicated page
/certrevoked.html
.
- The file
-
Edit your load balancer configuration to include
http-request return
directives. Also, add thecrt-ignore-err
argument to thebind
line so that errors don’t immediately close the connection, allowing you to return a web page instead:haproxyfrontend wwwmode httpbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt crl-file /certs/revoked.crl crt-ignore-err 10,23http-request return status 403 content-type text/html file /certexpired.html if { ssl_c_verify 10 }http-request return status 403 content-type text/html file /certrevoked.html if { ssl_c_verify 23 }haproxyfrontend wwwmode httpbind :443 ssl crt /certs/site.pem verify required ca-file /certs/ca.crt crl-file /certs/revoked.crl crt-ignore-err 10,23http-request return status 403 content-type text/html file /certexpired.html if { ssl_c_verify 10 }http-request return status 403 content-type text/html file /certrevoked.html if { ssl_c_verify 23 } -
Reload the load balancer configuration.
See also Jump to heading
Do you have any suggestions on how we can improve the content of this page?