-
Notifications
You must be signed in to change notification settings - Fork 150
Using Let's Encrypt
This How-To helps to configure A+ SSL protected web server, using nginx and Let's Encrypt as a certificate issuer right on router.
- You need domain name (my.domain.ru as example below) which is resolved to router IP address,
- You need TCP80 and TCP443 ports open on router.
Install necessary packages:
opkg install bash ca-certificates coreutils-mktemp curl diffutils grep nginx openssl-util
Download helper script to get/renew Let's Encrypt certificates:
cd /opt/etc/nginx
curl -O https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated
Edit two sections at /opt/etc/nginx/nginx.conf
:
- in
server
section:
server_name "my.domain.ru";
- in
location
section:
root /opt/share/nginx/html;
Now start web server and make sure it's available from internet as http://my.domain.ru
/opt/etc/init.d/S80nginx start
Prepare folder, which will be used by Let's Encrypt service to make sure this web server belongs to you:
echo WELLKNOWN="/opt/share/nginx/html/.well-known/acme-challenge" > config
mkdir -p /opt/share/nginx/html/.well-known/acme-challenge
and start script to get new SSL sertificate:
bash ./dehydrated --domain my.domain.ru --cron
You'll get following answer if all goes fine:
/opt/etc/nginx # bash ./dehydrated --domain my.domain.ru --cron
# INFO: Using main config file /opt/etc/nginx/config.sh
Processing my.domain.ru
+ Signing domains...
+ Generating private key...
+ Generating signing request...
+ Requesting challenge for my.domain.ru...
+ Responding to challenge for my.domain.ru...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Done!
+ Creating fullchain.pem...
+ Done!
Note: You may encounter errors here depending on your settings. Many people have found it necessary to add the following to their server block for their configuration
location ^~ /.well-known {
allow all;
}
The next step can take from five minutes (on Asus RT-N66U) to one hour (on Asus RT-N14U). If you've got Linux PC, you can run following command on PC then transfer dhparams.pem to router:
openssl dhparam -out dhparams.pem 2048
Now, configure HTTPS on nginx by adding following strings to server
section of /opt/etc/nginx/nginx.conf
:
listen 443 ssl;
include ssl.conf;
and put following content to /opt/etc/nginx/ssl.conf
:
ssl_certificate /opt/etc/nginx/certs/my.domain.ru/fullchain.pem;
ssl_certificate_key /opt/etc/nginx/certs/my.domain.ru/privkey.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_dhparam /opt/etc/nginx/dhparams.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
# ssl_stapling on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
Restart web server and make sure https://my.domain.ru is available from internet:
/opt/etc/init.d/S80nginx restart
By default, the Let's Encrypt SSL certificate is valid for 3 months. You can renew it from cron automatically:
opkg install cron
Create cron job by placing following script to /opt/etc/cron.monthly/renew_certs.sh:
#!/bin/sh
cd /opt/etc/nginx
bash ./dehydrated --domain my.domain.ru --cron
nginx -s reload
and make it executable:
chmod +x /opt/etc/cron.monthly/renew_certs.sh
Don't forget to start cron:
/opt/etc/init.d/S10cron start
Depending on the version of busybox you are running on your router, there is an issue with the tr command that was later fixed, whereby lowercase letter 'u' is incorrectly replaced with a lowercase letter 'l', and uppercase letter 'U' is ignored when doing uppercase->lowercase replacements.
As a workaround, if you have a domain with a letter U/u in it, you can change the following line in dehydrated - and then be sure to use all lowercase letters when passing your domain name(s).
Change Line 627 in dehydrated
From the Following:
for line in $(<"${DOMAINS_TXT}" tr -d '\r' | tr '[:upper:]' '[:lower:]' | _sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g' -e 's/[[:space:]]+/ /g' | (grep -vE '^(#|$)' || true)); do
to the below:
for line in $(<"${DOMAINS_TXT}" tr -d '\r' | _sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g' -e 's/[[:space:]]+/ /g' | (grep -vE '^(#|$)' || true)); do
- Let's encrypt project - https://letsencrypt.org/
- Nginx project - http://nginx.org/
- Quality SSL labs - https://www.ssllabs.com/ssltest/