How to Create Private SSL Certificate Authority

You usually need to purchase SSL certificate from companies for your public websites that you host. However, it is not necessary to purchase SSL certificates if the websites (any HTTP based service) are privately hosted never exposed to the outside world. You can be your own Certificate Authority.

SSL Certificate Generation Flow

Here is the diagram that shows the SSL certificate generation flow.

Why HTTPS (SSL) Internally?

Here are some reasons I can think of.

  • Malicious attacks can come from internal engineers not just from outside.
  • Dev/test/staging environments are better to be tested mirroring the production environment as much as possible.
  • It is easier to promote the dev/test/staging environments to production by mirroring the production environment meaning less moving parts between different environments.
  • It has been more of a trend in the network security world that encryption must be done from end to end.

How to Create CA Root Certificate

CA stands for Certificate Authority. You can be a small Certificate Authority. Here are the steps.

  • Open terminal. (I use Linux Mint as my Linux machine but other distribution should be OK too.)
  • Create a directory.
    mkdir CA
  • Navigate to the directory.
    cd CA
  • Generate the private key for your CA. Usually 2048 will suffice but we will use 4096 in this example to make it stronger.
    openssl genrsa -des3 -out CA.key 4096
  • Enter pass phrase when prompted. You can choose whatever you want but do not forget it because you will use it later.
  • You now have CA.key (private key) file in ~/CA directory.
  • Out of the private key, we will create the root certificate using the command below.
    openssl req -x509 -new -nodes -key CA.key -sha256 -days 3650 -out CA.pem
  • You will be prompted to enter some information about your root certificate.
    Country Name (2 letter code) [AU]:US
    State or Province Name (full name) [Some-State]:WA
    Locality Name (eg, city) []:Seattle
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hayato Iriumi
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:hayato-iriumi.net
    mail Address []:hiriumi@gmail.com
  • Now you have the root certificate CA.pem under ~/CA directory.

Download CA Root Certificate

If you have the certificate on a remote machine, you need to download it to a client machine to install it. Follow the steps below.

  • Open your terminal on a client machine.
  • Navigate to the directory where you want to download the CA.pem file.
  • Use scp to download the CA.pem file.
    scp amaterasu48@linux-mint:~/CA/CA.pem .

How to Install Root Certificate (on client side)

  • If you are on macOS, you can execute the command to trust the root certificate.
    sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" CA.pem
  • Please refer to this document to install root certificate on Windows.

Create SSL Certificate Request

Now we need to generate CA key signed certificate for your web servers but first, we need to generate CSR (Certificate Signing Request). Please follow the steps below.

  • Create another private key. Replace linux-mint.local with whatever the web server you want to enable SSL for.
    openssl genrsa -out linux-mint.local.key 4096
  • Now generate the CSR file (linux-mint.local.csr).
    openssl req -new -key linux-mint.local.key -out linux-mint.local.csr
  • Enter information when prompted.
    Country Name (2 letter code) []:US
    State or Province Name (full name) []:WA
    Locality Name (eg, city) []:Covington
    Organization Name (eg, company) []:Hayato Iriumi
    Organizational Unit Name (eg, section) []:dev
    Common Name (eg, fully qualified host name) []:linux-mint.local
    Email Address []:hiriumi@gmail.com
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:YourPassword

Create SSL Certificate

We will need CA private key, CA certificate and CSR file to generate an SSL certificate. Please follow the steps below.

  • Upload the CSR file from the host where you created it to the CA.
    scp yourdomain.csr yourusername@yourhostname:~/CA
  • There are CA.key, CA.pem and linux-mint.local.csr in ~/CA directory on the host where CA key was generated.
  • Create linux-mint.local.ext file for configuration with the following content on the remote host at ~/CA.
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = linux-mint.local
  • At this point, I have CA.key, CA.pem, linux-mint.local.csr and linux-mint.local.ext.
  • Execute the following command.
    openssl x509 -req -in linux-mint.local.csr -CA CA.pem -CAkey CA.key -CAcreateserial -out linux-mint.local.crt -days 365 -sha256 -extfile linux-mint.local.ext
  • It has generated linux-mint.local.crt which will be used in your web server.

Implementing SSL Certificate on Web Server

There are many types of web servers. I will pick one of the most popular NGINX as an example to implement the SSL certificate that was generated in this process. Obviously, the prerequisite is that you already have NGINX up and running. There are a lot of documents out there on how to install and run NGINX.

Before you implement the SSL certficate, make sure the port 443 is open to your web server. (ufw for Debian descendent distros and firewall-cmd for RedHat descendent distros).

  • Create a directory /etc/nginx/conf.d/ssl
    sudo mkdir /etc/nginx/conf.d/ssl
  • Copy linux-mint.local.key (the original private key that generated the CSR file) and linux-mint.local.crt (the SSL certificate file generated in the previous section) to /etc/nginx/conf.d/ssl on your NGINX server.
  • Create file /etc/nginx/conf.d/ssl.conf with the following content. The first server block allows NGINX to redirect the traffic that comes to the port 80 to port 443 (HTTPS). The second server block actually takes care of the SSL part.
    server {
    listen 80;
    server_name linux-mint.local;
    return 301 https://linux-mint.local;
    }
    server {
    listen 443 ssl;
    server_name linux-mint.local;
    ssl_certificate /etc/nginx/conf.d/ssl/linux-mint.local.crt;
    ssl_certificate_key /etc/nginx/conf.d/ssl/linux-mint.local.key;
    }
  • Restart NGINX.
    sudo systemctl restart nginx

Accessing the SSL Enabled Web Server

Back on your client machine, make sure you can resolve whatever the address can resolve to the IP address. I will talk through my case in my private environment.

  • Edit your /etc/hosts (or C:\Windows\System32\drivers\etc\hosts on Windows) and add an entry in the file just to simulate DNS server. You can alternatively have your internal DNS server but I will omit it. The following line means if the machine tries to access linux-mint.local, it skips the whole DNS query but just resolves it to 192.168.1.22 which is the IP address of the NGINX I already setup.
    192.168.1.22 linux-mint.local
  • Open your browser and enter linux-mint.local and hit enter.
  • Now you can see the website if protected by SSL. If you click on the key icon, you get to see the certificate you created.

Recap

In this blog article, I’ve explained how to create your own CA certificate to protect internal HTTP traffic for free.

Author: admin

A software engineer in greater Seattle area

Leave a Reply

Your email address will not be published. Required fields are marked *