Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
@RMerl

This comment has been minimized.

Copy link

RMerl commented Jan 25, 2014

Instead of killing httpd and manually running it from inside /tmp/home/root/ (which won't work as httpd expects the web content to be in the CWD, simply restart the service:

service restart_httpd
@esimonds

This comment has been minimized.

Copy link

esimonds commented Jan 14, 2015

Worked perfectly on RT-AC68U running Merlin v. 3.0.0.4_376.49_5 -- thanks!

@sbrants

This comment has been minimized.

Copy link

sbrants commented Jan 14, 2015

Thanks a lot for this.
It worked for me too except that I can't configure the intermediate certificates.
I tried to add the intermediate certificate at the end of cert.pem but it is ignored.

I looked at the code and httpd.c calls mssl_init().
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/httpd/httpd.c#L1862

        if (mssl_init("/etc/cert.pem", "/etc/key.pem")) return;

The issue is that mssl_init() only takes the certificate, and private key, but not the intermediate certificate. I presume it should take another call to SSL_CTX_use_certificate_file to add the intermediate certificate.
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/mssl/mssl.c#L260

        // Set the certificate to be used
        _dprintf("SSL_CTX_use_certificate_file(%s)\n", cert);
        if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) <= 0) {
            _dprintf("SSL_CTX_use_certificate_file() failed\n");
            mssl_cleanup(1);
            return 0;
        }
        // Indicate the key file to be used
        _dprintf("SSL_CTX_use_PrivateKey_file(%s)\n", priv);
        if (SSL_CTX_use_PrivateKey_file(ctx, priv, SSL_FILETYPE_PEM) <= 0) {
            _dprintf("SSL_CTX_use_PrivateKey_file() failed\n");
            mssl_cleanup(1);
            return 0;
        }

I checked the code of SSL_CTX_use_certificate_file() and it only reads the first certificate in the file so you cannot simply concatenate the intermediate at the end of cert.pem.
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/cyassl/src/ssl.c#L456

    while(fgets(line, sizeof(line), file))
        if (strncmp(footer, line, strlen(footer)) == 0) {
            foundEnd = 1;
            break;
        }

It looks like we can't configure the intermediate certificate with the current code.

@htpcBeginner

This comment has been minimized.

Copy link

htpcBeginner commented Jan 27, 2015

Thanks! Worked great on AC68U.

@davidbalbert

This comment has been minimized.

Copy link
Owner Author

davidbalbert commented Mar 5, 2015

Thanks for the suggestion @RMerl. I updated the Gist. Sorry it took me so long.

@sasoiliev

This comment has been minimized.

Copy link

sasoiliev commented Mar 29, 2015

Using SSL_CTX_use_certificate_chain_file() instead of SSL_CTX_use_certificate_file() enables configuring certificate chains (intermediate + root CA certs). As per OpenSSL documentation the PEM file should contain the server certificate followed by the intermediate CA certificates up to the root CA certificate.

