Firefox Sync token server, Android et certificat auto-signé

24 juin 2015

Depuis quelques temps j'ai abondonné Chrome pour passer sur Firefox, en profitant de leur service de synchronisation auto-hébergé.

Le serveur est hébergé sur ma kimsufi, et n'ayant pas la volonté d'investir dans des certificats dignes de ce nom, j'ai opté pour un certificat auto-signé.

Nombre de tutoriels sur internet expliquent la procédure pour créer en créer un, et l'installation du tout a été réalisée assez rapidement.

Faire fonctionner un certificat auto-signé sur firefox windows a été assez simple, il suffit d'ajouter une exception permanente, mais pour ce qui est de mon téléphone sous Android, l'histoire a été un peu différente, impossible faire fonctionner la synchronistion.

Après quelques recherches et pas mal d'expérimentations, le coupable a été trouvé : le fameux certificat! Voici donc la procédure à suivre.

Tout d'abord il faut un serveur Firefox Sync en état de fonctionnement. Pour ma part, il tourne dans un container docker avec un reverse proxy sur nginx.

Concernant la configuration sur Android, j'ai suivi ces explications qui ne présentaient à priori pas de difficultés majeures, mais qui pourtant ne fonctionnaient pas.

Après analyse des logs, il s'averait que mon système Android n'aimait pas le certificat du serveur web car la chaîne de confiance était absente ou quelque chose comme ça.

Je ne suis pas du tout un expert en matière de certificat numérique, donc je ne vais pas entrer dans les détails au risque de dire des bêtises, mais voici en gros ce que j'ai compris, et comment créer un certificat accepté par tout le monde.

La clé de la réussite c'est de faire une sorte de chaîne d'approbation de certificat. En gros on ne crée pas un certificat autosigné pour le serveur, on crée un certificat auto-signé qui fera office d'autorité de certification pour émettre le certificat du serveur. Il existe pleins de façons/options pour créer les certificats, voici juste la méthode de base.

Commençons par créer le nécessaire pour l'autorité de certification (CA) :

$ openssl genrsa -out ca.key 4096
$ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

La première ligne génère la clé privée (le fichier ca.key), la seconde le certificat auto-signé (le fichier ca.crt). Une série de question sera posée, l'important étant que le champ Common Name ne soit pas le même pour le CA et pour le serveur. -days permet de préciser la durée de validité en jours.

On passe ensuite à la création du certificat du serveur :

$ openssl genrsa -out serveur.key 4096
$ openssl req -new -key serveur.key -out serveur.csr
$ openssl x509 -req -days 365 -in serveur.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out serveur.crt

Comme pour le CA, la première ligne crée une clé privée. On ajoute cependant en seconde étape la création d'un fichier de requête (pensez bien à indiquer un Common Name différent de celui du CA). Enfin on crée le certificat à partir du fichier de requête, en utilisant la clé et le certificat du CA.

Il faut également faire attention à ce que le champ Common Name corresponde au nom (fqdn ou ip) du serveur firefox sync.

Ce que nous avons là, c'est ce que nous trouvons à peu près partout sur internet, c'est suffisant pour fonctionner sur pc, mais pas pour Android!

Pour qu'android reconnaisse la chaîne, il faut inclure la signature du certificat CA dans celui du serveur :

$ cat ca.crt >> serveur.crt

Notre certificat est prêt, il ne reste plus qu'à l'utiliser sur le serveur web, par exemple pour nginx, rajouter :

listen  443 ssl;
ssl_certificate /chemin/vers/serveur.crt;
ssl_certificate_key /chemin/vers/ffsync.key;
ssl_ciphers HIGH:!aNULL:!MD5:RC4+RSA;

Concernant la dernière ligne, c'est une info que j'ai trouvé sur une déclaration de bug sur firefox où quelqu'un précisait dans les commentaires que la configuration par défaut de nginx ne supportait pas RC4+RSA utilisé par firefox android.

Reste une dernière étape à effectuer sur tous les postes suceptibles d'utiliser le ou les certificat(s) signés par le CA : ajouter le certificat autosigné du CA dans les autorités de confiance.

Sous Windows il suffit de double cliquer sur le fichier crt puis d'installer le certificat.

Sur mon téléphone (Android 5.0.1) je suis allé dans les paramètres > sécurité > section certificats > installer depuis le stockage local.

Une fois que c'est fait, la machine devrait accepter n'importe quel certificat émis par le CA, aussi bien le serveur.crt que n'importe quel autre que vous pourriez créer à l'avenir.