local Certificates

Nowadays it is very easy and quick to get a free SSL certificate with Let's Encrypt. Unfortunately, this only applies to public, registered domains. Sadly, this is not a real solution for the home network. That is why I would like to describe / record here how you can implement SSL for your home network.

What happens with browser queries?

DNS names are read by browsers from right to left. e.g. 

Definition of a domain: Top Level Domain (TLD) - Second Level Domain (SLD) - Subdomain (optional) - Protocol

This ensures that a local search is performed first and that a resolution request is only forwarded to a “resolver” if information is not available locally.

In local home networks, this is always solved on each device with the “/etc/hosts” file ( Microsoft: C:\Windows\System32\drivers\etc\hosts ).

With an increased number of devices in the home network, this management becomes inefficient and error-prone over time!

This is why local DNS resolvers (a device that is announced via DHCP or by manual entry on a device) are also used in home networks if required (typical representatives: bind9, dnsmasq, PI-Hole, AdGuard, Technitium and certainly many others). This is where the wheat is separated from the chaff... You have to master the DNS part of the tools and know what you are doing! So far, none of this has anything to do with http:// or https://!

http:// - https:// Resolution

We want to concentrate on SSL = https://! When the browser has processed the above topic, it checks whether a corresponding web server (e.g. apache2, Nginx, others...) provides an accessible page. AND now it gets interesting!!!! The browser uses the certificate stored by the web server to check / query locally whether a trustworthy root certification authority is stored! And this causes the home network with https & domain name to fail! You can find the standard root certification authorities for:

MAC : /Library/Keychains/System.keychain
Linux : /usr/local/share/ca-certificates
Windows : certmgr.msc

But not for the reader, of course! We take this into our hands and realize the concept for a home network!


Requirements / Recommendations

1. Hardware / Operating System

I would recommend buying a Raspberry PI 4 or 5 and running the PI as a 24/7 server in your home network. This will give you the most cost-effective, reliable hardware possible. Operation with LAN (I would not recommend WLAN!) and “ssh” is sufficient. Personally, I would not set up a Windows-based device for this purpose (nor do I describe it)!

2. Software

3. additional Software

Since the SSL implementation is so closely linked to DNS mechanisms, I would also recommend a DNS resolver. Recommendation: Technitium! If PI-Hole & AdGuard fans are now shaking their heads, please watch this video:

4. Decide on an internal domain name

Typically, if you operate an AVM Fritz Box, you can create a "fritz.box" domain. Then the names would be e.g. nas.fritz.box, router.fritz.box, repeater.fritz.box, etc. However, this does not necessarily reflect your home network.  It would therefore be better to use a name such as a unique, self-explanatory name, e.g. zuhause,lan or thomas.home.

Please do not use a .local domain, as .local is used by local mDNS services and can lead to "confusion", i.e. unreachability or strange behavior in the network on some devices!

Create Certificates

All subsequent entries, commands, etc. are required in the terminal of the PI OS!

 Depending on which instructions you have already read on the Internet, different directories are always suggested or used for storing the certificates. I would suggest that you create a directory that you always use to create and edit your own certificates and specify as the storage location in the browser 'VirtualHost' blocks.

For our example we use:

TLD = lan
SLD = home
subdomain = nas

1. Create a trusted root certification authority

1.1 Create a private key for the root certification authority

command: "openssl genrsa -des3 -out <SLD, ohne TLD>.key 2048"

1.2 Create the root certificate

<> = you can fill in, but you don't have to!

2. Create certificates based on the root certificate

You must repeat this procedure for each subdomain (mostly devices, e.g. NAS)!

2.1 Create a private key for the certificate

command: "openssl genrsa -out <subdomain.SLD.TLD>.key 2048"

2.2 Create a CSR (Code Signing Request)

command: "openssl req -new -key <subdomain.SLD.TLD>.key -out <subdomain.SLD.TLD>.csr"

2.3 Create an X509 V3 certificate extension configuration file

command: "nano <subdomain.SLD.TLD>.ext"

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = <subdomain.SLD.TLD>
2.4 create the certificate

(with our CSR, the private key of the CA, the CA certificate and the configuration file)

command: "openssl x509 -req -in <subdomain.SLD.TLD>.csr -CA <SLD>.pem -CAkey <SLD>.key -CAcreateserial -out <subdomain.SLD.TLD>.crt -days 3650 -sha256 -extfile <subdomain.SLD.TLD>.ext"

hey, you "perseverers...", you actually made it... well, yes - almost!  😇  The root certificate still has to be distributed so that the browsers can successfully validate your certificate and the web server still needs the information about which certificate it should use, but then, I promise, "you'll get along with your neighbor" 😎 

Distribute Certificates

1. Root Certificate

The root certificate must be installed on all devices from which you want to access / browse your web server! It is therefore advisable to have your "certificate directory" connected as a drive on the respective devices!

1.1 MAC

command: "sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" <Verzeichnis><SLD>.pem

1.2 Linux

command: "sudo cp <Verzeichnis><SLD>.pem /usr/local/share/ca-certificates/<SLD>.crt"

command: "sudo update-ca-certificates"

1.3 Windows

