Secure HTTP Server

Overview

This example demonstrates how to use ZentriOS to create a secure TLS HTTPS server using a self-signed TLS certificate. Any web browser may then securely connect to the HTTPS server. If required, a client certificate may be used to enable bi-directional client and server authentication.

The following steps are covered by this example:

WARNING! This app note has a security flaw. The TLS certificate used to generate other certificates is stored on the device. If the device is hacked, the certificate can be used to generate more certificates for devices of which you do not have control or knowledge.

If you are new to TLS certificates it is recommended to work through this app note first to gain a basic understanding of certificates.

In production it is recommended to follow the HTTPS Intermediate Certificates app note, which provides higher security.


Command Line Conventions

The procedures below for running OpenSSL commands work on Linux, Mac or Windows computers with the correct software packages installed.

The examples shown are for a Linux machine.

Notes are provided where a variation is required for a different platform, and references for Windows in particular are provided in the final section at the bottom of the page.

Command Line Prompt

In the command line examples below, the beginning part ~$ stands for the command prompt. The actual prompt varies depending on your user name, machine name and platform. Enter only the part of the command line following the command prompt.

Command Line Continuation

This procedure requires long command lines. Where command lines are too long to display, a line continuation character \ is shown at the end of the first line, and the remainder of the command line is shown on the next line. Type the whole command on the same line. Alternatively, on some operating systems you can type the line continuation character followed by Enter, and continue the command on the next line.

On a Linux system the line continuation character is a backslash \ as shown in the examples below. On a MS Windows command line, the line continuation character is a caret ^.


TLS Certificate Overview

TLS certificates are used to:

See TLS Client, TLS Certificate Primer for more information.

OpenSSL

For the following steps in which certificates are generated, it is assumed you have OpenSSL installed on your computer and OpenSSL is in the PATH environment variable i.e. you can execute OpenSSL directly from a command line. OpenSSL may be downloaded here: https://wiki.openssl.org/index.php/Binaries or on Ubuntu, run the command: ~$ sudo apt-get install openssl The manual for OpenSSL may be found here: https://www.openssl.org/docs/

In some instances, it may be necessary to set the RANDFILE environment variable to avoid OpenSSL errors such as ''unable to write 'random state'''. To temporarily set the RANDFILE environment variable to a local file, use the following command:

~$ set RANDFILE=.rnd

Generating a Self-Signed CA Certificate

The first certificate to generate is a self-signed Certificate Authority (CA) certificate. This is the root certificate from which all other certificates are derived.

We start by generating the CA key. This is the most sensitive file in your secure TLS system. This key should be kept in a secure location.

~$ openssl genrsa -aes256 -out my_ca.key 4096

After executing this command OpenSSL prompts for a password to secure the CA key, enter a password (and a confirmation password). This is the same password used for the rest of the process.

Next, create the self-signed CA cert using the key:

~$ openssl req -new -sha1 -x509 -key my_ca.key -out my_ca.crt

OpenSSL prompts for various values. Press Enter to accept a default value. At the Common Name prompt, you can enter any name, for example my_ca_cert. Here is an example of what to expect (note the Common Name value):

~$ openssl req -new -sha1 -x509 -key my_ca.key -out my_ca.crt
Enter pass phrase for my_ca.key:
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
For some fields there will be a default value,
If you enter '.', the field will be left blank.

----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:my_ca_cert      <-- Common Name
Email Address []:

Generating a Server Certificate

Now that we have a CA certificate, we need to generate a TLS server certificate. This is TLS cert used by the ZentriOS HTTPS server.

