HTTP/3 (QUIC) Not Working in Traefik v3.4.3 – QUIC “Black Hole”

Hi,

I’m running Traefik v3.4.3 inside Docker Compose and cannot get HTTP/3 (QUIC) to work. Traefik advertises h3 correctly in alt-svc, UDP 443 is open and forwarded, but any client QUIC request simply hangs forever—no errors or log entries in Traefik, even at TRACE level. I’m out of ideas and suspect a bug or conflicting option.

Environment & Versions
• Docker Engine on Linux (IPv4 only)
• Traefik image: traefik v3.4.3
• DNS A record points directly to server IP
• No Cloudflare/CDN or additional reverse proxy

Docker Compose Snippet

services:
  traefik:
    image: traefik:v3.4.3
    container_name: traefik
    hostname: traefik
    restart: unless-stopped
    command:
      - "--ping"
      - "--log.level=TRACE"
      - "--log.maxbackups=3"
      - "--accesslog=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.filename=/dynamic-file-provider/dynamic_conf.yml"
      - "--providers.file.watch=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.letsencrypt.acme.email=me@example.com"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=60"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.tls=false"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.priority=10000000"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"
      - "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
      - "--entrypoints.websecure.http.tls.domains[0].main=${MY_DOMAIN}"
      - "--entrypoints.websecure.http.tls.domains[0].sans=*.${MY_DOMAIN}"
      - "--entrypoints.websecure.http.tls.options=secureoptions@file"
      - "--entrypoints.websecure.http3"
      - "--entrypoints.websecure.http3.advertisedport=443"
      
      # used for other services, but should not conflict right?
      - "--entrypoints.tcp.address=:5201"
      - "--entrypoints.udp.address=:5201/udp"
    ports:
      - "80:80"
      - "443:443/tcp"
      - "443:443/udp"
      
      # used for other services, but should not conflict right?
      - "5201:5201"
      - "5201:5201/udp"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
      - "./dynamic-file-provider:/dynamic-file-provider"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.STSHeader.headers.stsSeconds=15552000"
      - "traefik.http.middlewares.STSHeader.headers.stsPreload=true"
      - "traefik.http.middlewares.STSHeader.headers.forceSTSHeader=true"
      - "traefik.http.routers.api.rule=Host(`traefik.${MY_DOMAIN}`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.service=api@internal"
      - "traefik.http.routers.api.middlewares=STSHeader"

What Works

  1. Entrypoints listening(inside container):
    tcp   LISTEN 0 511 0.0.0.0:443 0.0.0.0:*  
    udp   UNCONN 0 0   0.0.0.0:443 0.0.0.0:*
    
  2. alt-svc header
    $ curl -I https://traefik.${MY_DOMAIN}
    HTTP/2 200
    alt-svc: h3=":443"; ma=2592000
    
  3. UDP forwarding (socat echo test on UDP 443 via Docker port mapping)
    # Host:
    docker run --rm -d --name udpecho -p 443:443/udp alpine \
      sh -c "apk add --no-cache socat && socat -v UDP-RECVFROM:443,fork STDOUT"
    # Client:
    echo "hello" | socat - UDP:SERVER_IP:443
    # “hello” appears in udpecho logs
    

What Fails

  1. HTTP/3 request hangs forever (never falls back):
    curl --http3-only https://traefik.${MY_DOMAIN}
    
    And it is not like, when there is not an open port and you get an instant "refused", the requests just departs into the unkown :smiley:
  2. Traefik logs (TRACE level) show no QUIC or HTTP/3 handshake attempts or errors.

Questions & Suspicions

  • Could any combination of --entrypoints.* or redirection options conflict with HTTP/3?
  • Is --entrypoints.websecure.http3.advertisedPort=443 required?
  • Are there known bugs in v3.4.3’s QUIC implementation?
  • What debug flags or logging points reveal QUIC handshake failures?

I’m happy to provide more logs if helpful. Any guidance would be greatly appreciated!

Thanks,
JB

1 Like

Update:

Still same issue in Tv3.5

If you think this is a bug, it’s probably best to create an issue for the devs at Traefik Github and provide a reproducible example.