Home network security – Part 2: HTTPS and TLS hardening

Home network security – Part 2: HTTPS and TLS hardening

In May, we showed you the basic configuration of our Turris Omnia. The Omnia is a Czech router which runs open-source software and is mostly made of open hardware components. In this article, we configure the Omnia to use HTTPS-only and harden its TLS configuration.

Contents

  1. The defaults
  2. Requirements
  3. Step by step from HTTP to hardened HTTPS
  4. Summary
  5. Sources
  6. Changelog

Always stay in the loop!
Subscribe to our RSS/Atom feeds.

The defaults

By default, our Turris Omnia is reachable via port 80 (HTTP) and 22 (SSH). HTTP is unencrypted. This means that other devices in our network can monitor and read the network traffic between a computer and the Omnia. Furthermore, we can’t be sure that we are really connected with our Omnia when connecting to 192.168.1.1. There is no cryptographic proof.

The solution: Get a certificate, enable HTTPS (port 443) and disable HTTP. Currently, Turris OS shows you a warning that you should enable HTTPS. You can enable this configuration which uses a Turris certificate and not so strict TLS cipher suites.

Subsequently, we want to use our own certificate and only strong/modern cipher suites. If you don’t own a Turris Omnia, you can still try to find according guides for your home router.

Requirements

This time, we need:

  • our Turris Omnia which is connected with our computer and the internet
  • an SSH client on our computer
  • time (if you want to use DHE instead of ECDHE)
  • tools like nmap, sslyze or sslscan

Step by step from HTTP to hardened HTTPS

Our plan is really straightforward: Our Omnia runs lighttpd for HTTP/HTTPS connections. We have to generate a certificate, change the configuration of lighttpd and restart our router.

Be aware: It is possible that you misconfigure lighttpd. Then you will be unable to connect to your Omnia via HTTP/HTTPS. However, you can always fall back to SSH which remains unaffected by the following guide and reset your lighttpd configuration.

Step 1: Connect via SSH

The first step is to establish an SSH connection between your computer and your Omnia. This requires that you installed an SSH client on your device (if you use Linux, it is very likely that you have it installed). Windows users can use PuTTY. The password is the “advanced password” which you can configure separately in Turris OS.

The simple command here is: ssh root@[turris router ip].

Follow us on Mastodon:
@infosechandbook

Step 2: Generate strong DH parameters

LEGACY ONLY: If you want to use DHE (Diffie–Hellman key exchange) later, you probably want to generate strong DH parameters for key exchange. DHE is only needed if you use legacy web browsers which do not support ECDHE (Elliptic Curve Diffie–Hellman key exchange). We recommend that you try to use ECDHE only. ECDHE is faster and requires less resources than DHE. You can skip this step if you only want to use ECDHE.

If you still want to use DHE-based cipher suites, go to the “certs” folder: cd /etc/ssl/certs. Then initiate the generation of strong DH parameters using openssl: openssl dhparam -out dhparam.pem 4096.

Generating 4096 bit DH parameters can take several hours!

Step 3: Generate your certificate

The next step is to create a new folder to store our certificate: mkdir -p /etc/lighttpd/certs. After that, go to the new folder: cd /etc/lighttpd/certs.

Now, we generate our 4096 bit RSA certificate using openssl again. In the following, we use the same file to store the private key and public certificate. This is necessary since most web servers expect the private key to be chained to the public certificate:

Enter: openssl req -newkey rsa:4096 -x509 -keyout rsa-cert.pem -out rsa-cert.pem -subj '/CN=192.168.1.1' -days 365 -nodes

Explanation:

  • openssl req is the PKCS#10 certificate request and certificate generating utility
  • -newkey rsa:4096 creates a new certificate request (RSA 4096 bit) and a new private key
  • -x509 outputs a self signed certificate instead of a certificate request
  • -keyout rsa-cert.pem writes the newly created private key to “rsa-cert.pem”
  • -out rsa-cert.pem writes remaining output (public certificate) to “rsa-cert.pem”
  • -subj '/CN=192.168.1.1' sets the Common Name of the certificate to “192.168.1.1”
  • -days 365 means that the self-signed certificate will be valid for the next 365 days (1 year)
  • -nodes avoids that the private key becomes encrypted (this is optional)

The result is one single file “rsa-cert.pem” in “/etc/lighttpd/certs” which contains private key and public certificate. Set read permissions for root only: chmod 400 rsa-cert.pem.

Step 4: Harden your TLS configuration

We generated our RSA certificate. Now we configure TLS. Simply using the defaults here results in a warning when we test our connection:

Warning that DH and EC parameters are too weak.
Warning that DH and EC parameters are too weak. (🔍 Zoom in)

