Skip to content

Instantly share code, notes, and snippets.

@olokelo
Last active October 4, 2024 10:05
Show Gist options
  • Save olokelo/abd2040091893f2ff3167972a328a550 to your computer and use it in GitHub Desktop.
Save olokelo/abd2040091893f2ff3167972a328a550 to your computer and use it in GitHub Desktop.

My Video

https://youtu.be/8DWcMbgQSZg or https://video.hardlimit.com/w/6oSkB4tL1KbuqoxgDistqR

Prerequisites

(shown in the video but not described here)

  • have a Linux server
  • forward ports 80 and 443 of your Linux Server on your Router
  • install Docker
  • install Nginx Proxy Manager as a container
  • set up and enable your host in Nginx Proxy Manager
  • install GnuTLS certtool ( apt install gnutls-bin )

Creating root CA certificate

$ mkdir certs/
$ cd certs/

Generate root CA key

$ openssl ecparam -genkey -name secp256r1 | openssl ec -out ca.key

Create root CA certificate using generated key, will be valid for 10 years. It does not matter what you type in as an input.

$ openssl req -new -x509 -days 3650 -key ca.key -out ca.pem

Creating client certificates and bundles

Variables

  • client name - unique name for your client (ex. Smartphone)
  • client serial - unique client ID number (ex. 01), increment it with each client creation
  • challenge password - password used when importing the client certificate, can't be longer than 20 bytes

Generate client key

$ openssl ecparam -genkey -name secp256r1 | openssl ec -out <client name>.key

Create client Certificate Signing Request (CSR)

$ openssl req -new -key <client name>.key -o <client name>.csr

When asked:

  • Keep common name the same as <client name>.
  • Provide a <challenge password>.
  • Leave the optional company name empty.

Generate client Certificate by signing client CSR with CA root. It will be valid for one year.

$ openssl x509 -req -days 365 -in <client name>.csr -CA ca.pem -CAkey ca.key -set_serial <client serial> -out <client name>.crt

Export p12 bundle

$ certtool --load-privkey <client name>.key --load-certificate <client name>.crt --load-ca-certificate ca.pem --to-p12 --outder --outfile <client name>.p12 --p12-name "<client name>" --hash SHA1 --pkcs-cipher 3dec-pkcs12 --password <challenge password>

Repeat that for each client you want to create incrementing <client serial> by one.

Changing Nginx Proxy Manager configuration

Variables

  • ca path - path to mounted ca.pem file in your container.

Mount certs/ca.pem in your Nginx Proxy Manager container under <ca path>.

In the web interface navigate to your Proxied Host, click Edit, then Advanced.

In Custom Nginx Configuration add:

ssl_client_certificate <ca path>;
ssl_verify_client on;

Make sure you have Force SSL option enabled for your Host.

And save.

That's it :)

References and Resources

@9dc
Copy link

9dc commented Sep 15, 2024

$ openssl req -new -key <client name>.key -out <client name>.csr
is the correct cmd, at least
$ openssl req -new -key <client name>.key -o <client name>.csr
did not work for me.
thanks for the guide!

@olokelo
Copy link
Author

olokelo commented Sep 15, 2024

@9dc not sure why, the docs do have -out option however your comment may help someone who encounters similar issue.

Thank you for using my guide and I hope you'll have good experience with mTLS :)

@skyboard89
Copy link

Just want to leave this here as I was having password not accepted issues with apple aswell.

The Apple Keychain uses LibreSSL and it cannot read the certificate even with the correct password due to the default crypto method employed by OpenSSL. The -legacy flag creates the PK12 certificate using the previous crypto methods and thus creates a PK12 certificate that is readable with LibreSSL and thus the Apple Keychain.

Credit to James Brickley: https://discussions.apple.com/thread/254518218?sortBy=rank

That worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment