In this third part of our WebSocket tutorial series, we will be building upon the real-time dashboard example that was described in the previous articles – now adding a critical Transport Layer Security (TLS) to protect the low-latency communication from our embedded WebSockets Secure application. If you missed the first two articles, it’s best to start from the beginning to catch up and find out how WebSockets can help you create a web-based dashboard to control your hardware and display your sensor data in real-time.
In this day and age, everything online should be encrypted. Now that the TLS Security Suite is included for free with NNDK 3.0 or later, it’s never been easier to encrypt your data. For that reason, we will demonstrate how to implement WebSocket Secure (WSS) using NNDK 3.0.
Adding TLS (commonly known as SSL) is the first step to prevent man-in-the-middle (MITM) and eavesdropping attacks. This is because using TLS ensures three features that allow for secure communication. At a very high level, those features are:
1. Authentication: TLS uses certificates and certificate authorities to authenticate the identity of the client before establishing a connection. This gives you peace of mind by knowing that you’re communicating with whom you want to be communicating with.
2. Privacy: TLS encrypts data before transmission so that the data is private between the client and the server. This prevents anyone from being able to see your unencrypted data while in transit.
3. Integrity: TLS uses hash functions and ciphers to ensure that data was not altered while in transit.
To demonstrate how to use WSS, we will modify the real-time dashboard example developed in the prior installments of this series. The full source code can be found in our public GitHub repository here. It’s fairly straight forward. The modifications are as follows:
Add certificate and key generation to the makefile (bold red text indicates those sections specifically addressing SSL certificate creation):
NAME = SecureDIPSwitches CPP_SRC += \ src/main.cpp \ src/SimpleAD.cpp CPP_SRC += \ src/key.cpp \ src/cert.cpp \ src/htmldata.cpp CREATEDTARGS += \ src/key.cpp \ src/cert.cpp \ src/htmldata.cpp src/htmldata.cpp : $(wildcard html/*.*) comphtml html -osrc/htmldata.cpp device.crt: device.key device.key: CA.crt openssl genrsa -out device.key 1024 openssl req -new -config ssl_cert_config.txt -key device.key -out device.csr openssl x509 -req -days 3650 -in device.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out device.crt CA.key: openssl genrsa -out CA.key 1024 CA.crt: CA.key openssl genrsa -out CA.key 1024 openssl req -new -config ssl_cert_config.txt -key CA.key -x509 -days 3650 -out CA.crt src/key.cpp: device.key compfile device.key comp_key comp_key_len $@ src/cert.cpp: device.crt compfile device.crt comp_cert comp_cert_len $@ include $(NNDK_ROOT)/make/boilerplate.mk
This configuration will generate a 1k RSA key and a self-signed certificate that is good for 10 years. The makefile references the file
ssl_cert_config.txt to configure the certificate parameters. If you’re curious as to how that is configured, this file can be found along with the source code in our public repo. For a deeper explanation on how self-signed certificates are generated, take a look at our article on this topic here.
The certificate and key are then translated into a format that will be compiled directly into the application as
key.cpp, respectively. Finally, they are listed with the other source files that comprise the application.
In UserMain, found in
main.cpp, modify the
StartHttp() function to
StartHttps() to start a secure web server:
script.js, modify the WebSocket connection to use the “wss” protocol:
ws = new WebSocket("wss://" + window.location.hostname + "/INDEX.HTML");
That’s it! For the most part, we had to add an “s” to a couple lines of code to use the secure variations of certain functions, and generate a certificate and key.
Accessing the web-based dashboard using WebSocket Secure is the same as accessing the webpage with normal WebSockets. Simply go to the webpage of your NetBurner device using the “https://” URL protocol prefix. One difference you will notice when using a self-signed certificate, is that you will need to tell your browser it is okay to trust the self-signed cert that your NetBurner’s web server is providing. In Firefox and most browsers, it will look like this:
You will need to click “Advanced” and “Proceed” or something similar depending on the browser and version you are using. The reason you’re seeing this warning is because, for the sake of creating an easy to demonstrate secure web server example (not to mention free), we generate a no-cost self-signed certificate (Disclaimer: We do not recommend using self-signed certificates for production level code!). Your web browser is warning you that the self-signed certificate cannot be trusted because it has not been verified by a trusted Certificate Authority supported by your web browser.
Beyond that, the webpage and WebSocket connection work like they did previously. If you try to sniff data using a packet analyzer application, like Wireshark, you shouldn’t see unencrypted (human readable) WebSocket data in transit. Now you can rest assured knowing your WebSocket data is protected!