Showing posts with label Beaglebone. Show all posts
Showing posts with label Beaglebone. Show all posts

Thursday, 17 December 2020

RESTful IoT with privacy & security: How to set up a Debian HTTPS Server

 

"It is quiet here and restful, and the air is delicious. There are gardens everywhere and police spies lie in the bushes ... " - Maxim Gorky

It is very tempting to use the ubiquitous HTTP web protocol for IoT. It is easy to test, and lets you operate your IoT from smartphones, tablets, desktops and even a computer program. Such a setup is called RESTful. It simply means your IoT device speaks the language of the web browser and web server. 



So we rush ahead with our RESTful API, and the IoT device is soon working and indispensable. Pretty soon we realize we need security and privacy: it won't do to have a hacker open the voice-controlled garage door ...

Our first line of defense is our WiFi password. It is reasonable to assume those living in the house should have access to WiFi and IoT. But what if we had guests or lodgers? Changing WiFi passwords can be a real bear, especially if you have 20-odd IoT devices. In fact it makes sense to localize the changes to a dedicated IoT server. RESTful, naturally.  

We will be needing some form of authentication: account names and passwords should do for now. Next we will need a reasonable amount of privacy, i.e., encryption so that someone else should not be able to lift the IoT password off the WiFi. That means HTTPS, or HTTP with SSL.

We start by implementing HTTPS server on a Linux system. The ESP8266 is known to be a little wobbly running HTTPS. ESP32 is better, but we can do without the complication for now. The traditional way is to use Apache. There are other, easier ways (like nginx, nodejs and even python) but Apache lets you run multiple servers right off the bat. This means you can keep your bad old HTTP server, add another HTTPS server on top of that and lets you support both your HTTP and HTTPS IoT devices.

From a bog-standard Debian (mine is a Beaglebone on eMMC), do the usual:

# apt-get update

# apt-get upgrade

Next, get Apache:

# apt install apache2

And while you are at it, you might as well make sure you have ssh. I got my DNS from duckdns.

Apache should come up complete with the stock webpage at http://localhost. Put your webserver files at /var/www/html/

To access the webserver from outside your WiFi access point, you will need a DNS server, but once you get it organized, a bog standard browser will display a warning before it will display your home page:


That means you need SSL, which usually costs money. You can opt for a self-signed certificate but this will produce a warning with most browsers. You then elect to disregard the warning and proceed, but this is a real problem if you are trying to sell the IoT device.

One way out is to get a 90-day certificate free from sslforfree. You just have to register, input your domain name and prove that you have access to the webserver, usually by uploading an sslforfree file to it. After it checks out the certificates can be downloaded. sslforfree links to a youtube video describing the process.

Do check out the video. I will simply list the differences relevant to a Debian installation. In Debian it is a simple:

# a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create s
elf-signed certificates.
To activate the new configuration, you need to run:
  systemctl restart apache2

I now need a configuration file for my HTTPS (or SSL) webserver. There is a template in Debian:

# cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/secure.cmheong.duckdns.org.conf

secure.cmheong.duckdns.org being the domain name of my new HTTPS server. The parameters for the new server are put in:

# cat /etc/apache2/sites-available/secure.cmheong.duckdns.org.conf | head -n 16
<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerName secure.cmheong.duckdns.org
                ServerAlias www.secure.cmheong.duckdns.org
                ServerAdmin webmaster@secure.cmheong.duckdns.org

                DocumentRoot /var/www/html

                # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
                # error, crit, alert, emerg.
                # It is also possible to configure the loglevel for particular
                # modules, e.g.
                #LogLevel info ssl:warn

                ErrorLog ${APACHE_LOG_DIR}/secure.cmheong.error.log
                CustomLog ${APACHE_LOG_DIR}/secure.cmheong.access.log combined

You then check your configuration and do not proceed further until this passes:

# apachectl configtest
Syntax OK

Make sure your webserver is now accessible from the Internet. Usually this means setting up Port Forwarding in your gateway to forward all port 443 traffic to your server IP address.

