Blog |Follow Nick on Twitter| About
 

I recently purchased a Teltonika RUT240 to use as a home 4G router, and very quickly I got irritated by the self-signed certificate on the WebUI! 😬 It's been a very long time since I've needed to really delve back into let's encrypt, certbot on centos meets my webserver needs and for home network previously I didn't have much else.

The Teltonika RUT240 is built on a very old version of OpenWRT therefore prebuilt package options are limited; I'd heard good things about acme.sh as it allows DNS based challanges. For internal devices, DNS based certificated issuance are the way forward, it allows let's encrypt to issue you a certificate without you having to run the relevant web server (no port 80/443 needing to be opened, all the traffic is outbound).

Getting going on RutOS was surprisingly easy, of course to start with you need to SSH onto your box, achme.sh recommend running as root so that's fine for me.

Run curl https://get.acme.sh | sh of course you shouldn't run/pipe random shell scripts into a root shell, so have a read of the code, read some of the github issues/feedback acme.sh is well established, so we're good to go.

root@rut240:~# curl https://get.acme.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   775    0   775    0     0    168      0 --:--:--  0:00:04 --:--:--   208
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  202k  100  202k    0     0   150k      0  0:00:01  0:00:01 --:--:--  157k
[Tue Dec  8 17:43:58 GMT 2020] Installing from online archive.
[Tue Dec  8 17:43:58 GMT 2020] Downloading https://github.com/acmesh-official/acme.sh/archive/master.tar.gz
[Tue Dec  8 17:44:04 GMT 2020] Extracting master.tar.gz
[Tue Dec  8 17:44:14 GMT 2020] It is recommended to install socat first.
[Tue Dec  8 17:44:14 GMT 2020] We use socat for standalone server if you use standalone mode.
[Tue Dec  8 17:44:14 GMT 2020] If you don't use standalone mode, just ignore this warning.
[Tue Dec  8 17:44:14 GMT 2020] Installing to /root/.acme.sh
[Tue Dec  8 17:44:16 GMT 2020] Installed to /root/.acme.sh/acme.sh
[Tue Dec  8 17:44:17 GMT 2020] No profile is found, you will need to go into /root/.acme.sh to use acme.sh
[Tue Dec  8 17:44:24 GMT 2020] Installing cron job
[Tue Dec  8 17:44:24 GMT 2020] OK
[Tue Dec  8 17:44:24 GMT 2020] Install success!
root@rut240:~# 

RutOS runs the ash shell, so next up you need to tweak (or create) your /root/.profile file, I'm using the cloudflare DNS challange so mine looks like this (replace the xxx with your details)...

root@rut240:~# cat /root/.profile
export CF_Token="xxxx"
export CF_Account_ID="xxxx"
export CF_Zone_ID="xxx"

. "/root/.acme.sh/acme.sh.env"
root@rut240:~# 

Close your SSH session and re-log back in, everything should now be ready to go.

This badboy is the command you want to run, but before you do, take a backup of your old self-signed cert & key (/etc/uhttpd.crt & /etc/uhttpd.key)... you know, just in case!

acme.sh --force --issue --dns dns_cf -d rut240.linickx.com --fullchainpath /etc/uhttpd.crt --keypath /etc/uhttpd.key  --reloadcmd "/etc/init.d/uhttpd restart" --log

Tweak as needed, replace rut240.linickx.com with the FQDN you want to use if you're not on cloudflare select a different provider.

If all goes well, you'll get something similar to this...

