Share: Securing and sharing web Things
9.1.3 Enabling HTTPS and WSS with TLS on your P
Now that you’ve seen the theory, it’s time for a bit of practice! Let’s secure the API of your WoT Pi to ensure that traffic between the Pi and its clients is encrypted. Note that the process we define here works as well on all the other Linux devices we talked about—for example, the Intel Edison or the BeagleBone—as well as on any Linux- or Unix-based machines. Go ahead and generate a certificate. First, you need to make sure the OpenSSL library is installed. On your Pi go to the /resources directory and run
sudo apt-get install openssl
This should tell you something along the lines of openssl is already the newest version. Or it will be installed if not present. Now, to generate the certificates, run
openssl req -sha256 -newkey rsa:2048 -keyout privateKey.pem -out caCert.pem -days 1095 -x509
Because this command is self-explanatory we won’t detail it. No? Fine, let’s dig into it! The command does two things in one. First, it generates a private key (-newkey rsa:2048 -keyout privateKey.pem) that will be used to sign the certificate using the sha256 hashing algorithm. While it does this, you’ll see a Generating a 2048 bit RSA private key message followed by a prompt to provide a passphrase, essentially a pass- word to protect your private key. Make sure you keep this one safe because you’ll need it soon!
Second, it will generate a new certificate (-out caCert.pem) that will last for 1,095 days using the x509 data format, and it also prompts you with a few questions, as shown in listing 9.1. The common name is the hostname for which this certificate should be valid; for example, raspberrypi.local if you’re on your Pi or localhost if you’re running these examples on your machine. The information you provide here will be exposed in the certificate and will be visible to all clients.
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank
88 CHAPTER 9 Share: Securing and sharing web Things
For some fields there will be a default value, If you enter '.', the field will be left blank. ---
Country Name (2 letter code) [AU]: UK
State or Province Name (full name) [Some-State]: London Locality Name (eg, city) []:London
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Web of Things Organizational Unit Name (eg, section) []: Web of Things
Common Name (e.g. server FQDN or YOUR name) []: raspberrypi.local Email Address []:[email protected]
At the end of this process, two files will be generated:
caCert.pem is the public part of the certificate your Pi server will send to the clients when connecting to it via TLS.
privateKey.pem is the private key of your Pi server and hence should be kept, well...private.
You’re now ready to turn your Pi unencrypted HTTP and WS APIs into secure
HTTPS and WSS APIs. All you need to do is modify the code of the wot-server.js file at the root of your WoT PI project (see chapters 7 and 8). Copy the content of wot- server.js into a new wot-server-secure.js file and modify it as shown in the following list- ing, which enables HTTPS and WSS.
[...]
var createServer = function (port, secure) { if (process.env.PORT) port = process.env.PORT;
else if (port === undefined) port = resources.customFields.port; if (secure === undefined) secure = resources.customFields.secure; initPlugins();
if(secure) {
var https = require('https');
var certFile = './resources/change_me_caCert.pem'; var keyFile = './resources/change_me_privateKey.pem'; var passphrase = 'webofthings';
var config = {
cert: fs.readFileSync(certFile), key: fs.readFileSync(keyFile), passphrase: passphrase
};
return server = https.createServer(config, restApp) .listen(port, function () {
wsServer.listen(server);
console.log('Secure WoT server started on port %s', port); })
} else {
var http = require('http');
return server = http.createServer(restApp)
Listing 9.2 Modifying the WoT Pi server to serve HTTPS and WSS content
This should be the hostname, IP, or domain name corresponding to your Pi or the local machine you test the code from.
Start the internal hardware plugins. If in secure
mode, import the HTTPS
module.
The actual certificate file of the server
The private key of the server generated earlier The password of
the private key
Create an HTTPS server using the config object.
By passing it the server you create, the WebSocket library will automatically detect and enable TLS support.
89
Securing Things
.listen(process.env.PORT | port, function () { wsServer.listen(server);
console.log('Unsecure WoT server started on port %s', port); })
} };
function initPlugins() {
var LedsPlugin = require('./plugins/internal/ledsPlugin').LedsPlugin; var PirPlugin = require('./plugins/internal/pirPlugin').PirPlugin; var Dht22Plugin = require('./plugins/internal/dht22Plugin').Dht22Plugin; pirPlugin = new PirPlugin({'simulate': true, 'frequency': 5000});
pirPlugin.start();
ledsPlugin = new LedsPlugin({'simulate': true, 'frequency': 5000}); ledsPlugin.start();
dht22Plugin = new Dht22Plugin({'simulate': true, 'frequency': 5000}); dht22Plugin.start(); } module.exports = createServer; process.on('SIGINT', function () { ledsPlugin.stop(); pirPlugin.stop(); dht22Plugin.stop(); console.log('Bye, bye!'); process.exit(); });
Finally, modify the wot.js file to require wot-server-secure.js, and start the server by running nodewot.js. Now, go to https://localhost:8484/properties/pir in your browser. You should get a warning saying that the connection is not private. What this really means appears in the small print: ERR_CERT_AUTHORITY_INVALID. This means that the certificate was generated by you and not by a certificate authority (CA) trusted by your browser. There are two ways to fix this: you can buy a certificate from a trusted
CA, as explained in the next section, or you can tell your computer to trust the certi- ficate you just created. The best way to do this is by adding the certificate to the trust store of your browser. The operation will differ depending on which environment you’re using, but here’s how to add it to Firefox: click I Understand The Risk (because now you do, don’t you?), Add Exception, and finally Confirm Security Exception. Other browsers like Chrome use the trust store of the underlying operating system. Hence, to ensure Chrome accepts your certificate, go to Preferences > Settings > Show Advanced Settings; in HTTPS/SSL click Manage Certificates. This should open the trust store of your operating system, where you can import the certificate. Adding self- signed SSL certificates directly to your operating system1 will make it much easier for you to develop secure applications for your Pi.
90 CHAPTER 9 Share: Securing and sharing web Things
Once your browser trusts the certificate of your WoT Pi, you should be able to get the content returned and the browser should display the usual lock icon on the address bar. If you click it, you’ll see the details of your TLS certificate, as shown in figure 9.5.
BEYONDSELF-SIGNEDCERTIFICATES
Clearly, having to deal with all these security exceptions isn’t nice, but these excep- tions exist for a reason: to warn clients that part of the security usually covered by
SSL/TLS can’t be guaranteed with the certificate you generated. Basically, although the encryption of messages will work with a self-signed certificate (the one you created with the previous command), the authenticity of the server (the Pi) can’t be guaran- teed. In consequence, the chain of trust is broken—problem 2 of figure 9.2. In an IoT context, this means that attackers could pretend to be the Thing you think you’re talk- ing to. This isn’t a big deal when your Things are accessible only on the local network, but as soon as you make them available on the web, this becomes critical.
The common way to generate certificates that guarantee the authenticity of the server is to get them from a well-known and trusted certificate authority (CA). There are a number of them on the web, such as Thawte, Symantec, and GeoTrust. The good
The certificate is trusted because we added it to the trust store. The domain corresponds
to this certificate. The channel is encrypted. The connection is secured by TLS 1.2.
Figure 9.5 The server of the WoT Pi can now be accessed via HTTPS. The details of the secure connection and certificates can be reviewed by clicking the small lock icon on the address bar.
91
Securing Things
thing about certificates issued by such CAs is that they verify who created the certifi- cates, albeit with various degrees of rigor. This means that a client has a greater cer- tainty of which server it’s talking to (authentication). In consequence, these certificates, or certificates generated using these, are trusted by a number of clients such as web browsers. More concretely, this means that web browsers and operating systems have these certificates in their trust store.
The problem is that certificates issued by well-known CAs are certainly not free. The business of selling web security is a lucrative one! A direct and unfortunate conse- quence of this is that a number of sites use cheaper CAs that do a poorer job of check- ing to whom they deliver certificates, or they decide to not use secured connections at all. But this is rapidly changing: a number of major actors on the web, such as Mozilla, Akamai, Cisco, and the Internet Security Research Group, got together to create the Let’s Encrypt1 project, an automated CA providing free and secure certificates for the public’s benefit. There are even ways to automatically generate certificates using Let’s Encrypt from a Raspberry Pi running a Node server with Express.2 Now that you have the basics of TLS, you should consider this when moving your Pi to the World Wild Wide Web.
1 https://letsencrypt.org
2 https://github.com/DylanPiercey/auto-sni
The nerd corner—I want my Pi to be on the web!
Once the development and testing phase of your WoT Pi is finished, you’ll likely want to make it accessible over the web with its own public domain; for example, mypi.webofthings.io. To do this, you could use Yaler,a which is a great service and open source project that offers a relay to securely access your embedded devices through your firewall and supports mobile Things connecting to different networks. Alternatively, if you want to go the DIY route, you can use a dynamic DNS service— unless you already have a fixed IP address—that keeps monitoring the IP address of your home router to determine when it changes. There are a number of those, but Duck DNS is straightforward and free. Moreover, it provides clear explanations of how to install it on a Pi.b Once this is set up, you’ll also have to set up port forwarding on your home router.c Then, you might also need to generate (or buy) a certificate with a common name corresponding to the new Duck DNS subdomain of your Pi; for exam- ple, mypi.duckdns.org. Once you’ve done all of this, your Pi should be truly on the world-wide Web of Things. But your Pi will also be ready for attackers to try to hack it, so make sure you protect it well, at the very least by reading to the end of this chapter and implementing the concepts we describe!
a https://www.yaler.net/raspberrypi
b http://www.duckdns.org/install.jsp#pi
92 CHAPTER 9 Share: Securing and sharing web Things
9.2
Authentication and access control
Once we encrypt the communication between Things and clients as shown in the pre- vious section, we want to enable only some applications to access it. Let’s get back to our hotel scenario to understand this issue. The hotel control center application needs to have full access to all devices in the network and the ability to configure and administer them. But Lena, who stays in room 212, only needs to access the devices and services in that room. Besides, she shouldn’t be able to configure them, only to send a limited set of commands. First, this means that the Things—or a gateway to which Things are connected—need to be able to know the sender of each request (identification). Second, devices need to trust that the sender really is who they claim to be (authentication). Third, the devices also need to know if they should accept or reject each request depending on the identity of this sender and which request has been sent (authorization). If encryption is like sending a postcard in a sealed envelope, authentication and authorization are like sending that envelope via registered mail: the postman will deliver the letter only to the correct recipient as long as they can prove their identity with a valid ID.