staticshin

Client side and proxy_ssl certificates in nginx

Client side certificates allow the server to authenticate the source of the request. The client sends along it's certificate with a request for the connection to be established. If everything checks out the server allows further communication. If it does not the requests from the client are not entertained.

One of the most important use cases of client side certificates is in creation of mutual authentication systems. Where both client and the server authenticate each other. As opposed to the server side certificates, in which the client determines the identity of the server, certain applications, especially the ones where the load of distribution of certificates is low and security is of prime importance, this method provides a very natural way of establishing trust between a client and server.

To use the client side certificate it becomes the responsibility of the client (while establishing a connection) to read the certificate file and send it to the server with the connection request. And while it's fairly easy to do, you can delegate this responsibility of handling the certificate to a proxy so that the client talks to a proxy and the proxy talks to the server.

This allows you to build applications where you are managing multiple client connections to a mutual authentication system with just one client certificate. The proxy authenticates a client and the server authenticates a proxy. Once you introduce a proxy you can also distribute the certificate level client authentication. That is, there can be multiple proxys just for managing the client connecting to a server.

In business terms this translates into a scenario where you are a trusted associate with the ability to use services and resources of an organization and you want to be able to distribute these services to your own clients. Now the source organization will only be dealing with you and you'll be dealing with your clients.

Nginx can not only serve requests of the client but also act as a proxy to other servers (hence the name reverse proxy server) Nginx's directives allow you to configure both server side and client side certificates. In this post we'll see how to use nginx for proxy ssl certificates as well as for client side certificates. But first let's define the upsteam and downstream terminology as used in nginx so that there's no confusion when we use these terms.

"Upstream and downstream describe the flow of a message: all messages flow from upstream to downstream."

This means that when nginx is used as a normal server (serving the requests of a client) the request is downstream and response is upstream. Similarly when nginx acts as a proxy it acts as a client and it's request becomes downstream where as the response from the proxied server becomes upstream.

It becomes important to understand this message flow becomes when we talk about server side and client side certificates:-

Server side certificate: By server side certificate we mean that the downstream , that is the requests coming in to nginx from the client is to an authenticated source. In other words the client establishes the authenticity of the server.

Client side certificate: By client side certificate, we mean that the upstream , that is the response going out of nginx is to an authenticated source. In other words the server establishes the authenticity of the client.

Proxy certificates are used when the client's request, instead of hitting the server directly, goes via nginx. In that case the client does not need to provide any certificate to the server directly. The proxy handles the responsibility of establishing the identity of the client to the server. The server for all intents and purposes treats the proxy as a known client, where as the proxy takes care of the responsibility of handling the identity verification of the clients conneting to it upon itself.

The proxy certificates are handled by the directives in the ngx_http_proxy module. In configuration files this translates into a couple of lines of code.

	      
#edit this with your own cert
proxy_ssl_certificate ./certs/cert.pem;
## edit this with your own key
proxy_ssl_certificate_key ./keys/key_wrinq.pem;
	      
	    

Simillarly the client side certificates are configured by the ssl_client_certificate in the ngx_http_module

	      
#edit this with your own ca cert
ssl_client_certificate ./keys/ca.crt;
	      
	    

To verify a client certificate all you need to do is point the ssl_client_certificate directive to the location of your CA (Certificate authority) certificate that you used to sign the certificates for your clients. You can create a CA on your own server using openssl . With a CA cert and a certificate signing request (CSR) you can sign the certificates for your clients. A couple of lines of openssl can create signed certificates for your clients. Here's the code for reference:-

              
## Create a CA certificate
openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

## Create a CSR (certificate signing request)
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr

# Sign the client certificate with our CA cert.  
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
	      
            

Once a certificate has been created you can distribute these to the client. It then becomes the responsibility of the client to send this certificate while establishing a connection. Our server which is also the CA in this case verifies the genuineness of the certificate by ensuring the validity of the digital signature. Once that is done a connection is established.

Any Questions?

.... wait a minute let me put on my glasses

Yes,Questions?

"What is a CA?

CA stands for certificate authority. A CA is responsible for issuing digital certificates. A client trusts the CA implicitly and relies upon the fact the CA's signature on the certificate proves the authenticity of the certificate holder. If a client goes on the website www.bank.com and the certificate sent by the server contains the signature of a trusted CA (this trust is verified by the public key of the CA) then the client can be certain of the fact the certificate is valid and that he is indeed talking to the server of wwww.bank.com .

"So how do the client side certificates work?"

Essentially the purpose of client side certificates is authentication of the client by the server. The client sends it's certificate to the server. The server checks whether the client certificate is valid. If it is, the connection is established for future requests and if not the request for connection is denied. As the use case of client side certificates is limited to scenarios where we can control the distribution of certificates, eg restful services to be used primarily by non browser clients,we can make our server the CA and create our own digitally signed certificate.

In plain english:-

  1. Client obtains a digitally signed certificate from the server
  2. Client sends it's certificate at the time of establishing a request.
  3. The server verifies the signature and hence the validity of the certificate and proceeds further

Now all of this may just be a couple of lines of openssl magic but it does fulfill our long time fantasy of owning a Certificate Authority one day,does it not? The fruit of patience is sweet :-)

"Is there any benefit in letting nginx handle the certificates?"

Yes. For one ssl handling in nginx is extremely optimized. It's fast and light. And second it's easy. All you got to do is add few directives and you are set. Furthermore the proxy_ssl_certificate directive allows you to play with concept of client side certificate in novel ways. You are able to design architectures that can reuse a single client certificate across a variety of clients allowing you to combine traditional authentication methods with certificate based identity management.

"What is your favorite animal?"

Ahh.. hard to pick. I really like cows. They are so milky... and they can chew all day long. I've tried chewing gums a couple of times but strain in my jaw becomes unbearable after about 3 hours. I have to rely on a liquid diet for the rest of the day to restore myself. A man's got to know his limitations, I suppose?

[ Digital ocean has a great guide on what it takes to create SSL certificates along with an explanation of some of the technical terms used.]

-Akshat Jiwan Sharma


comments powered by Disqus