To generate the server certificate, we need to decide on the host name of our server. The host name is the URL entered into a web browser (e.g https://mydevice.com). ZentriOS has several options for host names.

First we need to decide, is ZentriOS connecting to a network or is it creating the network? i.e will the ZentriOS 'wlan' or 'softap' interface be used?

If the 'wlan' interface is used, there are two host name options:

If the 'softAP' interface is used, there are also two host name options:

The following examples uses the wlan interface and mDNS. The host name will be: mydevice.local.

When generating the server certificate, it is CRITICAL the host name is used since the web browser will verify the name. If the server certificate is generated with the host name: mydevice.local, the only valid URL is: https://mydevice.local. If any other domain is used the web browser will display a warning indicating the certificate is not valid.

NOTE! At every point where mydevice.local appears in the procedure below, you should substitute the host name you have chosen for the device.

First generate the private key for our server certificate:

~$ openssl genrsa -aes256 -out mydevice.local.key 1024

OpenSSL prompts for another password. This can be the same as the password used for the CA cert above (or a different password if you prefer).

Next we need to create a Certificate Signing Request (CSR).

~$ openssl req -new -sha1 -key mydevice.local.key -out mydevice.local.csr

OpenSSL prompts for various values. Press Enter to accept default values until the Common Name prompt.

Important Note! At Common Name prompt enter the host name of the device. At the OpenSSL Challenge password, do NOT enter anything. Just press Enter. Here is an example of what to expect (note the Common Name value):

~$ openssl req -new -sha1 -key mydevice.local.key -out mydevice.local.csr
Enter pass phrase for mydevice.local.key:
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
For some fields there will be a default value,
If you enter '.', the field will be left blank.

----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:mydevice.local    <-- Common Name
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:                                    <-- Leave this BLANK!
An optional company name []:

Now, remove the passphrase on the server key so ZentriOS may use it:

~$ cat mydevice.local.key | openssl rsa -out mydevice.local.key

Next we need to generate the server certificate signed by our self-signed CA certificate:

~$ openssl x509 -req -sha1 -in mydevice.local.csr -CA my_ca.crt \
           -CAkey my_ca.key -out mydevice.local.crt -set_serial 01

Next, convert mydevice.local.crt to .pem format (converting first to an intermediate DER format):

~$ openssl x509 -in mydevice.local.crt -outform DER | \
           openssl x509 -inform DER -out mydevice.local.pem -outform PEM

The server certificate has now been generated in the required .pem format.

At this point we have everything needed to run the ZentriOS device as a Secure HTTPS server (but not with client auth ... yet). Any client (that has a copy of the device root CA certificate, or a cert signed by the device root CA) can connect and authenticate the ZentriOS HTTP server. Once authenticated an encrypted connection can be opened between the client and HTTPS server.

This process is identical to the process used when you open a non-password protected https:// site from your web browser. e.g. https://google.com. However, instead of a self-signed cert, your web browser uses a CA cert from a trusted third-party company GeoTrust Global CA. The Google server certificate is signed by the GeoTrust CA cert, and your web browser uses this CA cert (which is contained in a certificate store on your PC) to authenticate the Google HTTPS server.


Authenticating the Client

If you don't want to use client authentication, you may want to skip to the next section.

What if the ZentriOS HTTPS server wants to authenticate the client? ZentriOS has two options, both of which may be used simultaneously:

- Use the http.server.username and http.server.password variables. Using these variables, the web browser displays a prompt asking for credentials before the ZentriOS HTTPS server will return a webpage. - Use a client TLS certificate. With this option, a certificate is installed into the client web browser. The ZentriOS HTTPS server authenticates the client certificate before a webpage is returned.

Each option has its pros and cons.

Option 1: - Pro: Much simpler. The client just needs the username/password. - Con: Every client uses the same username/password.

Option 2: - Pro: Much more secure. Each client has a unique custom certificate which the server authenticates. - Con: Much more complicated. A unique certificate must be generated and loaded into each client.

For this example we'll use both (because ZentriOS supports both!).

Setting up HTTPS server username and password is described in HTTP Server Username and Password below.

Generating a Client Certificate and Key

The remainder of this section describes how to generate a client key and certificate.

Decide on a name for the client. For this example we'll use the name: name@email.com.

The first step is to generate a certificate key for the client.

~$ openssl genrsa -aes256 -out name@email.com.key 1024

OpenSSL prompts for another password (and a confirmation). This can be the same as the password used for the CA cert above, or a different password.

Next we need to create a Certificate Signing Request (CSR).

~$ openssl req -new -sha1 -key name@email.com.key -out name@email.com.csr

OpenSSL prompts for various values. Press Enter to accept default values until reaching the Common Name prompt. At the prompt Common Name: enter the name of the client, name@email.com for this example. When OpenSSL asks for a Challenge password, do NOT enter anything. Just press Enter. Here is an example of what to expect (note the Common Name value):

~$ openssl req -new -sha1 -key name@email.com.key -out name@email.com.csr
Enter pass phrase for name@email.com.key:
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
For some fields there will be a default value,
If you enter '.', the field will be left blank.

----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:name@email.com     <-- Common Name
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:                                     <-- Leave this BLANK!
An optional company name []:

Next we generate the client certificate signed by the mydevice.local.crt server certificate:

~$ openssl x509 -req -sha1 -in name@email.com.csr -CA mydevice.local.crt  \
           -CAkey mydevice.local.key -out name@email.com.crt -set_serial 02

Finally we create a '.p12' file from the client certificate and key. A .p12 file makes it much easier to install the client certificate into a web browser.

~$ openssl pkcs12 -export -clcerts -in name@email.com.crt  \
           -inkey name@email.com.key -out name@email.com.p12

Simply press enter when prompted for an 'Export Password' (twice). This makes the .p12 file non-password protected.

We now have everything needed to setup a Secure HTTPS server with client authentication.

NOTE: The name@email.com.key file is password protected. If you intend to use the .key/.crt files rather than the .p12 file, the password can be removed with the following command:

~$ cat name@email.com.key | openssl rsa -out name@email.com.key

Loading the Server cert onto the Device (using ZentriOS)

Next we'll load the server cert and key onto the ZentriOS device. The easiest way to do this is to use the ZentriOS Web App provided with ZentriOS 2.1 or later. To start the webapp, issue the following command to the device using a ZentriOS terminal:

> setup web

This starts the ZentriOS softAP and webserver. Connect your computer to the ZentriOS Wi-Fi network (by default the network name is ZentriOS-XXX, and the network password is 'password'). Then open a web browser and enter the URL: http://setup.com

Wait for the ZentriOS webapp to load, then click on the 'Files' tab. The Files tab enables you to drag and drop files from your computer to the file system on the ZentriOS device.

On your computer, find the server key and certificate files that you just created:

Drag these files onto the ZentriOS webapp where it says 'Drop files here'. Alternately, click the button labelled 'Click to add files'.

That's it! The server key and certificate are now stored in non-volatile memory on the ZentriOS device flash file system.

Issue the following command to stop the softAP and webserver:

> reboot

Run ZentriOS as a Secure HTTPS Server

We're now ready to configure the device for:

First, setup the secure HTTPS server without client authentication or verification. Issue the following commands:

ZentriOS CommandsDescription

set http.server.enabled      1
set http.server.port         443
set http.server.tls_enabled  1
set http.server.tls_cert mydevice.local.pem
set http.server.tls_key mydevice.local.key
set http.server.max_clients  1




<- Enable the HTTP server
<- Standard secure HTTP port
<- Enable secure (TLS) HTTP server
<- Set the server certificate
<- Set the server certificate key
<- (optional) A TLS connection may use
   lots memory. This variable ensures
   only one connection is opened

Next let's enabled the mDNS feature with the host name 'mydevice' :

ZentriOS CommandsDescription

set mdns.enabled 1
set mdns.name    mydevice

save

<- Enable mDNS daemon
<- Set the host name to 'mydevice'
   (note that '.local' is automatically appended)
<- Save the settings

Now, put the device on the network. Issue the following command and follow the prompts:

network_up -s

That's it! The ZentriOS device is now running a secure HTTPS server with mDNS support. Go to your web browser (on a computer connected to the same network as the device) and enter the URL: https://mydevice.local/

At this point, your web browser will likely display a security warning message. That's good!

Recall that the mydevice.local.pem server certifcate was signed by the self-signed CA certificate? Your browser doesn't know about the self-signed CA certificate (yet), as a result, it is unable to authenicate the mydevice.local.pem certificate.

To fix this, find and double-click on the my_ca.crt file. This should display a dialog providing information about the certificate. There should also be a button that says something like 'Install Certificate'. Click the 'Install Certificate' button and follow the dialogs to install the certificate. Make sure the cert is installed in the 'Trusted Root Certification Authorities' Certificate Store.

Once installed, you may need to restart your browser for the new my_ca.crt cert to be recognized as a valid certificate authority. Once recognized, the browser should not display a security warning when browsing to the device at the URL: https://mydevice.local

If everything is working, you are now viewing secure encrypted HTTP pages served from the ZentriOS device.

The ZentriOS Web App displays by default, but the default webpage can easily be changed by setting the ZentriOS variable:

set http.server.root_filename <webpage.html>

where <webpage.html> is the name of the desired root web page located on the ZentriOS file system (you need to put your own page on there first!).

Other default pages that can be changed are:

ZentriOS CommandsDescription

set http.server.notfound_filename <mypage.html>

set http.server.denied_filename   <mypage.html>



<- Sets the page that appears
   if the webpage isn't found
<- Sets the page that appears
   if bad credentials are entered

HTTP Server / Client Authentication

As an extra security measure, let's enable client authentication. This forces a client to supply a validate TLS certificate before the HTTP server returns information requested by the client.

NOTE: This is a memory intensive feature. Other settings may need to be adjusted for it to function properly.

To enable client authentication, issue the following command:

ZentriOS CommandsDescription

set http.server.tls_verify_peer 1
save

<- Enable client (i.e. peer) authentication
<- Save the new settings

Toggle the network interface to restart the secure HTTPS server (with client authentication enabled):

network_down
network_up

Open your web browser and enter the URL: https://mydevice.local/

The browser displays nothing. This is because the browser is not configured to supply a valid TLS certificate. We can fix this by installing the .p12 certificate generated previously.

To install the certificate, double-click the file name@email.com.p12 on your computer file system. This should bring up a dialog. Follow the dialog to install the cert into your system (the client certificate does not need to go into the Trusted Cert Authority). Again, you may need to restart your browser for the changes to take effect.

After the .p12 certificate is installed, open your web browser and enter the URL: https://mydevice.local/

This time you are prompted for certificate information. Select the newly installed name@email.com certificate.

You should once again see the ZentriOS webapp. This time bi-directional client AND server authentication is used. Your browser authenticates the ZentriOS HTTPS server and the ZentriOS HTTPS server authenticates your browser.


HTTP Server Username and Password

Finally, let's also force users to enter a username and password to access the HTTPS server using HTTP Basic Authentication. A valid username/password combination must be supplied to gain access to webpages on the device.

To set the username/password, issue the following commands:

ZentriOS CommandsDescription

set http.server.username admin
set http.server.password rootpassword
save

<- Sets the HTTP server username
<- Set the HTTP server password
<- Save the new settings

Toggle the network interface to restart the HTTP server with the new username/password settings:

network_down
network_up

Now go to your web browser and enter the URL: https://mydevice.local/

The browser prompts for a username and password, enter the details to match the settings given above: admin/rootpassword

To run this example on Windows, the following software packages are needed:

Change Log

ModifiedChangesZentriOS Version
Required
2015-02-03Created2.1+