# systemctl restart apache2

You will then need to prepare for the sslforfree test of webserver and domain name ownership:

# mkdir /var/www/html/.well-known
# mkdir /var/www/html/.well-known/pki-validation

Register with sslforfree, download the challenge file they provided and put it in the new directory. This is where the Debian ssh installation comes in handy. 

If the sslforfree challenge succeeds, then the certificates and private key will be generated as a zip file.

# unzip secure.cmheong.duckdns.org.zip
Archive:  secure.cmheong.duckdns.org.zip
 extracting: certificate.crt
 extracting: ca_bundle.crt
 extracting: private.key

You then move them to their final secure directories:
# cp -v ./sslforfree/*.crt  /etc/ssl/certs
'./sslforfree/ca_bundle.crt' -> 'certs/ca_bundle.crt'
'./sslforfree/certificate.crt' -> 'certs/certificate.crt'

# cp  ./sslforfree/private.key  /etc/ssl/private/private.key

Remember to delete the ./sslforfree directory. If you want to put the certificates in a different place you will need to update the site config file accordingly:

# cat /etc/apache2/sites-available/secure.cmheong.duckdns.org.conf | grep -i SSLCerti
                #   SSLCertificateFile directive is needed.
                #SSLCertificateFile     /etc/ssl/certs/ssl-cert-snakeoil.pem
                #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
                SSLCertificateFile      /etc/ssl/certs/certificate.crt
                SSLCertificateKeyFile /etc/ssl/private/private.key
                SSLCertificateChainFile /etc/ssl/certs/ca_bundle.crt

As usual test the Apache configuration:

# apachectl configtest

And then restart Apache:

# systemctl restart apache2

The just aim your Chrome browser at https://www.yoursecureserver.com. If it worked you get something like this:



 

Now the traffic to and from the IoT RESTful server is encrypted. Note the sslforfree certificates expire in 90 days, but you are free to generate a new set. They will even email you a reminder. 

There you have it: a secure Internet-facing RESTful IoT server.

Happy Trails.

Sunday, 9 August 2020

If at first you don't succeed, try try again: Flashing an old Beaglebone Black eMMC

 

2019 Hugo Award for Best Novelette: Zen Cho

Back in 2016 I bought a few Beaglebone Blacks, but did not get round to using them. I guess they were superseded by the later-model Raspberry Pi's. 


Beaglebone Black


The Pi has always been less reliable than the Beagleboard or Beaglebone. Broadcom USB subsystem was especially flaky and since the Pi USB bus handled both disk IO as well as Ethernet, you are often SOL as Broadcom is not really reknown for fixing things. Little things like industrial temperature rating of 85 degrees Celsius. And having to run Linux from sdcards, which are certain to wear out. Even worse the full-size sdcard sockets fail after a few years. Luckily the later Pi models use microsd sockets, but I am still stuck with a bunch of Pi Model Bs and their flaky sdcards.

The Pi had irresistible things going for it. It was way cheaper, had more addon modules (ie 'hats'), and best of all, it had Debian. There was no longer the month-long struggle to get Angstrom Linux to run properly. Yet those niggling problems ...

Getting my Beaglebone Black running was unexpectedly painless. I plugged it into my laptop USB port and it was running. It came up as /dev/ttyACM0 a serial port. No problem, all I needed was minicom, and the default settings of 115200 baud, 8 bits, 1 stop, no parity.


Default account is 'debian' and password 'tempwd'. There is no root password. I did not have to struggle with Angstrom. In fact I forgot to put in the sdcard. That meant it loaded from on-board mass storage. And it was Debian!

root@beaglebone:~# cat /etc/dogtag

BeagleBoard.org Debian Image 2015-03-01

Turned out the onboard memory was eMMC, still flash memory, but in IC form without those dreaded sockets. Memory is 512MB and there is no built-in WiFi; that would come only in the Beaglebone Black Wireless.

From bottom left: USB Master socket, microsd  and the elusive User-boot button


