Firefox, Websockets, HTTP/2 & connection failures
I have a tunneled connection to a Rachet (PHP) socket with a relevant config of
compress: 'ON'
limit-request-body: 4294967296
ssl-offload: kernel
hosts:
social.toastal.in.th:443:
file.custom-handler:
extension:
- .php
fastcgi.connect:
port: /run/phpfpm/movim.sock
type: unix
fastcgi.document_root: /nix/store/l80hivxkdqjbw5qh12w962q4rfjab0mw-movim-0.29.2
listen:
- port: 443
ssl:
identity:
- certificate-file: /var/lib/acme/toastal.in.th/fullchain.pem
key-file: /var/lib/acme/toastal.in.th/key.pem
paths:
/:
file.dir: /nix/store/l80hivxkdqjbw5qh12w962q4rfjab0mw-movim-0.29.2/share/php/movim/public
file.index:
- index.php
- index.html
file.send-compressed: 'ON'
header.set:
- 'Content-Security-Policy: default-src ''self''; img-src ''self'' aesgcm:
data: https:; media-src ''self'' aesgcm: https:; script-src ''self'' ''unsafe-eval''
''unsafe-inline''; style-src ''self'' ''unsafe-inline'''
redirect:
internal: 'YES'
status: 307
url: /index.php/
# ↓↓↓ WEBSOCKET PATH HERE ↓↓↓
/ws/:
proxy.preserve-host: 'ON'
proxy.reverse.url: http://127.0.0.1:8080/
proxy.tunnel: 'ON'
The behavior is that Chromium connects fine (101 Connection) after a bit of a connection delay, but Firefox eventually fails out with a 400 & no body.
Disabling HTTP/2 on the server via Fx’s about:config with network.http.http2.enabled or network.http.http2.enabled set to false gives the desired 101. Fiddling with the other proxy values doesn’t seem to help (or makes things worse & Chromium doesn’t connect). Disabling ad blocking + tracking protection in Fx did nothing.
Seems other projects have had or still have issues in this space:
- Jetty: https://github.com/jetty/jetty.project/issues/7740
- Mosquitto: https://github.com/eclipse-mosquitto/mosquitto/issues/1211
- Mattermost: https://github.com/mattermost/mattermost/issues/30285
With upstream issue:
Problematic URL in production: https://social.toastal.in.th
echo | websocat --origin "https://social.toastal.in.th" "wss://social.toastal.in.th/ws/?path=login&offset=0" seems fine.
According to the Jetty issue’s final comment, HTTP/2 for these sorts of connections for Gecko (Firefox, LibreWolf, & so on) are disabled. Mozilla forums suggest disabling HTTP/2 on websockets (meaning network.http.http2.websockets = false).
Having workarounds for possible bugs in browsers via UA detection is problematic, but so would be suggesting to users to poke around about:config. Perhaps there is an mruby solution I don’t know how to solve it (not an HTTP expert). There also aren’t ways to say selectively disable HTTP/2+ on a specific path such as
/ws/:
maximum-http-version: 1.1
proxy.preserve-host: 'ON'
proxy.reverse.url: http://127.0.0.1:8080/
proxy.tunnel: 'ON'tho this could have a negative experience for non-Gecko-based browsers. I’m not really sure what the solution is.
I do apologize if this is my own misconfiguration issue. I did have this socket working prior on Nginx & trying to migrate. Maybe at least if it is a dumb misconfiguration, the issue can help.
Source: h2o/h2o