Setup de Mozilla Sync Server

Firefox sync est disponible depuis Firefox 4, et il est possible de l’installer en auto hébergement. Je m’en sers pour synchroniser firefox desktop avec celui de mon android. L’installation est relativement simple, surtout sur une Debian, il suffit de suivre la documentation de mozilla.

Mon setup est en place avec du Nginx et Gunicorn (mozilla-sync étant en python).

Évidement, le tout se fait via une connexion https, et c’est là que les ennuis commencent…

Premièrement, si c’est un certificat auto-signé, il ne faut pas oublier d’importer votre CA certificat dans votre Firefox Android ! Sinon il sera impossible pour votre smartphone de se connecter au sync server car le certificat ne sera pas reconnu …
Ensuite, si vous avez suivi la documentation, vous devriez avoir une sync qui fonctionne avec votre Firefox desktop, via une connexion sécurisée.Le problème se situe lors du setup de Sync via Firefox Android, sur l’écran “Serveur personnalisé”, vous avez beau entrer la bonne url et mots de passe, le seul résultat est “Please enter a valid server URL”, et absolument RIEN dans les logs nginx coté serveur… Même constatation via la fonction “Pair a device”.

Après une sortie de tshark afin de voir les trames réseau, il s’avère que firefox android ne sait négocier le tls qu’AVEC un cipher RC4, ce qui est confirmé par le code mozilla-central/mobile/android/base/sync/net/TLSSocketFactory.java :

public class TLSSocketFactory extends SSLSocketFactory {
  private static final String LOG_TAG = "TLSSocketFactory";
  private static final String[] DEFAULT_CIPHER_SUITES = new String[] {
    "SSL_RSA_WITH_RC4_128_SHA",        // "RC4_SHA"
  };
  private static final String[] DEFAULT_PROTOCOLS = new String[] {
    "SSLv3",
    "TLSv1"
  };

  // Guarded by `this`.
  private static String[] cipherSuites = DEFAULT_CIPHER_SUITES;

  public TLSSocketFactory(SSLContext sslContext) {
    super(sslContext);
  }

Le problème est que les versions récente de nginx utilisent par défaut “ssl_ciphers HIGH:!aNULL:!MD5;”, et SSL_RSA_WITH_RC4_128_SHA n’est pas considéré comme un cipher “high”, donc la négociation ssl échoue tout bêtement…

Il faut donc forcer nginx à utiliser RC4, ce qui est dommage au vu de http://blog.ivanristic.com/2013/09/updated-best-practices-deprecate-rc4.html.

De plus, il semble que le client Android ne supporte pas le SNI, ce qui est dommage car vous devez donc faire la modification de ciphers dans le vhost ssl par défaut.

Voici donc une configuration fonctionnelle :

server {
	listen 443 ssl default;
	server_name mozillasync.domain.org;
	ssl_certificate /etc/nginx/ssl/cert.chain.crt;
	ssl_certificate_key /etc/nginx/ssl/cert.key;
	access_log  /var/log/nginx/mozillasync.access.log;
	ssl_ciphers RC4:HIGH:!aNULL:!MD5;
	ssl_prefer_server_ciphers on;

	location /sync/ {
		rewrite  ^/mozillasync/(.+)$ /$1 break;
		proxy_pass_header Server;
		proxy_set_header Host $http_host;
		proxy_redirect off;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Scheme $scheme;
		proxy_connect_timeout 10;
		proxy_read_timeout 10;
		proxy_pass http://localhost:5000/;
		}
	location / {
		root /home/server-full/;
	}
}

Et un lien vers le rapport de bug chez mozilla : https://bugzilla.mozilla.org/show_bug.cgi?id=756763#c31