rand256 / valetudo

Valetudo RE - experimental vacuum software, cloud free
Apache License 2.0
667 stars 73 forks source link

[RFC] Implement enforced https server if key and cert files available #314

Closed jneuhauser closed 3 years ago

jneuhauser commented 3 years ago

This pr is only a Request for Comments.

I think to have the option for encrypted web gui is a wanted feature for valetudo if we dont trust our network or want to open the web gui to the internet.

I know that the code isn't perfect and can be optimised, but this is only a quick proof of concept.

Any thoughts about such a feature and how we should implement it?

Binary size increases by about 72 KB:

Haven't checked for any ram usage/constraints so far...

jneuhauser commented 3 years ago

If this is a wanted feature, I will also implement providing static contents of the "/.well-known/acme-challenge" directory to get signed certificates from lets encrypt with the great bash acme client dehydrated.

A simple working example is here: jneuhauser/valetudo/tree/acme-http-01

jneuhauser commented 3 years ago

For those who want to test https without compiling Valetudo RE themselves, I have included a ready-to-use binary file below. valetudo_re_https.tar.gz

Step-by-step instructions

All you have to do is place the attached binary in /usr/local/bin, create a self-signed cert and key and reboot your robo. After that the valetudo RE web gui does listen on the default ports 80/http and 443/https. All request to the unecrypted port 80/http will be redirected to the encrypted 443/https port. If you wanna open your valetudo RE web gui to the internet, please enable the webserver basic authentication before.

Connect to your vacuum over ssh with putty or for example:

user@desktop-pc:~# ssh root@vacuum.lan

Backup and replace current valetudo with attached one

root@rockrobo:~# mv /usr/local/bin/valetudo /usr/local/bin/valetudo.bak
root@rockrobo:~# wget -O - https://github.com/rand256/valetudo/files/5431833/valetudo_re_https.tar.gz | tar xz -C /usr/local/bin

Create self-signed ssl cert and key to enable enforced https

root@rockrobo:~# mkdir -p /mnt/data/valetudo
root@rockrobo:~# cd /mnt/data/valetudo
root@rockrobo:~# openssl genrsa -out key.pem 4096
root@rockrobo:~# openssl req -new -key key.pem -out csr.pem
root@rockrobo:~# openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem
root@rockrobo:~# rm csr.pem

Reboot your robot

root@rockrobo:~# reboot

Restore original valetudo RE and delete certificate and key

root@rockrobo:~# mv /usr/local/bin/valetudo.bak /usr/local/bin/valetudo
root@rockrobo:~# rm /mnt/data/valetudo/{cert,key}.pem
root@rockrobo:~# reboot
rand256 commented 3 years ago

This seems to be working, but in case of self-signed certificates I suppose we need to change

        this.app.use(forceSsl);

to something like

        this.app.use((req, res, next) => {
            if (['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(req.ip)) {
                next();
            } else {
                forceSsl(req, res, next);
            }
        });

to add an exception for local connections, cause otherwise the firmware would be unable to upload the map data to valetudo. Mine was definitely unable to do that at least.

jneuhauser commented 3 years ago

You're totally right. Good catch... Tested the map with valetudo RE running on the device with a valid let's encrypt certificate only.

Should we expose some configurations for this "feature" or are there any other suggestions for improvements? Probably i will add a simple how to about dehydrated and let's encrypt...

I've added the serving of the acme-challenge directory as own commit and updated the binary in my comment before for testing by the users. So the directory /mnt/data/valetudo/acme-challenge gets served as http(s)://ip_or_domain/.well-known/acme-challenge if it exists. Tested this by using the dehydrated acme client with WELLKNOWN=/mnt/data/valetudo/acme-challenge set.

rand256 commented 3 years ago

I guess this feature could be left without configuration, as it works just straight: you put cert files - you get https mode, you remove cert files - you get plain http mode. That's it.

Maybe some integration of letsencrypt update scripts could be added to valetudo's web interface, but... I guess there won't be actually a lot of people who would set up a port forwarding from an external IP to their device, and otherwise it won't work. So just a howto with instructions would be enough I suppose.