Il y a des années, au moment du premier déploiement d’un projet avec le framework Phoenix sur mon serveur j’avais rencontré un problème avec les websockets. Les requêtes étaient systématiquement redirigées vers la même url en https.
Je n’y avais pas prêté particulièrement attention. Ma solution avait été de désactiver la redirection http -> https coté Phoenix, ceci étant déjà réalisé coté Traefik, mon reverse proxy.
Les années passent et les problèmes cachés sous le tapis finissent par revenir. En voulant déployer une instance de Nerves Hub, je suis tombé a nouveau sur le problème. J’ai décidé cette fois d’enquêter.
Je me suis douté tout de suite que le problème soit dû au fait de forcer https sur l’instance. Lorsque c’est une requête https classique ca passe, mais websocket non.
- Désactiver la redirection http -> https coté Traefik: Problème toujours présent.
- Chercher sur les forums des problèmes similaires: j’en trouve 2, mais sans solution satisfaisante.
- Lire la doc et le code du Plug.RewriteOn qui s’occupe de la logique. Relire la doc de Traefik pour vérifier qu’il envoie bien l’entête http
X-Forwarded-Proto. La réponse est oui. - Inspecter les entêtes https fournis par le serveur. Je suis tombé sur le projet docker-http-https-echo qui est juste parfait pour cela.
Je le lance sur mon serveur:
docker \ run \ --rm \ --network traefik \ --label traefik.enable=true \ --label 'traefik.http.routers.test.rule=Host(`test.2metz.fr`)' \ mendhak/http-https-echo:39En effectuant ma requête websocket, je me rends compte que la valeur de
X-Forwarded-Protoestwss.Je tombe sur l’issue de Traefik qui parle justement de cette valeur pas très standard https://github.com/traefik/traefik/issues/6388
A ce moment la, je pense avoir trouvé la source du problème. La valeur wss n’est pas attendu par Plug.RewriteOn, et redirige donc vers la version https pensant que c’est une requêtes non chiffré. Reste à trouver une solution.
Je tente alors de forcer la valeur de l’entête X-Forwarded-Proto a https par Traefik:
docker \
run \
--rm \
--network traefik \
--label traefik.http.routers.test.middlewares=test@docker \
--label traefik.http.middlewares.test.headers.customrequestheaders.X-Forwarded-Proto=https \
--label traefik.enable=true \
--label traefik.http.routers.test.rule='Host(`test.2metz.fr`)' \
mendhak/http-https-echo:39
Et cela fonctionne ! Mon instance Nerves Hub fonctionnelle, je peux désormais proposer un patch https://github.com/elixir-plug/plug/pull/1302/.