command: "WIN + R - Eingabe: certmgr.msc" - OK

certmgr01.png

NEXT

certmgr02.png

hope you can "click together" the rest yourself ! 😎

2. Web Server Certificate

2.1 Apache

Please make sure that you have activated "a2enmod ssl"!

xampp01.png

<VirtualHost *:443>
   ServerName <>
   DocumentRoot <>

   SSLEngine on
   SSLCertificateFile <Verzeichnis>/<subdomäne.SLD.TLD>.crt
   SSLCertificateKeyFile <Verzeichnis>/<subdomäne.SLD.TLD>.key
</VirtualHost>

in the case of XAMPP, stop and restart Apache!

2.1 NGINX
server {
    listen              443 ssl;
    server_name         <subdomäne.SLD.TLS>;
    ssl_certificate     <Verzeichnis><subdomäne.SLD.TLS>.crt;
    ssl_certificate_key <Verzeichnis><subdomäne.SLD.TLS>.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

But now you've done it!!!!  😁 Please understand that this is about local certificates and not how to generate a PI or how to set up a web server or, or, or, or... The only thing left to complete the picture is the actual side issue of DNS resolvers. Even if everything has been done correctly, it can happen that your domain is not accessible in your browsers....  😰 So here's a final chapter DNS Resolver! Hey, and of course a "Gutzi" for hanging in there. Have a look at "Gutzi" !!!!! 😎

DNS Resolver

To really and fully utilize your SSL environment you need a local DNS resolver that knows your home network...

There are various ways to successfully implement this technology (DNS), even with "in-house knowledge".

1. hosts File

You can define your devices in a hosts file and, for example, distribute this manually to all hosts files of the affected devices. However, this can quickly turn into time-consuming work and is prone to errors! Furthermore, there are devices (e.g. IOT, network devices, TVs) that do not offer manual hosts management at all.

2. Resolver

The standard tools such as bind9, dnsmasq could be considered here. However, availability is questionable depending on the operating system. In addition, "failure" is usually pre-programmed, as the technology and tools should be, let's say, semi-professional.

3. Hybrid Applications

The best-known tools here are PI-Hole and AdGuard. Please keep in mind that these tools were created for a different reason: Ad Blocker!!!!!! Due to the concept (foundation, structure), it is becoming increasingly difficult for the tools to follow modern DNS concepts, i.e. to implement the technologies (e.g. DNSSEC) with all possible methods (e.g. DNS-over-HTTPS or DNS-over-QUIC).

A currently less well-known but all the more remarkable application is Technitium. It combines all the "home computer scientist" requirements of a modern, customizable, sustainable DNS resolver solution. It can provide ad blocking with flexibility and customizability, a really easy to set up and maintain resolver implementation and, if desired, an extensive analysis and reporting environment. Hm, the only disadvantage could be the application language: English. However, this is very technical and English is always better than any botched German translations. The linked video is also very helpful!!!!!

Dashboard

technitium01.png

DNS Resolver

technitium02.png

Ad Blocking

technitium03.png

my recommendation: Technitium

Gutzi

Depending on the size of your home network, the "Create certificates" steps have to be carried out continuously, which can be annoying. Especially if you want to decide on a new domain name after some time... There are also devices, e.g. AVM routers or apps (e.g. Plex) that only accept a .pfx (PKCS#12 standard)! Hm, and we're already out of luck  😤 ...

1. all in one step, oups ...script

For all those who have implemented the realization as recommended by me on a PI or Linux device, here is a script that is quickly adapted and then takes your domain as a parameter and automatically creates all the necessary files.

8-tung! The root certificate must exist / have already been created! and be located in the same directory as the script.

#!/bin/bash

#Required
domain=$1
commonname=$domain

#Change to your company details
country=<>
state=<>
locality=<>
organization=<>
organizationalunit=<>
email=<>

if [ -z "$domain" ]
then
    echo "Argument not present."
    echo "Useage $0 [common name]"

    exit 99
fi

echo "1. generating .key for $domain"
#generate a .key
openssl genrsa -out $domain.key 2048
echo "successful!"
echo ""

echo "2. generating .csr for $domain"
#generate a .csr
openssl req -new -key $domain.key -out $domain.csr \
    -subj "/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalunit/CN=$commonname/emailAddress=$email"
echo "successful!"
echo ""


echo "3. generating .ext for $domain"
cat > $domain.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = $domain

EOF
echo "successful!"
echo ""

echo "4. creating .csr for $domain"
openssl x509 -req -in $domain.csr -CA <SLD>.pem -CAkey <SLD>.key -CAcreateserial -out $domain.crt -days 3650 -sha256 -extfile $domain.ext
echo "successful!"
echo ""

echo "5. creating .pem for $domain"
cat $domain.crt $domain.key > $domain.pem
echo "successful!"
echo ""

echo "6. creating .pfx for $domain"
openssl pkcs12 -export -in $domain.pem -out $domain.pfx
echo "successful!"
echo ""
echo "---------------------------"
echo "-------- All Set! ---------"
echo "---------------------------"
echo

DONE!

Execute with command: "./<sriptname>.sh <subDomäne.SLD.TLD>"  🤗