Skip to content

Instantly share code, notes, and snippets.

@davidbalbert
Last active September 23, 2024 13:16
Show Gist options
  • Save davidbalbert/6815258 to your computer and use it in GitHub Desktop.
Save davidbalbert/6815258 to your computer and use it in GitHub Desktop.
How to install custom SSL certificates on an ASUS RT-N66U running asuswrt-merlin
###########################################
# IMPORTANT NOTE:
#
# As of asuswrt-merlin 380.67 Beta, you
# can now configure SSL certificates from
# the Webui, making these instructions
# unnecessary.
###########################################
# First, enable SSH in the Administration->System tab.
# Then log in to the device.
# Verify that https_crt_save is off
admin@RT-N66U:/tmp/home/root# nvram get https_crt_save
0
# Enable https_crt_save and verify that it was set correctly
admin@RT-N66U:/tmp/home/root# nvram set https_crt_save=1
admin@RT-N66U:/tmp/home/root# nvram get https_crt_save
1
# Write your custom key and certificate to the ephemeral file system.
# Note that these files will not be preserved on restart.
admin@RT-N66U:/tmp/home/root# cat >/etc/key.pem
# paste in key
admin@RT-N66U:/tmp/home/root# cat >/etc/cert.pem
# paste in cert
# Verify https_crt_file is empty
admin@RT-N66U:/tmp/home/root# nvram get https_crt_file
admin@RT-N66U:/tmp/home/root#
# Restart httpd. When httpd starts up with https_crt_save enabled, it does the
# following: If /etc/cert.pem and /etc/key.pem exist, it tars them together and
# saves them in https_crt_file. If they do not exist (this would be the case
# on reboot) and https_crt_file exists, httpd will extract the contents of
# https_crt_file. You can see how this works in the start_ssl function here:
# https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/httpd/httpd.c
admin@RT-N66U:/tmp/home/root# service restart_httpd
# Ensure https_crt_file is now full
admin@RT-N66U:/tmp/home/root# nvram get https_crt_file
# ...snip...
# Reboot AP to make sure cert is put back on boot
admin@RT-N66U:/tmp/home/root# reboot
@adorobis
Copy link

adorobis commented Sep 2, 2024

Maybe try updating your firmware? I have RT-AC58U with 3.0.0.4.382_52504 firmware and here is the full script that works for me:

#!/bin/sh
rm ~/router.sh
cat <<EOT >> router.sh
#!/bin/sh
cd /etc
ls *.pem
rm *.pem
nvram set https_crt_save=0
nvram unset https_crt_file
service restart_httpd
echo "httpd restarted"
nvram unset https_crt_file
service restart_httpd
echo "httpd restarted"
nvram get https_crt_file
sleep 20
ls *.pem
rm *.pem
nvram set https_crt_save=1
cat <<EOT >> cert.pem
EOT
cat /etc/certificates/new/letsencrypt.crt >> router.sh
echo "" >> router.sh
echo "EOT" >> router.sh
cat <<EOT >> router.sh
cat <<EOT >> key.pem
EOT
cat /etc/certificates/new/letsencrypt.key >> router.sh
echo "EOT" >> router.sh
cat <<EOT >> router.sh
rm server.pem
cat key.pem > server.pem
cat cert.pem >> server.pem
service restart_httpd
nvram get https_crt_file
EOT
cat router.sh | ssh -o StrictHostKeyChecking=no \
 -p 4092 -i privatekey.pem [email protected]

@janedenone
Copy link

Unfortunately, 3.0.0.4.388_24621 is the latest firmware for my ZenWiFi AX (XT8) device, according to Asus' servers.

@jmontleon
Copy link

Something changed from some point after I wrote my comment above. But with what is current for my router (3.0.0.4.388_24329-g5906523) I was able to replace the certs.

I have this written down now.

mkdir tmp/etc
cd tmp

cat << EOF > etc/cert.pem
...
EOF

cat << EOF > etc/key.pem
...
EOF

tar -C / -czf /jffs/cert.tgz etc/cert.pem etc/key.pem
nvram set https_crt_save=1
service restart_httpd

Mostly, it looks like the difference is nvram set https_crt_save=1.

@janedenone
Copy link

This is what I do (after creating cert.pem and key.pem in /jffs/):

cd /jffs/
rm cert.tgz
tar -czf cert.tgz cert.pem key.pem
nvram set https_crt_save=1

At this point nvram get https_crt_file returns nothing, and as soon as I execute service restart_httpd, the file cert.tgz gets overwritten by the system.

@janedenone
Copy link

janedenone commented Sep 3, 2024

Maybe try updating your firmware? I have RT-AC58U with 3.0.0.4.382_52504 firmware and here is the full script that works for me:

...

If I execute the steps manually, this happens:

admin@ZenWiFi_XT8-A5C0:/tmp/etc# ls *.pem
cacert.pem      cacert_gen.pem  cakey.pem       cakey_gen.pem   cert.pem        cert_gen.pem    key.pem         key_gen.pem     server.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# rm *.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram set https_crt_save=0
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram unset https_crt_file
admin@ZenWiFi_XT8-A5C0:/tmp/etc# service restart_httpd

Done.
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram unset https_crt_file
admin@ZenWiFi_XT8-A5C0:/tmp/etc# service restart_httpd

