How to secure your arduino IOT network with Raspberry Pi and nginx

3 minute read

As a general rule, all API calls to your backend should always be encrypted with https (SSL/TLS), this applies for IOT scenarios just the same as for internet traffic in general. However, if you use cost-effective microcontrollers like Arduino or ESP8266, there is not enough computing horsepower to encrypt the traffic, or even enough memory to store the code for proper SSL/TLS handshake algorithms. So you loose out or you need to move to more expensive hardware.

This problem is listed as number 4 in the top 10 security vulnerabilities for IOT on the OWASP website, so I did not want to send the data from my home sensors unencrypted into the world.

Here I will describe a nice and elegant solution which solved this problem for me.

The story so far

In the previous parts of this series about “Monitoring Everything with Raspberry Pi and Arduino” I have described:

This is part V: how to secure the traffic between your microcontrollers and the backend API, before I will in the next parts go into more details about using Arduino microcontrollers with their own network access.

Backend

In my case, I have my backend configured to accept only https traffic. Any unencrypted http request is immediately redirected with a 301 “Moved permanently” response, so that there is nothing accepted without encryption.

Raspberry Pi

In some of my use cases I have a Raspberry Pi to read some sensors, or to connect to an Arduino via USB to use the Arduino’s analog input. This works without problem, because the any version of the Raspberry Pi is strong enough to use https directly.

Arduino and ESP8266

Some Arduino boards come with their own network connection. This is either by adding an Internet or WiFi shield to an Arduino, or by using a compatible board which has a Wifi chip on board, like the Wino board or the Photon. Another option is to use an ESP8266 chip and directly program it. In all of these cases you can send and receive data via Internet, so it would be no problem to send your sensor data with an HTTP post data to an API endpoint.

Here is an example how to read a soil humidity sensor: sketch_soil_wifi with a Wino Board and send the data as JSON object to an API backend like limitless garden.

But the traffic sent by the Arduino is not encrypted. I could accept this on the WiFi network in my home, so as not to get paranoid about people sniffing the traffic on my WiFi - but out on the internet? No way. Compromising my backend server by letting it accept unencrytped traffic? Surely not.

Nginx to the rescue

Nginx is a great piece of software and often used by websites as a https frontend before your web server, to offload the encryption work to a separate box. I figured out that this was exactly the opposite from what I wanted to achieve.

nginx on Raspberry -fullwidth

Instead of sitting close to the web server and converting from https to http, I wanted it to sit close to my web clients (my Arduino’s) and convert from http to https. Then the requests could go out in the world wide internet without being read by someone bad. So I quickly reappropriated my oldest Raspberry Pi, a venerable model A, and told it to

$ sudo apt-get install nginx 

then just added one file in /etc/nginx/sites-available:

# proxy server for selected stuff from /api folder, 
# giving 404 on everything else

server {
	listen 8118; 
	location /api {
		proxy_pass      https://<<your-backend-server>>/api;
	} location / {
		return  404;
	}
} 

This actually only allows the api traffic to go out and not anything else.

Now just activate this ruleset and deactivate the default (which would be a local web server for static files):

$ sudo rm /etc/nginx/sites-enabled/default 
$ sudo ln -s /etc/nginx/sites-available/proxy /etc/nginx/sites-enabled 
$ sudo /etc/init.d/nginx restart 

Done. Now you can connect all of your Arduinos to the port 8118 (or another one if you changed this in the proxy rules) and the Raspberry will happily convert it to encrypted https traffic.

Please let me know in the comments whether this was helpful for you.

Comments