Let’s Encrypt Certificate on FRITZ!Box
This script checks if the FRITZ!Box has a valid ssl certificate and renews it with certbot if necessary.
In order to upload the certificate to the FRITZ!Box, a separate user must be created in the webinterface beforehand.
It makes sense to call the script regularly (e.g. every 7 days) by a cronjob. A further development could be the dispatch of a mail when the certificate is renewed.
#!/bin/bash
# parameters
USERNAME="fritzuser"
PASSWORD="*********"
CERTPATH="/root"
CERTPASSWORD=""
FQDN=fritzbox.zaage.it
# Check if the certificate is expiring soon
echo | openssl s_client -servername $FQDN -connect $FQDN:443 2>/dev/null | openssl x509 -noout -checkend 2592000
if [ "$?" == "1" ]; then
# Expiring in less than one month. We need to renew
certbot certonly --csr /root/fritzbox.csr -d fritzbox.zaage.it --nginx
# make and secure a temporary file
TMP="$(mktemp -t XXXXXX)"
chmod 600 "$TMP"
# login to the box and get a valid SID
CHALLENGE=$(wget -q -O - $FQDN/login_sid.lua | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')
HASH="$(echo -n "$CHALLENGE"-"$PASSWORD" | iconv -f ASCII -t UTF16LE |md5sum|awk '{print $1}')"
SID=$(wget -q -O - "$FQDN/login_sid.lua?sid=0000000000000000&username=$USERNAME&response=$CHALLENGE-$HASH"| sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')
# generate our upload request
BOUNDARY="---------------------------"$(date +%Y%m%d%H%M%S)
printf -- "--$BOUNDARY\r\n" >> "$TMP"
printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n$SID\r\n" >> "$TMP"
printf -- "--$BOUNDARY\r\n" >> "$TMP"
printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n$CERTPASSWORD\r\n" >> "$TMP"
printf -- "--$BOUNDARY\r\n" >> "$TMP"
printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "$TMP"
printf "Content-Type: application/octet-stream\r\n\r\n" >> "$TMP"
cat $CERTPATH/fritzbox.key >> "$TMP"
cat $CERTPATH/0001_chain.pem >> "$TMP"
printf "\r\n" >> "$TMP"
printf -- "--$BOUNDARY--" >> "$TMP"
# upload the certificate to the box
wget -q -O - $FQDN/cgi-bin/firmwarecfg --header="Content-type: multipart/form-data boundary=$BOUNDARY" --post-file "$TMP" | grep SSL
# clean up
rm -f "$TMP" 0000_cert.pem 0000_chain.pem 0001_chain.pem
fi