diff --git a/release/src/router/mssl/mssl.c b/release/src/router/mssl/mssl.c
index 5d92ac5..905d727 100644
--- a/release/src/router/mssl/mssl.c
+++ b/release/src/router/mssl/mssl.c
@@ -256,9 +256,9 @@ int mssl_init(char *cert, char *priv)

        if (server) {
                // Set the certificate to be used
-               _dprintf("SSL_CTX_use_certificate_file(%s)\n", cert);
-               if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) <= 0) {
-                       _dprintf("SSL_CTX_use_certificate_file() failed\n");
+               _dprintf("SSL_CTX_use_certificate_chain_file(%s)\n", cert);
+               if (SSL_CTX_use_certificate_chain_file(ctx, cert) <= 0) {
+                       _dprintf("SSL_CTX_use_certificate_chain_file() failed\n");
                        mssl_cleanup(1);
                        return 0;
                }

@RMerl, do you think this is worth having in the codebase?

I've tested this both with a single server certificate in the PEM file, as well as with the whole certificate chain, so it's compatible with the current mode of operation.

The only drawback with this approach is that the chain will certainly take more space than a single certificate, so you could fill up the nvram, but since this is not an officially supported feature (supplying you own certificate is not included in the UI) one is expected to be aware of the possible consequences when doing this.

What do you think?

@RMerl

This comment has been minimized.

Copy link

RMerl commented Apr 15, 2015

As long it doesn't affect the current implementation for cases where one does not have an intermediary certificate I don't see any problem in making that change.

@tairun

This comment has been minimized.

Copy link

tairun commented Apr 30, 2015

Regarding the intermediate certificate issue I can't really follow what @sasoiliev and @sbrants are saying. I got a certificate from rapidssl for my webserver and also installed it to the router using the method described above, disregarding the intermediate cert, still the browser reports the site as versified. What is going on?

@sbrants

This comment has been minimized.

Copy link

sbrants commented May 27, 2015

@tairun, it depends who issued the certificate and which system you tested them on.
For instance with StartSLL, without the intermediate certificate it will work fine for Chrome on windows and will give you warnings with Chrome on Android. It all depends how many levels you certificate chain has and if the intermediate certs are recognized by your OS. Allowing to specify the intermediate certificate at the server level allows you to make sure it will work everywhere

@Jamyz

This comment has been minimized.

Copy link

Jamyz commented Aug 28, 2015

HI. if https_crt_file is not empty how i do to delete ??

@YasharF

This comment has been minimized.

Copy link

YasharF commented Sep 29, 2015

@Jamyz if https_crt_file already exist, you can just set it to blank nvram set https_crt_file= prior to the httpd service restart.

@wheelq

This comment has been minimized.

Copy link

wheelq commented Oct 29, 2015

each time I perform httpd restart it comes back with self signed cert with the date of the reboot. I have generated the keys using easyrsa3.
For the key.pem I paste private key, no new lines.
For the cert.pem I paste contents of the crt file from the issued directory

@lubo

This comment has been minimized.

Copy link

lubo commented Nov 10, 2015

Thanks for this awesome guide, works flawlessly on ASUS RT-N18U with stock asus-wrt.

There is only one thing this guide lacks and it is how to uninstall a previously installed certificate. Here is what i did:

# nvram set https_crt_save=0
# nvram unset https_crt_file
# service restart_httpd
# reboot

After reboot I was able to install a new certificate. # service restart_httpd may be actually useless, I'm not sure.

@wisq

This comment has been minimized.

Copy link

wisq commented Mar 16, 2016

Fun fact: nvram get https_crt_file gives you a base64-encoded tar.gz of the cert and key. But I don't believe the router has a base64 decoding command, so you'll have to paste / pipe it out and decode it locally.

Also, I successfully replaced an existing cert by

  1. unsetting https_crt_file (or actually, setting it to an empty string, either should work),
  2. service restart_httpd
  3. repeat #1 and #2

Not sure why it needs the double restart, but I verified that https_crt_file was still set to the old value, up until I restarted it a second time.

@Dyndrilliac

This comment has been minimized.

Copy link

Dyndrilliac commented Mar 19, 2016

I have an ASUS RT-N66R running firmware version 3.0.0.4.378_9459. Will this process work for that? I want to install my own signed Comodo PositiveSSL SHA-2 certificate. Also, when I check the Administration -> System tab, I only see an option for Telnet and not SSH. Are these instructions using those two interchangeably? And if I enable it, will it be accessible via LAN only by default? I don't want to expose my router's SSH functionality to the WAN.

@whyallyn

This comment has been minimized.

Copy link

whyallyn commented Mar 29, 2016

To replace an existing cert, I also had to do the double restart that @wisq posted.

@lmerega

This comment has been minimized.

Copy link

lmerega commented Nov 24, 2016

That's insane.
I'm on RT-N66U with 380.63_2 version.
I cannot install any certificate.
I tried to commit nvram too, but it looks like something is going wrong.
I use the crt file for Apache generated by startssl.com... I used it on Tomato happily, now I cannot install it on my router.
Any idea?
The process is entirely done. The file is generated... the cert is still the first one asus generated :-(
Any help appreciated

Luca

@lmerega

This comment has been minimized.

Copy link

lmerega commented Dec 4, 2016

C'mon... I do need an answer :-)

@lmerega

This comment has been minimized.

Copy link

lmerega commented Dec 5, 2016

Ok, I managed it. I do not know, what I was doing wrong. Now it works flawlessly.
Thx

Luca

@bigforo

This comment has been minimized.

Copy link

bigforo commented Dec 10, 2016

Thx

@PeterDaveHello

This comment has been minimized.

Copy link

PeterDaveHello commented Apr 23, 2017

It works on RT-AC58U / RT-AC1300G, thanks!

@cosmindidis

This comment has been minimized.

Copy link

cosmindidis commented Jun 21, 2017

Hi there,

I am trying to install a certificate using the above script and, for some reason, the last 'nvram get https_crt_file' command returns empty. I am running ver. 380.63.2 on an Asus RT-N66U. Any ideeas? The certificate is generated from Let's Encrypt, if it matters (I am using they private key and the full chain pem files).

Cosmin

@scorpiorooster

This comment has been minimized.

Copy link

scorpiorooster commented Nov 27, 2017

Found it!
Merlin won't accept the "my.server.cer" or "my.server.key" or "fullchain.cer" that are generated with acme.sh / Let's Encrypt.

I'm using an RT-N66W running 380.68.4.
*.pem format is required. Conversion is done with openssl.

Here's what worked for me:

SSH to Merlin. Go to dir that Let's Encrypt put your key and cer files.

openssl rsa -in my.server.key -text > private.pem
openssl x509 -inform PEM -in my.server.cer > public.pem

Go to Merlin web interface.
Upload them in the Asuswrt-Merlin web Administration / System menu. It will accept them if they will work or give you a wrong file message if they won't. The "Apply" button then restarts httpd and you will be back at login screen. A reboot is a good idea after that. I also flushed my dns and browser cache before opening the https Web interface ....and then I finally got to see the green lock and verified secure status...

@RiFi2k

This comment has been minimized.

Copy link

RiFi2k commented Dec 25, 2017

@scorpiorooster Your the man, exactly what I needed to make my local CA .crt and .key file I generated for the router work with Merlin. Saved me from pulling my hair out for another hour.

As an extra note for anyone else I didn't need to flush the cache just reboot and close the current tab and reopen it in a new one for the green lock.

@haraldinho2000

This comment has been minimized.

Copy link

haraldinho2000 commented Apr 23, 2018

@sasoiliev Did your suggestion make it into the codebase, in other words: should i be able to add a crt file with cert chain? For me it does not seem to work that way. I am using 384_4_2.
I solved it by simply going to /jffs/ssl and with nano edited the cert.pem file and pasted the content from my intermediate cert at the end of the file. After that a service restart_httpd and a new browser window and I was good to go.
However, just being able to upload the chain cert file through the UI would be much easier.

@sparky3387

This comment has been minimized.

Copy link

sparky3387 commented Jun 14, 2019

According to the code as long as https_crt_save is set to 1 and https_crt_file is unset it should save, but for some reason It was refusing to save the certs to the nvram, I was able to manually save the file by:

tar -czf cert.tgz --transform 's,^,etc/,' cert.pem key.pem
echo $(cat cert.tgz | base64 | tr -d '\n')

And then copying this and pasting it into the router without newlines or spaces at the end (I couldnt paste into the command prompt as it would truncate)

vi /tmp/https_crt_file
nvram set $(cat /tmp/https_crt_file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.