Done.
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram get https_crt_file
admin@ZenWiFi_XT8-A5C0:/tmp/etc# sleep 20
admin@ZenWiFi_XT8-A5C0:/tmp/etc# ls *.pem
cacert.pem      cacert_gen.pem  cakey.pem       cakey_gen.pem   cert.pem        cert_gen.pem    key.pem         key_gen.pem     server.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# rm *.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram set https_crt_save=1
admin@ZenWiFi_XT8-A5C0:/tmp/etc# cp /jffs/cert.pem .
admin@ZenWiFi_XT8-A5C0:/tmp/etc# cp /jffs/key.pem .
admin@ZenWiFi_XT8-A5C0:/tmp/etc# ll *.pem
-rw-rw-rw-    1 admin  root          1249 Sep  3 08:12 cert.pem
-rw-rw-rw-    1 admin  root          1704 Sep  3 08:12 key.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# cat key.pem > server.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# cat cert.pem >> server.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# ls *.pem
cert.pem    key.pem     server.pem
admin@ZenWiFi_XT8-A5C0:/tmp/etc# service restart_httpd

Done.
admin@ZenWiFi_XT8-A5C0:/tmp/etc# nvram get https_crt_file
admin@ZenWiFi_XT8-A5C0:/tmp/etc# ls *.pem
cacert.pem      cacert_gen.pem  cakey.pem       cakey_gen.pem   cert.pem        cert_gen.pem    key.pem         key_gen.pem     server.pem

/jffs/cert/tgz is recreated after all the steps above, but nvram get https_crt_file still returns nothing (and the router still presents the Asus certificate).

@stephen-dunne
Copy link

Yep, I've got an RT-AX88U Pro running Merlin 3004.388.8_2 and I can't replace the ss cert via the cli either.

I can manually update it via the web UI so I know my cert.pem and key.pem are good, but when I follow the steps suggested, i.e.
With etc/cert.pem etc/key.pem being my validated pem based cert and private key

steph@xxx:/tmp# tar -C / -czf /jffs/cert.tgz etc/cert.pem etc/key.pem
steph@xxx:/tmp# tar -tzf /jffs/cert.tgz
etc/cert.pem
etc/key.pem
steph@xxx:/tmp# nvram set https_crt_save=1
steph@xxx:/tmp# service restart_httpd

Done.

I see that /jffs/cert.tgz is overwritten with a server cert issued by a local CA on the router and the archive contents look like this:
steph@xxx:/tmp# tar -tzf /jffs/cert.tgz
etc/cacert.pem
etc/cakey.pem
etc/cert.pem
etc/key.pem
etc/cacert_gen.pem
etc/cakey_gen.pem
etc/cert_gen.pem
etc/key_gen.pem
steph@xxx:/tmp#

@jmontleon
Copy link

jmontleon commented Sep 12, 2024

Maybe extract and retain the other files. The archive looks like this for me, which suggests in december I replaced the key and crt, but kept the rest. Perhaps if other files are missing it regenerates / restores it. I should have kept better notes...

 tar tzvf cert.tgz
-rw-rw-rw- 0/0      1517 2018-05-05 01:05:31 etc/cacert.pem
-rw------- 0/0      1679 2018-05-05 01:05:31 etc/cakey.pem
-rw-rw-rw- 0/0      1838 2023-12-19 22:53:50 etc/cert.pem
-rw------- 0/0      1704 2023-12-19 22:53:51 etc/key.pem
-rw-rw-rw- 0/0      1517 2018-05-05 01:05:31 etc/cacert_gen.pem
-rw------- 0/0      1679 2018-05-05 01:05:31 etc/cakey_gen.pem
-rw-rw-rw- 0/0      1838 2018-05-05 01:05:25 etc/cert_gen.pem
-rw------- 0/0      1675 2018-05-05 01:05:25 etc/key_gen.pem

@stephen-dunne
Copy link

Yep, that was the missing piece of the puzzle.

Extracting the existing /jffs/cert.tgz into a temp subdir, overwriting etc/key.pem and etc/cert.pem and recreating /jffs/cert.tgz then running nvram set https_crt_save=1 and service restart_httpd seems to do the trick.

Finally !! Thanks for your help !

@cristit
Copy link

cristit commented Sep 21, 2024

Yep, that was the missing piece of the puzzle.

Extracting the existing /jffs/cert.tgz into a temp subdir, overwriting etc/key.pem and etc/cert.pem and recreating /jffs/cert.tgz then running nvram set https_crt_save=1 and service restart_httpd seems to do the trick.

Finally !! Thanks for your help !

I tryed exactly this and checked the md5 sum:
Before copy cert.tgz to /jffs/cert.tgz md5 was: ef7ba5b1ec34074a56c1349653860d82
after copy: 899f0ec767378c8e5a84079d4e6315d3 /jffs/cert.tgz
then I ran following commands:

nvram set https_crt_save=1
service restart_httpd

after last command, the md5 was ef7ba5b1ec34074a56c1349653860d82 (as initial).
I'm using: 3.0.0.4.388_24328-g1e6e634
any idea?

@janedenone
Copy link

after last command, the md5 was ef7ba5b1ec34074a56c1349653860d82 (as initial). I'm using: 3.0.0.4.388_24328-g1e6e634 any idea?

Same here. I am happy for everyone who managed to upload and activate their own certificate, but lost hope for myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment