Let's Encrypt Appliances!

Let's encrypt is incredibly exciting. For far too long, SSL has been too hard (manual process) and too expensive. Now everyone can get the green lock in the browser everywhere! for free! automagically! ish!

As an IT technician, I've long been frustrated with the extra steps required to bypass self-signed certificates on various appliances. The proper solution was to import the CA to your browser (for every browser the appliance is accessed from), but ain't nobody got time for all that! So the result was insecurity because technicians become accustomed to regularly clicking-through invalid certificates.

The browser screams STOP! but we all click-through because we're just trying to maintain an appliance with a self-signed certificate.

Let's encrypt isn't a solution for every appliance because aside from requiring a FQDN, it basically requires root access to the appliance in order to verify the domain that will be used by the certificate, but even with these constraints LE is a fantastic step in an awesome direction!

This is a quick example of steps taken, decisions made, and things discovered while working to get a green lock on an EdgeMax router. It's a very fast run-through; I hope to refine this write-up as time permits.

First, let's marvel at the result:

Then let's look at how we're going to get this certificate:


1: update webroot of router

When let's encrypt generates a certificate, it verifies the domain is pointed to the appliance by adding a file to the web root. For us to be able to do this, we'll want to create the appropriate directory and make it owned by our user so that we can edit the files it contains.

SSH into the router and do:

sudo mkdir /var/www/htdocs/.well-known  
sudo chown YOU:users /var/www/htdocs/.well-known  



2: adjust the lighthttp server config

EdgeMax routers use lighthttp to serve the router GUI, but the default config won't work with the directory we just created. Moreover, when let's encrypt verifies the domain, it'll use http, which doubly won't work.

Use vi (as root) to edit the config file and make the following changes

/etc/lighttpd/lighttpd.conf:

# In the url.rewrite-once block, find the following line:
"^(/(lib|media|ws|tests|)/.*)" => "$0",
# and change it to:
"^(/(lib|media|ws|tests|\.well-known)/.*)" => "$0",

# in the $HTTP["scheme"] == "http" block, find the following line:
$HTTP["url"] !~ "^(/index.php/error/)" {
# and change it to:
$HTTP["url"] !~ "^((/index\.php/error/)|(/\.well-known/.*))" {



/etc/lighthttpd/conf-enabled/10-ssl.conf:

# add this line to to both the IPv4 and v6 SSL blocks:
ssl.ca-file = "/etc/lighttpd/fullchain.pem"  



3: restart lighthttp server

kill -SIGINT $(cat /var/run/lighttpd.pid)  
/usr/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf

If you haven't already done so, you'll need to open port 80 so that let's encrypt can access the appliance for the purpose of verifying the new certificate.


That's it for changes on the router. Continue working from the PC that will communicate with let's encrypt on behalf of the router.



4: install let's encrypt

(if you haven't already)

apt-get -y install git  
git clone https://github.com/letsencrypt/letsencrypt  



5: mount the router's webroot

For this, we're using sshfs. If you're not already a member of the fuse group, you probably need to add yourself to it

sudo usermod -aG fuse YOU  

and then you would need to refresh your session (logout/login). You might also need to edit /etc/fuse.conf to ensure user_allow_other is enabled.

now we can mount the webroot:

mkdir /tmp/router  
sshfs -o allow_root YOU@ROUTER:/var/www/htdocs /tmp/router  



6: obtain a certificate

obviously, example.com needs to be changed accordingly.

# cd to the letsencrypt source directory:
cd letsencrypt  
# obtain the certificate:
./letsencrypt-auto certonly -a webroot --agree-tos \
--webroot-path=/tmp/router -d example.com



7: install the certificate

OK! almost done!

concatenate these two files:

/etc/letsencrypt/live/example.com/cert.pem /etc/letsencrypt/live/example.com/privkey.pem

and install them on the router to /etc/lighttpd/server.pem

also upload /etc/letsencrypt/live/example.com/fullchain.pem to /etc/lighthttpd on the router while being sure to keep the permissions 0400.

Then restart the lighthttpd server again (as above)! now when you browse to your router using the domain, you'll have a swanky green lock courtesy of let's encrypt!

Remember: let's encrypt certificates must be refreshed frequently. I'd like to refine this post and extend it to include an automatic refresh script, but that might not happen for a while...