Basic SSL Setup - server and client SSL certificate setup
Install nginx on the instance. We would also probably need to install vim as well to make it changes on nginx configuration.
sudo apt update && sudo apt install -y nginx vim
sudo su
mkdir -p /etc/nginx/ssl
cd /etc/nginx/ssl
Create the following file in ca.config
. The following ca configuration is used to create and configure SSL certifications
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
copy_extensions = copy
[req]
distinguished_name = req_distinguished_name
x509_extensions = server_cert
req_extensions = server_cert
[req_distinguished_name]
commonName = commonname
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
#authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alternate_names
[ alternate_names ]
DNS.1 = localhost
DNS.2 = lol.testtest.com
Refer to documentation for more details:
https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
Another useful documentation:
https://www.openssl.org/docs/man3.0/man5/x509v3_config.html
This link pertains to the various portions for the x509 v3 certificate options available for use. It tells what are the various options in there, and what it is for etc.
openssl genrsa -out ca.key 2048
openssl rsa -in ca.key -pubout > ca.pub
# Certificate "request" but produces a self signed cert instead
openssl req -x509 -config ca.config -new -nodes -key ca.key -sha256 -days 365 -out ca.pem -extensions v3_ca
Create server SSL certificate
openssl genrsa -out dev.app.key.server 2048
# Certificate "request"
# In order to make it easier - use *.example.com for common name
openssl req -new -key dev.app.key.server -out dev.app.csr
openssl x509 -req -in dev.app.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out dev.app.crt.server -days 365 -sha256 -extfile ca.config -extensions server_cert
cp dev.app.crt.server dev.app.crt
cat ca.pem >> dev.app.crt
cp dev.app.key.server dev.key.crt
cat ca.key >> dev.key.crt
With that, edit nginx accordingly to allow ssl traffic on the following file /etc/nginx/sites-available/default
. Ensure one of the blog have https port, 443 be allowed with ssl and to have the ssl certificate and ssl certificate that we created used here
server {
listen 443 ssl default_server;
ssl_certificate /etc/nginx/ssl/dev.app.crt;
ssl_certificate_key /etc/nginx/ssl/dev.key.crt;
...
}
We can go into another VM instance on Google Compute Engine and try to curl it to the server instance. Copy over the ca.pem
over from the server. Google Cloud instances
curl --cacert ca.pem https://instance-1
We would get the following error
curl: (60) SSL: no alternative certificate subject name matches target host name 'instance-1'
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Note from above that only 2 domains is acceptable: localhost
and lol.testtest.com
. Add ip address of the server with the lol.testtest.com
domain to the /etc/hosts
file.
We can then use curl on domains specified in the SSL Cert - lol.testtest.com
to obtain the response accordingly.
curl --cacert ca.pem https://lol.testtest.com
Create client SSL certificate request. We need to pass the certificate request to the instance that has the ca certificate to sign it
openssl genpkey -algorithm RSA -out client.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -key client.key -out client.req -subj /CN=testtest
Sign it and put it back to the caller instance
openssl x509 -req -in client.req -CA ca.pem -CAkey ca.key -set_serial 101 -extensions client -days 365 -sha256 -outform PEM -out client.crt
openssl x509 -in client.crt -noout -text
Adjust nginx configuration - /etc/nginx/nginx.conf
http {
map $ssl_client_s_dn $allowed {
default no;
"CN=testtest" yes;
}
...
Adjust the following nginx configuration - /etc/nginx/sites-available/default
server {
...
listen 443 ssl default_server;
ssl_certificate /etc/nginx/ssl/dev.app.crt;
ssl_certificate_key /etc/nginx/ssl/dev.key.crt;
ssl_verify_client on;
ssl_client_certificate /etc/nginx/ssl/ca.pem;
if ($allowed = "no") {
return 403;
}
...
We can run curl request
curl --cacert ca.pem https://lol.testtest.com
But we would receive the following response though
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.14.2</center>
</body>
</html>
We would need to pass the client ssl certificates
curl --cacert ca.pem --cert client.crt --key client.key https://lol.testtest.com
Additional Information
- If we simply wish to setup SSL cert in nginx without needed client authentication - we would just need to need to copy the “root”
ca.pem
and copy it into/usr/local/share/ca-certificates
. Ensure that the file ends with.crt
. We can do so by copying (assuming we’re in the folder where we created all the certs… -mv ca.pem /usr/local/share/ca-certificates/ca.crt
). - The next step would be to restore and update the ca-stores. This is done by running the following:
sudo update-ca-certificates
. Although, this would only affect on OS level. Browsers still require an update to their respective ca-stores.