End To End Encryption Between Nginx Aspnetcore Kestrel Angular

Internet is moving toward secure connections whereby HTTPS is a priority. Browsers are now warning users when navigating to non secured website. With this movement, Kestrel and ASPNET Core have adopted the mentality of security by default rather than security when needed. HTTPS will now be the default and HTTP will be a necessity due to implementation constraints. Together with Lets Encrypt and ACME protocol, we do not have excuses for not implementing an SSL connection.

When we run this application, we can access http://localhost:5000.
Next we configure our localhost proxy with nginx. We create localhost file in /etc/nginx/sites-available/ where we proxy localhost calls to localhost:5000.

Now when we navigate to http://localhost, we should have our call proxied to http://localhost:5000. So far we have the following:

Browser --(http)--> nginx --(http)--> kestrel

So far none of our connection is secured.

2. SSL self signed certificate for Nginx

The first communication is over internet therefore in order to keep the confidentiality of the commumication we can configure.

Here we will be creating a self signed certification which means that the certificate is issued and signed by ourselves instead of being issues by a trusted certificate authority. The difference is that our certificate will not be trusted by default in the browser.

If you need a SSL certificate signed by a trusted CA, you can install SSL nginx using Certbot but you would need to have a valid domain.

Now when we navigate to https://localhost, our communication is encrypted using the SSL cert we created and then proxied as http://localhost:5000.

So far we have the following:

Browser --(https)--> nginx --(http)--> kestrel

3. SSL self signed certificate for Kestrel

Now that we have secured the connection to nginx, we can secure the connection to Kestrel.

Since nginx and kestrel are both on localhost in our example (as we are developing locally), we can use the same certificate which we created as it is bound to the localhost common name.

We start by combining .crt and .key into a .pfx file to be used by Kestrel. A .pfx file is a file packagine the private and public certificate into a file protected by a password. It adds a protection in the event of the key failling under the wrong hands.

Next we add the HTTPS configuration on the WebHostBuilder. We copied localhost.pfx to the root of the project therefore we can reference it using the name only but it could be placed anywhere, UseHttps accepts a path.

Now when we navigate to https://localhost5001, our connection will be secured when directly interacting with Kestrel. Since Nginx proxies calls to Kestrel, we need to have Nginx verify whether the SSL certificate delivered by Kestrel is valid. We can do that by using the directives proxy_ssl_trusted_certificate and proxy_ssl_verify.

ca-certificates.cer contains all certificate trusted by the system but we haven’t done anything to make Ubuntu trust our certificate therefore when we try to access https://localhost, we get the following error in nginx logs:

SSL certificate verify error, if we want Nginx to trust our localhost.crt, we will need to configure Ubuntu to recognize it. To do so, we need to use the update-ca-certificates command. If we look at man update-ca-certificates, we can see the following instruction:

Furthermore all certificates with a .crt extension found below /usr/local/share/ca-certificates are also included as implicitly trusted.

So to extend the implicit trusted certificates, we place our certificate under /usr/local/share/ca-certificates/localhost/ then run the command sudo update-ca-certificates.

And we are done, we should now be able to navigate to https://localhost! Now all our communication channels will be encrypted.

1

Browser --(https)--> nginx --(https)--> kestrel

4. SSL self signed certificate for Angular CLI

As a side note, Angular CLI also allows to serve locally with SSL with the following command --ssl:

1

ng serve --ssl--port=4201

It will generate a self signed certificate and serve on https://localhost:4201. Navigate to the address and download the certificate from Chome directly by clicking on Copy File. Once downloaded, install it on the Trusted Root CA and restart all browsers. The certificate will now be trusted and during development we will be serving on https.

Conclusion

Today we saw how to encrypt our communication between client and Nginx and between Nginx to Kestrel. We saw how to create a self signed certificate using openssl. We started by looking at how to enable SSL for Nginx by configuring the site file and using the Nginx proxy module. Next we looked into Kestrel and how we could use the same SSL certificate to encrypt communication between Nginx and Kestrel for all proxied requests. Hope you liked this post, see you next time!