First order of business with Debian is to get it up to date. I connected it via copper LAN to my ADSL modem where it found the Internet on its own. But 'apt-get update' had errors, even though it technically did not fail:

root@beaglebone:~# apt-get update

W: Failed to fetch http://ftp.us.debian.org/debian/dists/wheezy/contrib/binary-a
rmhf/Packages  404  Not Found [IP: 64.50.233.100 80]

W: Failed to fetch http://ftp.us.debian.org/debian/dists/wheezy/non-free/binary-
armhf/Packages  404  Not Found [IP: 64.50.233.100 80]

W: Failed to fetch http://ftp.us.debian.org/debian/dists/wheezy-updates/main/bin
ary-armhf/Packages  404  Not Found [IP: 64.50.233.100 80]

'apt-get upgrade' finished OK:
root@beaglebone:/home/debian# apt-get upgrade

But the version was wheezy, and really old. Not to worry, I reached for the latest images, and downloaded AM3358 Debian 9.12 2020-04-06 4GB SD ImgTec. It only needed a tiny (4GB!) microsd card, and:

$xzcat bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz | sudo dd of=/dev/sdc
7372800+0 records in
7372800+0 records out
3774873600 bytes (3.8 GB, 3.5 GiB) copied, 3001 s, 1.3 MB/s

But it did not boot from the microsd, and instead after an hour or so booted from eMMC. Time to Read the Manual. The manual is no fluffy faux-friendly 'Getting Started' guide; it reads like a datasheet with schematics in glorious abundance.

There is mention of a 'Boot button', where if held down and the beaglebone is power-cycled it will force a boot from sdcard. But it did not work - and eventually always reverted to the old eMMC wheezy Debian.

After wasting a couple of days ruling out a hardware malfunction, the problem had to be the Debian image. One hint was that Debian Image 2015-03-01 would not mount  Debian 2020-04-06. That would point to an ext3 filesystem incompatibility. The existing eMMC Debian code would be needed to mount and boot the new Debian before flashing can commence.

And yet all this  has been solved before; one compromise is to use an fossil filesystem (like FAT16) just for booting, and indeed Debian 015-03-01 had such a partition but not Debian 2020-04-06. Usually SoCs have separate bootrom to prevent bricking incidents like this (like its close cousin the Beaglebone White), but this is easy enough to test.

beaglebard.org maintains a complete archive of old images, and hoping for an intermediate Debian that will be compatible with both, I picked Debian 2016-12-09. Then it s a simple matter of:

$xzcat bone-debian-8.6-iot-armhf-2016-12-09-4gb.img.xz > /dev/sdc

And it booted from microsd, just like that.

root@beaglebone:~# cat /proc/version
Linux version 4.4.36-ti-r72 (root@a2-imx6q-wandboard-2gb) (gcc version 4.9.2 (Debian 4.9.2-10) ) #1 SMP Wed Dec 7 22:29:53 UTC 2016

You need to prepare the new image for flashing. Just find the file /boot/uEnv.txt and uncomment the last line:

cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

To flash the eMMC, I added the 5V power cable, and powered off. Then with the microsd still in, held down 'User boot'  button and powered back on. This worked right off the bat; the blinkenlights did an impression of Pong, and when finished, all lit up, then shut down.

On powering up, and removing the microsd, I get:

root@beaglebone:~# cat /etc/dogtag
BeagleBoard.org Debian Image 2016-12-09

Our imugi is not yet a dragon, but this is clearly The Way. The trusty sdcard is then repurposed with:

$xzcat bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz | sudo dd of=/dev/sdc

And now it booted off the microsd. Now all I need to do is to repeat the eMMC flashing process with the latest Debian Image, 2020-04-06. As a precaution I first upgraded without incident:

root@beaglebone:~# apt-get update
root@beaglebone:~# apt-get upgrade

Changed the default passwords did the usual sysadmin stuff. The eMMC flash went without incident, and unlike Zen Cho's Byam, my Beaglebone Black did not turn back but transformed its eMMC to Debian 2020-04-06.

Happy Trails.