项目作者: ervinne13

项目描述 :
A docker project that sets up an NGINX server protected by 2-way SSL Verification (Mutual Authentication)
高级语言: Dockerfile
项目地址: git://github.com/ervinne13/mutual-authentication-protected-server.git


Mutual Authentication Protected Server

Proof of concept of implementing 2-way SSL Verification in NGINX (thus in any tech stack) demonstrated by using docker.
The dockerfile installs php and sets up a simple php server.

Mutual Authentication Visualized

Ongoing research and development to implement trust stores

Background

We’re trying to set up a secure way to create connections between servers. One way is to adapt Mutual Authentication similar to what J2EE servers do, but this time, implement it into something more generic that can support different platforms since NuWorks has PHP and NodeJS based applications. This is useful if you want to limit the users of a service and all the users are known in advanced.

Ongoing research and development effort for using this method in mobile applications so we can limit the users of APIs meant for use for mobile apps only.

Proof of Concept Setup Instructions

After cloning, create a .env file based on the .env.example and fill in volume_path (which will likely contain the current folder where you placed this repository locally), and the ip you want it accessible (let’s say for ex. 192.168.13.1)

Create image, container, and run it with:

  1. docker-compose build
  2. docker-compose up -d

Testing / Proof of Concept

Test without using a certificate (Should Fail)

Try accessing via cUrl

  1. curl --insecure https://192.168.13.1

This should result in an error message:
400 Bad Request
No required SSL certificate was sent

Note that we use —insecure since we’re only using a self signed certificate in our server’s SSL. This is fine as long as it’s only accessed internally by the organization. Just make sure to secure the generated ca.key file.

Test without using a certificate that’s not signed by the server’s CA (Should Fail)

Generate a certificate

  1. openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  2. -subj "/C=PH/ST=NCR/L=Pasig/O=NuWorks Interactive Labs Inc./OU=Tech Dept./CN=Unsigned Cert" \
  3. -keyout unsigned-cert.key -out unsigned-cert.crt

Try accessing via cUrl

  1. curl --insecure --cert ./unsigned-cert.crt --key ./unsigned-cert.key https://192.168.13.1

This should result in an error message:
400 Bad Request
No required SSL certificate was sent

Test without using a certificate that’s signed by the CA (Should be successful)

For demonstration purposes, this dockerfile is set to generate a signed certificate using the server’s CA (Certificate Authority). It’s located at /root/certs/client/

Copy the file via scp if this is in a real server with scp support

  1. scp root@192.168.13.1:/root/certs/client/client.crt .
  2. scp root@192.168.13.1:/root/certs/client/client.key .

Or if in docker, just manually copy the files to outside the container by copying it the directory you set using volume_path to expose the files.

Test the connection using cUrl

  1. curl --insecure --cert ./client.crt --key ./client.key https://192.168.13.1

Or create a pem file and use the combined certificate and key using

  1. cat client.crt client.key > client.pem
  2. curl --insecure --cert ./client.pem https://192.168.13.1

Both method should now work and output the response of this repository’s index.php file.

Actual implementation Details (As seen in the dockerfile)

Now that we’ve proven Mutual Authentication using NGINX, let’s explore how it’s actually done.

Generating your own Certificate Authority

A certificate authority (literally like Commodo CA) is a certificate that signs and validates other certificates.

We’ll have to create one on the server. For better readability, let’s create first an openssl.cnf file for our CA with the following contents:

  1. [ req ]
  2. prompt = no
  3. default_md = sha1
  4. distinguished_name = req_distinguished_name
  5. [ req_distinguished_name ]
  6. C = PH
  7. ST = NCR
  8. L = Pasig City
  9. O = NuWorks Interactive Labs Inc.
  10. OU = TechDept
  11. CN = TechDept CA
  12. [ certauth ]
  13. basicConstraints = CA:true
  14. subjectKeyIdentifier = hash
  15. authorityKeyIdentifier = keyid:always,issuer:always

certauth is an extension in openssl we can use for creating a custom certificate authority certificate.
In the terminal, we generate both the key and the certificate with:

  1. openssl req -config /root/certs/root-ca/openssl.cnf -newkey rsa:2048 -nodes -keyform PEM \
  2. -keyout /root/certs/root-ca/ca.key -x509 -days 3650 \
  3. -extensions certauth -outform PEM -out /root/certs/root-ca/ca.crt

Note that you could also password protect the ca.key with -passout.

Generating and signing a client certificate to be given to authorized servers / clients

Create another openssl.cnf in the client machine or in another folder. This time, it’s for creating client certificates.

  1. [ req ]
  2. prompt = no
  3. default_md = sha1
  4. distinguished_name = req_distinguished_name
  5. [ req_distinguished_name ]
  6. C = PH
  7. ST = NCR
  8. L = Pasig City
  9. O = NuWorks Interactive Labs Inc.
  10. OU = TechDept
  11. CN = Client System
  12. [ client ]
  13. basicConstraints = critical,CA:FALSE
  14. keyUsage = digitalSignature, keyEncipherment, dataEncipherment
  15. extendedKeyUsage = clientAuth

Then generate the request to create a certificate and its key in the terminal with:

  1. openssl genrsa -out /root/certs/client/client.key 2048
  2. openssl req -config /root/certs/client/openssl.cnf -new \
  3. -key /root/certs/client/client.key -out /root/certs/client/client.req

Keep the client.key file safe. Send/copy the client.req file to the server with the certificate authority so it can be signed and a certificate can be created. In the example below, it’s copied in the folder /root/certs/client

In the server, sign the request with:

  1. openssl x509 -req -in /root/certs/client/client.req \
  2. -CA /root/certs/root-ca/ca.crt -CAkey /root/certs/root-ca/ca.key \
  3. -extfile /root/certs/client/openssl.cnf -extensions client -days 365 -outform PEM \
  4. -out /root/certs/client/client.crt -CAcreateserial -CAserial /root/certs/client/serial.seq

Once the client.crt is generated, give it back to the client server/machine.

With both the crt and key files, you may now try connections to the server as demonstrated in the proof of concept.

Other Notes

You don’t have to sign the crt and key file of the actual server. This should be done by certificate authorities (like Commodo CA) and not the CA’s you create.

Changing the CA automatically revokes the certificates of all the clients. They will have to create requests and have you sign them again.

This can also be done directly in Apache should you wish to do so. You will just have to set the following on the apache server:
SSLCACertificateFile SSLVerifyClient SSLVerifyDepth