1. Introduction of the Home Automation project
  2. Part 2: Setting up the Raspberry Pi
  3. Part 3: Building the control box
  4. Part 4: Securing the software
  5. Part 5: Public access to the service
  6. Part 6: Setting up the app


In Part 4: Securing the software we took some steps to secure the Raspberry Pi against attackers. This post shows how to make the Raspberry Pi accessible from any network. Therefore some steps must be undertaken. These include the forwarding of some ports to the Raspberry Pi, managing the change of IP addresses by using a Dynamic Domain Name Service (DDNS) and securing the webserver with an encrypted connection using a Let’s Encrypt certificate.

Port Forwarding

The steps to configure forwarding rules are somehow specific to the router software, but the rules in itself are the same. The goal is to forward four ports to the IP address of your Raspberry Pi:

  • 80 -> Apache2 HTTP
  • 443 -> Apache2 HTTPS
  • 8080 -> Tomcat HTTP
  • 8443 -> Tomcat HTTPS

Dynamic Domain Name Service (DDNS)

Most ISP’s provide only dynamic IP addresses to consumers. To be able to access the webservice in these networks a DDNS must be configured, so a single domain is associated and updated with the external IP address. In this example http://freedns.afraid.org is used, but every other DDNS works similarly. Create a new subdomain and DDNS entry with a free domain and a and your current IP address, which can, for example be checked at https://www.whatismyip.com or at your router’s configurations.

The next step is to create a cron job to update the IP address. I have chosen a time 5 minutes between every update, so the worst case is a down-time of 5 minutes.

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

4,9,14,19,24,29,34,39,44,49,54,59 * * * * sleep 36 ; wget -O - http://freedns.afraid.org/dynamic/update.php?########################################### >> /tmp/freedns_domain_name.log 2>&1 &

Just copy these lines into crontab and replace the # with your individual update parameter. To confirm the functionality just try the command by itself like this:

wget -O - http://freedns.afraid.org/dynamic/update.php?########################################### >> /tmp/freedns_domain_name.log 2>&1 &

Let’s Encrypt Certificate (HTTPS)

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

sudo ./letsencrypt-auto -d ddnsdomain.example.com --redirect --apache -m mail@example.com

If you encounter an error like this:

Had a problem while installing Python packages.

pip prints the following errors:
=====================================================
Collecting ConfigArgParse==0.14.0 (from -r /tmp/tmp.U9XKxwadoL/letsencrypt-auto-requirements.txt (line 12))
  Downloading https://files.pythonhosted.org/packages/55/ea/f0ade52790bcd687127a302b26c1663bf2e0f23210d5281dbfcd1dfcda28/ConfigArgParse-0.14.0.tar.gz
Collecting asn1crypto==0.24.0 (from -r /tmp/tmp.U9XKxwadoL/letsencrypt-auto-requirements.txt (line 14))
  Downloading https://files.pythonhosted.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl (101kB)
...
...
... https://files.pythonhosted.org/packages/54/d1/87999757ce3737b53ed286f30b1bc03e3eed06075da0c0989ebae7f60fff/certbot_nginx-0.39.0-py2.py3-none-any.whl (90kB)
Requirement already satisfied: setuptools>=1.0 in /opt/eff.org/certbot/venv/lib/python2.7/site-packages (from josepy==1.2.0->-r /tmp/tmp.U9XKxwadoL/letsencrypt-auto-requirements.txt (line 90))
THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    pycparser==2.19 from https://www.piwheels.org/simple/pycparser/pycparser-2.19-py2.py3-none-any.whl#sha256=bc15573b7c6edd24407526dbbc7a0bd33d80d8af44231c37f58d73f56ff9cab6 (from -r /tmp/tmp.U9XKxwadoL/letsencrypt-auto-requirements.txt (line 108)):
        Expected sha256 a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3
             Got        bc15573b7c6edd24407526dbbc7a0bd33d80d8af44231c37f58d73f56ff9cab6
=====================================================

Certbot has problem setting up the virtual environment.

We were not be able to guess the right solution from your pip
output.

Consult https://certbot.eff.org/docs/install.html#problems-with-python-virtual-environment
for possible solutions.
You may also find some support resources at https://certbot.eff.org/support/ .

Delete the /etc/pip.conf file as stated in this thread https://community.letsencrypt.org/t/certbot-auto-certificates-fails-while-installing-phyton-packages-with-these-packages-do-not-match-the-hashes/90363/6.

sudo rm /etc/pip.conf

And repeat the process

sudo ./letsencrypt-auto -d ddnsdomain.example.com --redirect --apache -m mail@example.com

sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/cert.pem /opt/tomcat/latest/conf/
sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/chain.pem /opt/tomcat/latest/conf/
sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/privkey.pem /opt/tomcat/latest/conf/

sudo chown -R tomcat:tomcat /opt/tomcat/latest/conf/

sudo nano /opt/tomcat/latest/conf/server.xml

Comment out and adapt the following block in the server.xml file:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateFile="conf/cert.pem"
                 certificateKeyFile="conf/privkey.pem"
                 certificateChainFile="conf/chain.pem" />
        </SSLHostConfig>
    </Connector>

Restart Tomcat

sudo service tomcat restart

Now try to access the REST-API from your local network in a browser:

http://192.168.0.200:8080/HomeAutomationBackend/rest/information/PublicKey

If the public key is not shown try to restart the server

sudo /opt/tomcat/latest/bin/shutdown.sh
sudo /opt/tomcat/latest/bin/catalina.sh run &

It should also be possible to access the domain from outside the network. Be sure to change the network, as the Let’s Encrypt certificate does not work in the LAN!

https://ddnsdomain.example.com:8443/HomeAutomationBackend/rest/information/PublicKey

Renew the Let’s Encrypt Certificates

sudo apt install anacron
sudo nano /etc/anacrontab

Adapt the following line and append it to the anacron configuration.

@monthly        15      letsencrypt.renew       /home/pi/letsencrypt/letsencrypt-auto -d ddnsdomain.example.com --redirect -m mail@example.com --agree-tos --renew-by-default; sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/cert.pem /opt/tomcat/latest/conf/; sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/chain.pem /opt/tomcat/latest/conf/; sudo cp /etc/letsencrypt/live/ddnsdomain.example.com/privkey.pem /opt/tomcat/latest/conf/; sudo chown -R tomcat:tomcat /opt/tomcat/latest/conf/


Congratulations if everything works! The last step is to download and configure the HomeAutomationApp. Read Part 6: Setting up the app to finish this project and control the Remote-Control-Box from everywhere!

Links and Sources