Changelog
mTLS requires clients to present a client certificate to authenticate usage. The mTLS flow goes roughly like:
Authentication is facilitated by PKI. The subset of cases where this may be undesirable includes:
Where this is desirable includes:
Assuming the basic web configuration has already been setup, together with certificates. Then the main changes are:
server { ssl_client_certificate <PATH_TO_CA_CERT>; ssl_verify_client optional; if ($ssl_client_verify != SUCCESS) { ... # reject clients } ... }
If no special behaviour based on the validity of the client certificate is required (processed based on the return code of $ssl_client_verify
), then ssl_verify_client
can be set to "on", and the response will be a simple 400 Bad Request.
Note the ssl_trusted_certificate
directive is mainly for OSCP stapling, not for hiding the list of accepted client certificates from the client. Using this in tandem with ssl_verify_client
without ssl_client_certificate
raises a configuration error.
Consider the following additional considerations:
stream
to route TCP packets to the backend, and poke a hole in the firewall.bind
option to the "listen" directives.# Create CA user:~$ easyrsa init-pki # configure vars, e.g. for ECC user:~$ easyrsa build-ca # Create client certificate user:~$ easyrsa gen-req <MY_CLIENT> user:~$ easyrsa --san=DNS:<MY_DOMAIN> sign-req client <MY_CLIENT> # Verify client certificate, e.g. extended key usage of Client Authentication and SAN user:~$ cat pki/issued/<MY_CLIENT>.crt # Package into p12 bundle (set export password if desired) # Note there is no real need to generate the full chain user:~$ openssl pkcs12 -export \ -in pki/issued/<MY_CLIENT>.crt \ -inkey pki/private/<MY_CLIENT>.key \ -out pki/private/<MY_CLIENT>.p12
Generally per usual for Linux/Windows.
For iOS devices, the .p12 file needs to be created using the -legacy
flag in OpenSSL 3, and then either:
So many hurdles to leap through... *internal screaming* Even then, the client certificate is added only to Apple's keychain, so these certificates cannot be used in other browsers unless those apps support client cert importing mechanisms, see answer. *more internal screaming*