331.2 - X.509 Certificates for Encryption, Signing and Authentication
Key Knowledge Areas:
- Understand SSL, TLS, including protocol versions and ciphers
- Configure Apache HTTPD with mod_ssl to provide HTTPS service, including SNI and HSTS
- Configure Apache HTTPD with mod_ssl to serve certificate chains and adjust the cipher configuration (no cipher-specific knowledge)
- Configure Apache HTTPD with mod_ssl to authenticate users using certificates
- Configure Apache HTTPD with mod_ssl to provide OCSP stapling
- Use OpenSSL for SSL/TLS client and server tests
Partial list of the used files, terms and utilities:
- httpd.conf
- mod_ssl
- openssl (including relevant subcommands)
Files
httpd.conf
httpd.conf is the main configuration file for the Apache HTTP Server
Utilities
mod_ssl
mod_ssl is a module for the Apache HTTP Server that provides SSL v3 and TLS v1.x support
HTTPS
LoadModule ssl_module modules/mod_ssl.so
Listen 443
<VirtualHost _default_:443>
SSLEngine on
SSLCertificateFile "/usr/local/apache2/conf/server.crt"
SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
#SSLCertificateChainFile "/usr/local/apache2/conf/server-ca.crt"
#SSLCACertificatePath "/usr/local/apache2/conf/ssl.crt"
#SSLCACertificateFile "/usr/local/apache2/conf/ssl.crt/ca-bundle.crt"
#SSLCARevocationPath "/usr/local/apache2/conf/ssl.crl"
#SSLCARevocationFile "/usr/local/apache2/conf/ssl.crl/ca-bundle.crl"
#SSLCARevocationCheck chain
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/apache2/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
SNI
From the wiki:
# Listen for virtual host requests on all IP addresses
NameVirtualHost *:443
# Go ahead and accept connections for these vhosts
# from non-SNI clients
SSLStrictSNIVHostCheck off
<VirtualHost *:443>
# Because this virtual host is defined first, it will
# be used as the default if the hostname is not received
# in the SSL handshake, e.g. if the browser doesn't support
# SNI.
DocumentRoot /www/example1
ServerName www.example.net
# Other directives here
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /www/example2
ServerName www.example2.org
# Other directives here
</VirtualHost>
HSTS
HTTP Strict Transport Security is configured by defining a header:
LoadModule headers_module modules/mod_headers.so
<VirtualHost _default_:443>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</VirtualHost>
certificate chain
SSLCertificateChainFile: One file containing the issuing CA for the server’s certificate and can range up to the root CA.
SSLCertificateChainFile "/usr/local/apache2/conf/server-ca.crt"
Note: From version 2.4.8 onwards the chain can alternatively be defined through the SSLCertificateFile directive, where a single file would contain the chain sorted from leaf to root.
cipher configuration
SSLHonorCipherOrder on
# be liberal in general
SSLCipherSuite ALL:!aNULL:RC4+RSA:+HIGH:+MEDIUM:+LOW:+EXP:+eNULL
<Location "/strong/area">
# but https://hostname/strong/area/ and below
# requires strong ciphers
SSLCipherSuite HIGH:!aNULL:!MD5
</Location>
authenticate users using certificates (mutual TLS)
Authenticating clients using certificates is commonly called mutual TLS.
secure a particular route with certificate authentication, but allow unauthenticated access to the rest:
SSLVerifyClient none
SSLCACertificateFile "conf/ssl.crt/ca.crt"
<Location "/secure/area">
SSLVerifyClient require
SSLVerifyDepth 1
</Location>
match clients which are part of a common hierarchy which is encoded into the DN:
SSLVerifyClient none
SSLCACertificateFile "conf/ssl.crt/ca.crt"
SSLCACertificatePath "conf/ssl.crt"
<Directory "/usr/local/apache2/htdocs/secure/area">
SSLVerifyClient require
SSLVerifyDepth 5
SSLOptions +FakeBasicAuth
SSLRequireSSL
SSLRequire %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"}
</Directory>
OCSP stapling
Online Certificate Status Protocol (OCSP) describes a mechanism that reports the current revocation status of certificates. It can be used instead of a Certificate Revocation List (CRL). This is beneficial for clients because they no longer need to download the full CRL, but can instead directly query the validity of a single entry. For the certificate authorities (CA) that provide OCSP this adds significant load. To mitigate the load from OCSP queries to an extent, the OCSP results can be cached by the server and provided to the client (OCSP stapling). This reduces load on the CA and saves the client a request to the CA.
minimal configuration:
# global scope
SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
recommended production use:
# Do not pass OCSP responder errors to clients:
SSLStaplingReturnResponderErrors off
# Reduce the OCSP responder timeout from the default 10s:
SSLStaplingResponderTimeout 4
# Cache valid OCSP responses for 48 hours (default: 1 hour).
# This reduces load on OCSP responders and avoids transient
# errors caused by frequent queries:
SSLStaplingStandardCacheTimeout 172800
# Retry failed OCSP queries after 60 seconds instead of the
# default 600s:
SSLStaplingErrorCacheTimeout 60
openssl
client test
Use OpenSSL s_server to set up a SSL/TLS server to which clients can connect.
Example IPv4 server on port 8443, without a server certificate::
openssl s_server -4 -nocert -port 8443
Client response:
$ openssl s_client -connect 127.0.0.1:8443
Connecting to 127.0.0.1
CONNECTED(00000003)
402740D2CA7F0000:error:0A000410:SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure:ssl/record/rec_layer_s3.c:914:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 302 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Example server on port 8443, with a status response on HTTP GET requests:
openssl s_server -cert leaf.crt -cert_chain chain.crt -key leaf.key -port 8443 -www
Client response:
$ curl -k https://127.0.0.1:8443/
<HTML><BODY BGCOLOR="#ffffff">
<pre>
s_server -cert leaf.crt -cert_chain chain.crt -key leaf.key -port 8443 -www
This TLS version forbids renegotiation.
Ciphers supported in s_server binary
TLSv1.3 :TLS_AES_256_GCM_SHA384 TLSv1.3 :TLS_CHACHA20_POLY1305_SHA256
TLSv1.3 :TLS_AES_128_GCM_SHA256 TLSv1.3 :TLS_AES_128_CCM_SHA256
TLSv1.2 :ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 :ECDHE-RSA-AES256-GCM-SHA384
TLSv1.2 :ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 :ECDHE-RSA-CHACHA20-POLY1305
TLSv1.2 :ECDHE-ECDSA-AES256-CCM TLSv1.2 :ECDHE-ECDSA-AES128-GCM-SHA256
TLSv1.2 :ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 :ECDHE-ECDSA-AES128-CCM
TLSv1.2 :ECDHE-ECDSA-AES128-SHA256 TLSv1.2 :ECDHE-RSA-AES128-SHA256
TLSv1.0 :ECDHE-ECDSA-AES256-SHA TLSv1.0 :ECDHE-RSA-AES256-SHA
TLSv1.0 :ECDHE-ECDSA-AES128-SHA TLSv1.0 :ECDHE-RSA-AES128-SHA
TLSv1.2 :AES256-GCM-SHA384 TLSv1.2 :AES256-CCM
TLSv1.2 :AES128-GCM-SHA256 TLSv1.2 :AES128-CCM
TLSv1.2 :AES256-SHA256 TLSv1.2 :AES128-SHA256
SSLv3 :AES256-SHA SSLv3 :AES128-SHA
TLSv1.2 :DHE-RSA-AES256-GCM-SHA384 TLSv1.2 :DHE-RSA-CHACHA20-POLY1305
TLSv1.2 :DHE-RSA-AES256-CCM TLSv1.2 :DHE-RSA-AES128-GCM-SHA256
TLSv1.2 :DHE-RSA-AES128-CCM TLSv1.2 :DHE-RSA-AES256-SHA256
TLSv1.2 :DHE-RSA-AES128-SHA256 SSLv3 :DHE-RSA-AES256-SHA
SSLv3 :DHE-RSA-AES128-SHA TLSv1.2 :PSK-AES256-GCM-SHA384
TLSv1.2 :PSK-CHACHA20-POLY1305 TLSv1.2 :PSK-AES256-CCM
TLSv1.2 :PSK-AES128-GCM-SHA256 TLSv1.2 :PSK-AES128-CCM
SSLv3 :PSK-AES256-CBC-SHA TLSv1.0 :PSK-AES128-CBC-SHA256
SSLv3 :PSK-AES128-CBC-SHA TLSv1.2 :DHE-PSK-AES256-GCM-SHA384
TLSv1.2 :DHE-PSK-CHACHA20-POLY1305 TLSv1.2 :DHE-PSK-AES256-CCM
TLSv1.2 :DHE-PSK-AES128-GCM-SHA256 TLSv1.2 :DHE-PSK-AES128-CCM
SSLv3 :DHE-PSK-AES256-CBC-SHA TLSv1.0 :DHE-PSK-AES128-CBC-SHA256
SSLv3 :DHE-PSK-AES128-CBC-SHA TLSv1.2 :ECDHE-PSK-CHACHA20-POLY1305
TLSv1.0 :ECDHE-PSK-AES256-CBC-SHA TLSv1.0 :ECDHE-PSK-AES128-CBC-SHA256
TLSv1.0 :ECDHE-PSK-AES128-CBC-SHA TLSv1.2 :RSA-PSK-AES256-GCM-SHA384
TLSv1.2 :RSA-PSK-CHACHA20-POLY1305 TLSv1.2 :RSA-PSK-AES128-GCM-SHA256
SSLv3 :RSA-PSK-AES256-CBC-SHA TLSv1.0 :RSA-PSK-AES128-CBC-SHA256
SSLv3 :RSA-PSK-AES128-CBC-SHA
---
Ciphers common between both SSL end points:
TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256
TLS_AES_128_CCM_SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-CCM
ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-CCM
ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA
ECDHE-RSA-AES256-SHA ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES128-SHA
AES256-GCM-SHA384 AES256-CCM AES128-GCM-SHA256
AES128-CCM AES256-SHA256 AES128-SHA256
AES256-SHA AES128-SHA DHE-RSA-AES256-GCM-SHA384
DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-CCM DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES128-CCM DHE-RSA-AES256-SHA256 DHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA
Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Supported groups: x25519:secp256r1:x448:secp521r1:secp384r1:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192
Shared groups: x25519:secp256r1:x448:secp521r1:secp384r1:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 8575D2B03276B807ABD391B0F9FF5051734519FB57E737E6F5EE6202B27CD948
Session-ID-ctx: 01000000
Resumption PSK: EC8544258DC9310B44C5E3EB054955C04F3C5B4730FFED57B080120E53F07203A34C7A60E3D6E7DF067A51907070A911
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1778279645
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
0 items in the session cache
0 client connects (SSL_connect())
0 client renegotiates (SSL_connect())
0 client connects that finished
3 server accepts (SSL_accept())
0 server renegotiates (SSL_accept())
2 server accepts that finished
0 session cache hits
0 session cache misses
0 session cache timeouts
0 callback cache hits
0 cache full overflows (128 allowed)
---
no client certificate available
</pre></BODY></HTML>
server test
Use OpenSSL s_client to test client connections to SSL/TLS servers. There are options for protocol, client certificate, server certificate verification, network characteristics, etc.
Example:
openssl s_client -connect imaps.example.net:993
Note: Add -debug argument to print message payloads.
Notes
SNI
Server Name Indication (SNI) is a Transport Layer Security (TLS) extension which provides virtual hosting capability to HTTPS connections. During the initial handshake the client communicates the virtual domain it desires to reach through the Client Hello message. This data allows the host to select the matching certificate, usually out of a pool of certificates, and use that to complete the TLS handshake. A privacy flaw in this setup is that the virtual domain of otherwise encrypted HTTPS traffic can be learned by inspecting the plain text handshake packets.
ECH
Encrypted Client Hello (ECH) is a TLS 1.3 extension which encrypts the Client Hello message using a public key that has been distributed to the web browser beforehand. By encrypting the Client Hello message its contents are inaccessible for monitoring in transit.
HSTS
HTTP Strict Transport Security (HSTS) is a policy mechanism that informs the web browser that a host is to be reached through HTTPS for the given period. The web browser persists this requirement and updates any HTTP requests to HTTPS before submitting them, for the given period.