The result shows that weak DH parameters and a weak elliptic curve are in use. There are also several cipher suites without DHE/ECDHE. Let’s change this. Open the TLS configuration of lighttpd using the vi editor: vi ../conf.d/ssl-enable.conf. We are using Vim here. If you never used it before, read some beginner’s guides or use your favorite command line editor.

After opening the ssl-enable.conf, we change the configuration to:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# IPv4 configuration
$SERVER["socket"] == ":443" {
        ssl.engine = "enable"
        ssl.pemfile = "/etc/lighttpd/certs/rsa-cert.pem"
        ssl.honor-cipher-order = "enable"
        ssl.disable-client-renegotiation = "enable"
        # Modern cipher suites (ECDHE only, no TLS 1.0 or TLS 1.2)
        ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA- CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
        # Legacy cipher suites (including DHE, TLS 1.0 and TLS 1.2)
        # ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDH"
        ssl.use-compression = "disable"
        setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=63072000; includeSubDomains; preload", "X-     Frame-Options" => "DENY", "X-Content-Type-Options" => "nosniff" )
        ssl.use-sslv2 = "disable"
        ssl.use-sslv3 = "disable"
        # If your web browser supports secp521r1, use it instead of secp384r1.
        ssl.ec-curve = "secp384r1"
        # Legacy DH param file (uncomment, if you use legacy cipher suites)
        # ssl.dh-file = "/etc/ssl/dhparam.pem"
}

# IPv6 configuration (you only need this if you use IPv6 in your home network)
$SERVER["socket"] == "[::]:443" {
        ssl.engine = "enable"
        ssl.pemfile = "/etc/lighttpd/certs/rsa-cert.pem"
        ssl.honor-cipher-order = "enable"
        ssl.disable-client-renegotiation = "enable"
        # Modern cipher suites (ECDHE only, no TLS 1.0 or TLS 1.2)
        ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA- CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
        # Legacy cipher suites (including DHE, TLS 1.0 and TLS 1.2)
        # ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDH"
        ssl.use-compression = "disable"
        setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=63072000; includeSubDomains; preload", "X-     Frame-Options" => "DENY", "X-Content-Type-Options" => "nosniff" )
        ssl.use-sslv2 = "disable"
        ssl.use-sslv3 = "disable"
        # If your web browser supports secp521r1, use it instead of secp384r1.
        ssl.ec-curve = "secp384r1"
        # Legacy DH param file (uncomment, if you use legacy cipher suites)
        # ssl.dh-file = "/etc/ssl/dhparam.pem"
}

# Redirect HTTP to HTTPS
$HTTP["scheme"] == "http" {
        $HTTP["host"] =~ ".*" {
                url.redirect = (".*" => "https://%0$0")
        }
        setenv.add-environment = ( "HTTPS" => "on" )
}

Please note that cipher suites which need an ECDSA certificate are enabled now, however, they won’t be in use until you also provide an ECDSA certificate. Additionally, CHACHA20-POLY1305-based cipher suites can only be used if your Turris Omnia uses OpenSSL 1.1.0 or higher.

Step 5: Restart and test your connection

After saving, we restart lighttpd: /etc/init.d/lighttpd restart. Try to connect to your Omnia using your web browser. Your router should change the connection to HTTPS.

Errors like “NET::ERR_CERT_AUTHORITY_INVALID” or “MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT” are normal: We are using a self-signed certificate here. Self-signed certificates are always untrusted by our web browsers. This is normal behavior.

You can validate your configuration using nmap, sslyze and/or sslscan:

  • nmap --script +ssl-enum-ciphers -n -p 443 [turris omnia ip]
  • sslyze --regular [turris omnia ip]
  • sslscan [turris omnia ip]

The following screenshot shows the final configuration using modern cipher suites and TLS 1.2 only:

This is the final configuration using modern cipher suites and TLS 1.2 only.
This is the final configuration using modern cipher suites and TLS 1.2 only. (🔍 Zoom in)

If you uncommented legacy cipher suites, you will likely see the following cipher suites:

This is the final configuration using legacy cipher suites as well as TLS 1.0 and TLS 1.1.
This is the final configuration using legacy cipher suites as well as TLS 1.0 and TLS 1.1. (🔍 Zoom in)

This article is part of the "Home network security" series.
Read other articles of this series.

Summary

This configuration example enables HTTPS-only and enforces strong TLS cipher suites. One weak point remains: We are using our own, untrusted certificate. However, this is sufficient for our purposes since the certificate is only in use for the local area network. Moreover, you can try to configure an ECDSA certificate instead of the RSA certificate.

To harden your SSH configuration, you can check our Web server security series part 1.

In part 3a, you can read about using your Turris Omnia as network-attached storage which is a big plus for privacy.

Sources

Changelog

  • Dec 8, 2018: Updated code for better understanding, added information about filenames in use, added modern TLS configuration.

See also