@mk24 Thanks for that advice.
It's not clear from the How to get rid of LuCI HTTPS certificate warnings page that you have to do another step to completely get rid of browser https certificate warnings.
I read around alot and here are the most useful links I found:
OpenWrt and self-signed certificates
Getting Chrome to accept self-signed localhost certificate
Generate self-signed TLS certificate using OpenSSL
I am using Windows OS and Google Chrome to run a webpage hosted in Nginx on OpenWrt.
This solution may not be the only way or even the best way of doing this. It allows you to run websites on your local lan using https and not get annoying https browser errors.
Here is what I did:
- This script,
genCA.sh
, creates a root CA pem and key file. - When you run it you just need to specify any name you like, e.g:
$./genCA.sh mylanCA
- You add the PEM file to Chrome > Manage Certificates > Trusted Root Certification Authorities Then restart Chrome.... chrome://restart
- This script has to be run ONCE only.
#!/bin/bash
# Directories
cur=$(pwd)
tmp=$(mktemp -d)
scriptName=$(basename "$0")
# Certificate Variables
OUTPATH="./"
VERBOSE=0
DURATION=3650 # 10 years
C="US"
ST="California"
L="Ureka"
O="Paradise Inc"
OU="The Beach"
safeExit() {
if [ -d "$tmp" ]; then
if [ $VERBOSE -eq 1 ]; then
echo "Removing temporary directory '${tmp}'"
fi
rm -rf "$tmp"
fi
trap - INT TERM EXIT
exit
}
# Help Screen
help() {
echo -n "${scriptName} [OPTIONS] --name=mylanCA
Generate a CA using OpenSSL which you can use to make your own self-signed Certs
Options:
-n|--name Name to give your own Certificate Authority
-h|--help Display this help and exit
"
}
# Script starts here...
# Process Arguments
while [ "$1" != "" ]; do
PARAM=$(echo "$1" | awk -F= '{print $1}')
VALUE=$(echo "$1" | awk -F= '{print $2}')
case $PARAM in
-h|--help) help; safeExit ;;
-n|--name) NAME=$VALUE ;;
*) echo "ERROR: unknown parameter \"$PARAM\""; help; exit 1 ;;
esac
shift
done
# Prompt for variables that were not provided in arguments
checkVariables() {
# Country
if [ -z "$NAME" ]; then
echo -n "Name to give your own Certificate Authority:"
read -r NAME
fi
}
# Build TLS Certificate
build() {
# Sanitise domain name for file name
FILENAME=${NAME/\*\./}
# Generate CA key & crt
openssl genrsa -out "${FILENAME}_CA.key" 2048
openssl req -x509 -new -nodes -key "${FILENAME}_CA.key" -sha256 -days "${DURATION}" -out "${OUTPATH}${FILENAME}_CA.pem" -subj "/C=$C/ST=$ST/L=$L/O=$O/OU=$OU/CN=$NAME/emailAddress=info@${FILENAME}.com"
}
checkVariables
build
safeExit
Next step:
- This script,
gen-self-signed.sh
, creates the cert/key pair that are signed by the CA created above. You add them to your server block .conf file on Nginx on OpenWrt. - Before you run it you need to update the info at the top of the script between the two #============== lines, with details specific to your needs.
- Then save the file and run the script, takes no parameters.
- Reload Nginx should be enough, may need to restart?
#!/bin/bash
#==================================================================
# When creating a new cert/key pair for your site you only need to
# change the details below and make sure CA_PEM and CA_KEY are in the
# same directory as this script and that CA_PEM is added to your browser.
# Then add the newly created .key/.crt pair to your webserver.
CN="mysite.lan"
NAMES="mysite.lan,www.mysite.lan,fun.mysite.lan"
IP="192.168.1.254"
C="US"
ST="New York"
L="Manhatton"
O="Studio 54"
OU="Fun Times"
DURATION=3650 # 10 years
# Your CA details
CA_PEM="mylanCA_CA.pem"
CA_KEY="mylanCA_CA.key"
#==================================================================
j=0
SAN=""
getaltnames(){
for i in $(echo $NAMES | sed "s/,/ /g")
do
if [[ ! -z "$i" ]]; then
j=$((j+1))
if [ "$j" -gt 1 ]; then
SAN="${SAN}"$'\n'
fi
SAN="${SAN}DNS.${j} = ${i}"
fi
done <<< "${CN},${SAN}"
}
buildCsrCnf() {
cat << EOF > "${CN}.csr.cnf"
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=${C}
ST=${ST}
L=${L}
O=${O}
OU=${OU}
CN=${CN}
emailAddress=info@${CN}
EOF
}
buildExtCnf() {
cat << EOF > "${CN}.v3.ext"
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
${SAN}
IP.1=${IP}
EOF
}
# Build TLS Certificate
build() {
# Put list of sub domains (NAMES) into SAN variable (${SAN})
getaltnames
# CSR Configuration
buildCsrCnf
# Create v3.ext configuration file
buildExtCnf
# Server key
openssl req -new -sha256 -nodes -out "${CN}.csr" -newkey rsa:2048 -keyout "${CN}.key" -config <( cat "${CN}.csr.cnf" )
# Server certificate
openssl x509 -req -in "${CN}.csr" -CA "${CA_PEM}" -CAkey "${CA_KEY}" -CAcreateserial -out "${CN}.crt" -days "${DURATION}" -sha256 -extfile "${CN}.v3.ext"
}
# Script starts here
build
Here is my new server block in /etc/nginx/mysite.lan.conf
:
server {
listen 443;
listen [::]:443;
include '/var/lib/nginx/lan_ssl.listen';
server_name mysite.lan www.mysite.lan fun.mysite.lan 192.168.1.254;
root /www/mysite;
index index.html index.htm index.nginx-debian.html;
ssl_certificate '/etc/nginx/conf.d/mysite.lan.crt';
ssl_certificate_key '/etc/nginx/conf.d/mysite.lan.key';
ssl_session_cache 'shared:SSL:32k';
ssl_session_timeout '64m';
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/mysite.lan.access.log;
error_log /var/log/nginx/mysite.lan.error.log;
}
When I try to load a page using a local only domain name, the correct page is served and no certificate errors in the browser:
Hopefully this will save someone hours!
Flex
I have a follow up question about this in case anyone can help.