How to Use OpenWrt self-signed Certs and get no https browsers errors?

Hello,

I installed a Snapshot OpenWrt image on a Pi 4.
I am accessing the OpenWrt LuCI Web admin page from a Windows PC running Chrome v87

OpenWrt didn't come with LuCI so I installed it along with nginx ssl version:
opkg install luci-ssl-nginx

It creates self signed certs in /etc/nginx/conf.d
When I browse to... https://openwrt.lan/cgi-bin/luci/ I get the log-in page for my OpenWrt router and I can log in and it all works fine.

However I get the browser warning error...

When I hit F12 in Chrome and look at the security tab I get this:

So it looks like I have secure communication between my browser and the router Luci home page? Despite reading ?official documentation about Nginx webserver and How to get rid of LuCI HTTPS certificate warnings I am totally confused as to what I am supposed to do to get rid of that address bar warning.

Here is my current understanding:
Self-signed certificates are auto generated during the install of nginx. Does the Chrome error message above mean that these certs are not adequate to stop the browser error? Because they only seem to have a Common Name (OpenWrt) which is not enough if your Chrome version is > v.58? Instead I need to follow the steps in How to get rid of LuCI HTTPS certificate warnings and...

  1. Create /etc/ssl/myconfig.conf that contains a Subject Alternative Name extension containing a domain name or IP address (DNS.1 and IP.1)
  2. Then go here: cd /etc/ssl and generate a new pair of keys
  3. openssl req -x509 -nodes -days 730 -newkey rsa:2048 -keyout mycert.key -out mycert.crt -config myconfig.conf
  4. Then add /etc/ssl/mycert.crt to the the Trusted Root Certification Authorities store in Chrome?
  5. Not sure if I would need to add to the Windows System Store using that powershell comand instead for any reason?

Or is there a better approach?

Update
I tried steps 1-4 above.. I am still getting the Certificate - missing error in Chrome F12?

Thank you,

Flex

Isn't this more a thing of Chrome bein a pain in the behind about self-signed certificates? I vaguely remember something about Google wanting to be holier than thou again.

A trusted root certificate needs to be in CA format, not just a certificate. In other words create a self-signed CA (certificate with CA flag set), then use it to sign the server certificate. Export the public part of the CA to your browser machine. You don't have to export the server certificate. The public part of the server certificate is automatically transferred during each https negotiation.

It's a significant risk to install a trusted root CA on your machine because if someone is able to steal the private key, they can create signed certificates to set up a fake version of any website you may visit.

Chrome is extremely strict about this. I'm surprised it's letting you access the page at all.

https does not protect a server from malicious users. Don't expose LuCI to the Internet even in https mode.

4 Likes

@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:

  1. This script, genCA.sh, creates a root CA pem and key file.
  2. When you run it you just need to specify any name you like, e.g: $./genCA.sh mylanCA
  3. You add the PEM file to Chrome > Manage Certificates > Trusted Root Certification Authorities Then restart Chrome.... chrome://restart
  4. 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:

  1. 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.
  2. 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.
  3. Then save the file and run the script, takes no parameters.
  4. 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.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.