X-Forwarded-Proto contains "invalid" protocol #411

Closed
opened 2026-04-05 17:09:25 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @NecktiedHummingbird on 1/1/2026

Describe the Bug

Happy new Year everyone!

Okay so I have finally figured out, what the problem with my Socket.IO services is.
Socket.IO is doing an GET wss://<domain>/socket.io/?EIO=4&transport=websocket call.
The response with Pangolin between client/browser and called service is HTTP400 and the connection is denied. So far so not the problem of Pangolin, I suppose.
When I add the X-Forwarded-Proto: https header in the ressource proxy configuration it overrides the x-forwarded-proto header from Pangolin and the connection gets established.
So i analyzed the requests with mitmproxy finally and found out, that Pangolin is writing the original scheme wss into the x-forwarded-proto header, so x-forwarded-proto: wss.

Image

So at this point I'm not quite sure who to blame.
Do I blame Socket.IO for wanting explicit x-forwarded-proto: https on secured web socket requests or do I blame Pangolin for not writing x-forwarded-proto: https as it is defined in the MDN Docs?

Environment

  • OS Type & Version: Debian 13.2
  • Pangolin Version: 1.14.1
  • Gerbil Version: 1.3.0
  • Traefik Version: 3.6.6
  • Newt Version: 1.8.1

To Reproduce

Add a Ressource to a Socket.IO Service, f.e. changedetection.io
Use mitmproxy to read the requests

Example docker-compose

services:
  proxy:
    image: mitmproxy/mitmproxy:11.0.0
    command: >
      mitmweb 
      --mode reverse:http://changedetection:5000
      --set web_host=0.0.0.0
      --set web_port=8081
      --set web_password:'xxx'
      --set block_global:false
    ports:
      - "8080:8080"
      - "8081:8081"
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    hostname: changedetection
    volumes:
      - changedetection-data:/datastore
    environment:
      - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000
      - DISABLE_VERSION_CHECK=true
      - TZ=Europe/Berlin
      - LC_ALL=de_DE.UTF-8
    restart: unless-stopped
    depends_on:
      browser-sockpuppet-chrome:
        condition: service_started

        
  browser-sockpuppet-chrome:
    hostname: browser-sockpuppet-chrome
    image: dgtlmoon/sockpuppetbrowser:latest
    restart: unless-stopped
    environment:
      - SCREEN_WIDTH=1920
      - SCREEN_HEIGHT=1024
      - SCREEN_DEPTH=16
      - MAX_CONCURRENT_CHROME_PROCESSES=10

volumes:
  changedetection-data:

Navigate to the mitmproxy website (http://127.0.01:8081), then navigate to your proxied resource (in this compose it is bound to 8080) and check the requests header x-forwarded-proto, it should currently have the value wss, but i suppose it is expected to have https.
The response is HTTP400
Image

Expected is HTTP101
Image
Can be forced by adding your own header
Image

Expected Behavior

That the x-forwarded-proto header contains https.

*Originally created by @NecktiedHummingbird on 1/1/2026* ### Describe the Bug Happy new Year everyone! Okay so I have finally figured out, what the problem with my Socket.IO services is. Socket.IO is doing an `GET wss://<domain>/socket.io/?EIO=4&transport=websocket` call. The response with Pangolin between client/browser and called service is HTTP400 and the connection is denied. So far so not the problem of Pangolin, I suppose. When I add the `X-Forwarded-Proto: https` header in the ressource proxy configuration it overrides the `x-forwarded-proto` header from Pangolin and the connection gets established. So i analyzed the requests with mitmproxy finally and found out, that Pangolin is writing the original scheme `wss` into the `x-forwarded-proto` header, so `x-forwarded-proto: wss`. <img width="888" height="868" alt="Image" src="https://github.com/user-attachments/assets/37525f87-ec64-41d0-a402-76e843d784e3" /> So at this point I'm not quite sure who to blame. Do I blame Socket.IO for wanting explicit `x-forwarded-proto: https` on secured web socket requests or do I blame Pangolin for not writing `x-forwarded-proto: https` as it is defined in the [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto)? ### Environment - OS Type & Version: Debian 13.2 - Pangolin Version: 1.14.1 - Gerbil Version: 1.3.0 - Traefik Version: 3.6.6 - Newt Version: 1.8.1 ### To Reproduce Add a Ressource to a Socket.IO Service, f.e. changedetection.io Use mitmproxy to read the requests Example docker-compose ```yml services: proxy: image: mitmproxy/mitmproxy:11.0.0 command: > mitmweb --mode reverse:http://changedetection:5000 --set web_host=0.0.0.0 --set web_port=8081 --set web_password:'xxx' --set block_global:false ports: - "8080:8080" - "8081:8081" changedetection: image: ghcr.io/dgtlmoon/changedetection.io hostname: changedetection volumes: - changedetection-data:/datastore environment: - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000 - DISABLE_VERSION_CHECK=true - TZ=Europe/Berlin - LC_ALL=de_DE.UTF-8 restart: unless-stopped depends_on: browser-sockpuppet-chrome: condition: service_started browser-sockpuppet-chrome: hostname: browser-sockpuppet-chrome image: dgtlmoon/sockpuppetbrowser:latest restart: unless-stopped environment: - SCREEN_WIDTH=1920 - SCREEN_HEIGHT=1024 - SCREEN_DEPTH=16 - MAX_CONCURRENT_CHROME_PROCESSES=10 volumes: changedetection-data: ``` Navigate to the mitmproxy website (http://127.0.01:8081), then navigate to your proxied resource (in this compose it is bound to 8080) and check the requests header `x-forwarded-proto`, it should currently have the value `wss`, but i suppose it is expected to have `https`. The response is HTTP400 <img width="867" height="227" alt="Image" src="https://github.com/user-attachments/assets/3cfabf4f-8e54-46b7-8ac3-216fda92500a" /> Expected is HTTP101 <img width="432" height="174" alt="Image" src="https://github.com/user-attachments/assets/1e633cdd-5991-4597-9083-b854e374c50c" /> Can be forced by adding your own header <img width="1474" height="1146" alt="Image" src="https://github.com/user-attachments/assets/c4b87a03-cb1f-4d8c-bdb6-c5e6941149d2" /> ### Expected Behavior That the `x-forwarded-proto` header contains `https`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/pangolin#411