[Wed Dec  9 09:09:20 GMT 2020] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Wed Dec  9 09:09:21 GMT 2020] Single domain='rut240.linickx.com'
[Wed Dec  9 09:09:22 GMT 2020] Getting domain auth token for each domain
[Wed Dec  9 09:09:33 GMT 2020] Getting webroot for domain='rut240.linickx.com'
[Wed Dec  9 09:09:34 GMT 2020] rut240.linickx.com is already verified, skip dns-01.
[Wed Dec  9 09:09:34 GMT 2020] Verify finished, start to sign.
[Wed Dec  9 09:09:34 GMT 2020] Lets finalize the order.
[Wed Dec  9 09:09:34 GMT 2020] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/1234/1234'
[Wed Dec  9 09:09:37 GMT 2020] Downloading cert.
[Wed Dec  9 09:09:37 GMT 2020] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/abc123'
[Wed Dec  9 09:09:45 GMT 2020] Cert success.
-----BEGIN CERTIFICATE-----
xxx
-----END CERTIFICATE-----
[Wed Dec  9 09:09:45 GMT 2020] Your cert is in  /root/.acme.sh/rut240.linickx.com/rut240.linickx.com.cer 
[Wed Dec  9 09:09:45 GMT 2020] Your cert key is in  /root/.acme.sh/rut240.linickx.com/rut240.linickx.com.key 
[Wed Dec  9 09:09:45 GMT 2020] The intermediate CA cert is in  /root/.acme.sh/rut240.linickx.com/ca.cer 
[Wed Dec  9 09:09:45 GMT 2020] And the full chain certs is there:  /root/.acme.sh/rut240.linickx.com/fullchain.cer 
[Wed Dec  9 09:09:46 GMT 2020] Installing key to:/etc/uhttpd.key
[Wed Dec  9 09:09:46 GMT 2020] Installing full chain to:/etc/uhttpd.crt
[Wed Dec  9 09:09:46 GMT 2020] Run reload cmd: /etc/init.d/uhttpd restart
[Wed Dec  9 09:09:47 GMT 2020] Reload success

A couple of points to make about that output... in the command the post hook restarts the RutOS WebUI ("/etc/init.d/uhttpd restart) so as soon as it's finished it should just work, also I'm on a bit of a flaky 4G connection, you'll see "already verified" in my output, the first time I ran these I got the following errors..

[Tue Dec  8 18:01:51 GMT 2020] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Tue Dec  8 18:02:02 GMT 2020] Create account key ok.
[Tue Dec  8 18:02:03 GMT 2020] Registering account: https://acme-v02.api.letsencrypt.org/directory
[Tue Dec  8 18:02:19 GMT 2020] Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 35
[Tue Dec  8 18:02:32 GMT 2020] Registered
[Tue Dec  8 18:02:33 GMT 2020] ACCOUNT_THUMBPRINT='xxx'
[Tue Dec  8 18:02:33 GMT 2020] Creating domain key
[Tue Dec  8 18:02:38 GMT 2020] The domain key is here: /root/.acme.sh/rut240.linickx.com/rut240.linickx.com.key
[Tue Dec  8 18:02:38 GMT 2020] Single domain='rut240.linickx.com'
[Tue Dec  8 18:02:39 GMT 2020] Getting domain auth token for each domain
[Tue Dec  8 18:02:49 GMT 2020] Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 35
[Tue Dec  8 18:02:49 GMT 2020] Getting webroot for domain='rut240.linickx.com'
[Tue Dec  8 18:02:49 GMT 2020] get to authz error.
[Tue Dec  8 18:02:49 GMT 2020] _authorizations_map=',
'
[Tue Dec  8 18:02:49 GMT 2020] Please add '--debug' or '--log' to check more details.
[Tue Dec  8 18:02:49 GMT 2020] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh
root@rut240:~#

I didn't do anything to fix it, I simply went to bed and tried the next morning! 😂

Renewals should be already taken care of by acme, crontab -l shows a job already setup, I'll update this post if it doesn't work!

References:

  • https://community.teltonika-networks.com/10995/pem-ca-changed-https-ui-not-updating-certificate?show=11013#a11013
  • https://www.jamesridgway.co.uk/auto-renewing-ssl-certificate-unifi-cloud-key-lets-encrypt-cloudflare-dns-validation/

 

 
Nick Bettison ©