Skip to content

Instantly share code, notes, and snippets.

@wikrie
Last active March 2, 2024 10:48
Show Gist options
  • Star 84 You must be signed in to star a gist
  • Fork 23 You must be signed in to fork a gist
  • Save wikrie/f1d5747a714e0a34d0582981f7cb4cfb to your computer and use it in GitHub Desktop.
Save wikrie/f1d5747a714e0a34d0582981f7cb4cfb to your computer and use it in GitHub Desktop.
Fritzbox Fritz!Box AVM SSL Letsencrypt automatically update
#!/bin/bash
## this little Gist is for Copy the Letsencrypt Cert from an Linux machine (e.g. Raspberry PI or Synology NAS)
## to the router (Fritzbox).
## It is usefull to be able to speak to the Router over DDNS without any Cert issue in the Browser.
## thanks to https://gist.github.com/mahowi for the perfect Idea
## put it in /etc/letsencrypt/renewal-hooks/post so it gets run after every renewal.
## since Fritz OS 7.25 it is needed to select a Username, from a security point of view
## it is always a good idea to have a non default user name. And as normaly a Fritz Box
## is connected to the Internet, the prefered method should be WITH Username.
# parameters
USERNAME="needed since Fritz OS 7.25"
PASSWORD="fritzbox-password"
CERTPATH="path to cert eg /etc/letsencrypt/live/domain.tld/"
CERTPASSWORD="cert password if needed"
HOST=http://fritz.box
# 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 - $HOST/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 - "$HOST/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/privkey.pem >> $TMP
cat $CERTPATH/fullchain.pem >> $TMP
printf "\r\n" >> $TMP
printf -- "--$BOUNDARY--" >> $TMP
# upload the certificate to the box
wget -q -O - $HOST/cgi-bin/firmwarecfg --header="Content-type: multipart/form-data boundary=$BOUNDARY" --post-file $TMP | grep SSL
# clean up
rm -f $TMP
@ant0nwax
Copy link

This sentence comes to my mind:
Security breaking down our nerves (2023)

@doits
Copy link

doits commented Feb 18, 2023

I had the same problem and it was because the certificate's private key was an ecdsa key.

Changing key_type to rsa in /etc/letsencrypt/renewal/xxx.conf and renewing the certificate (certbot renew --force-renewal) generated a certificate with a rsa private key which could be imported again.

@mbo77
Copy link

mbo77 commented Sep 17, 2023

Since recently, I was using this script to update the certificate on both, a Fritz!Box and a Fritz!Repeater 1200 AX.
The certificate option is not exposed in the UI on repeaters, but worked via this script just fine.

The repeater is now on 7.57 and it stopped working.
The returning page indicates a problem:

`

Das Update ist fehlgeschlagen:

Invalid variable name.

`

Anyone experiencing the same problem?

@franzs
Copy link

franzs commented Sep 17, 2023

@mbo77 maybe you want to give fritzbox_upload_certificate a try. it was recently updated for 7.57.

@mbo77
Copy link

mbo77 commented Sep 17, 2023

@franzs

Looks nice and clean, but I suspect the problem is on the repeater side.
POSTing to the URL still gives the same message on the returing page:

Das Update ist fehlgeschlagen:

Invalid variable name.

Works fine with 7530AX on 7.57.

@mbo77
Copy link

mbo77 commented Sep 17, 2023

I suspect the repeater triggers the wrong function internally:

FRITZ!Repeater Update

Das Update ist fehlgeschlagen:

Invalid variable name.

Wiederholen Sie das Update oder starten Sie den FRITZ!Repeater neu.

This looks to me some message related to updating the firmware itself.
As the server-side binary is called "firmwarecfg", I suspect it was initially deployed for updating the firmware and later was extended to handle certificates as well. So maybe they messed it up internally on the repeater.
I will open a support case with AVM.

@franzs
Copy link

franzs commented Sep 17, 2023

@mbo77 unfortunately i don't have access to a Fritz!Repeater 1200 AX. i ran the fritzbox_upload_certificate sucessfully with a FRITZ!WLAN Repeater DVB-C. it's not possible to upload a certificate via the ui but the /cgi-bin/firmwarecfg url works well with at least 7.01.

let us know what AVM says. 😄

@mbo77
Copy link

mbo77 commented Sep 19, 2023

No luck..

Die Funktion für den Import der Zertifikate war für unsere Repeater nie geplant und über die Benutzeroberfläche auch nicht möglich.
Durch aktuelle FRITZ!OS-Änderungen im Unterbau ist es nun bei Repeatern auch komplett entfernt worden.

Gerne gebe ich Ihr Anliegen aber als Verbesserungsvorschlag an unsere Produktentwicklung weiter.

@franzs
Copy link

franzs commented Sep 19, 2023

@mbo77 What a pity. But thanks for sharing the answer. At least I'll list the Fritz!Repeater 1200 AX with 7.57 as unsupported. Unfortunately there is no easy way to get the product name and the OS version from a fritzbox to check it.

@xraver
Copy link

xraver commented Dec 28, 2023

Hello,
I want to share my experience.
The script worked well. At a certain point it looks not working properly: no error prompted and no certificate imported.
After troubleshooting it I've discovered the issue was related to letsencrypt that changed from rsa to ecdsa. I replaced in the letsencrypt configuration file as below
#key_type = ecdsa
key_type = rsa
And now is working well back.
hope my experience will help you.

(tested with fritz7590 and 7530ax both version 7.57)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment