HTTP3 QUIC connection migration to another network · Issue #3529 · haproxy/haproxy · GitHub
Skip to content

HTTP3 QUIC connection migration to another network #3529

Open

Description

@lawl-lawl

Detailed Description of the Problem

When a client connects to haproxy using HTTP3, the QUIC protocol gives you a connection ID that you can re-use on a different IP or even a different network. This is super useful if you're roaming or switching from wifi/LTE. Sadly, Haproxy doesnt support connection handoff, as the current documentation implies:

https://www.haproxy.com/documentation/haproxy-configuration-manual/2-8r1/#1.1

HTTP/3 is implemented over QUIC, itself implemented over UDP. QUIC solves the
head of line blocking at transport level by means of independently treated
streams. Indeed, when experiencing loss, an impacted stream does not affect the
other streams. QUIC also provides connection migration support but currently
haproxy does not support it.

Expected Behavior

The connection migration happens seamlessly, and the user can reach the resource from a different network. Right now, since this isn't implemented, the connection times out for 30 seconds on browsers like Safari, then falls back to http2 and then back again to http3.

Steps to Reproduce the Behavior

  1. Open Safari on iPhone
  2. Load a page, ensure http3 is being used
  3. Switch to LTE

Do you have any idea what may have caused this?

Unimplemented part of the QUIC spec

Do you have an idea how to solve the issue?

I'm not familiar with the haproxy codebase.

What is your configuration?

frontend https_1443_in
        # bind tcp ip4/6
        bind *:1443 ssl crt /etc/apache2/ssl/haproxy.pem
        bind [::]:1443 ssl crt /etc/apache2/ssl/haproxy.pem

        # bind udp ip4/6
        bind quic4@*:1443 ssl crt /etc/apache2/ssl/haproxy.pem alpn h3
        bind quic6@[::]:1443 ssl crt /etc/apache2/ssl/haproxy.pem alpn h3

        # tell client we support http3 now
        http-response set-header Alt-Svc "h3=\":1443\"; ma=86400"

        mode http

        # pass real IP
        option forwardfor

        # pass ja4
        http-request lua.fingerprint_ja4
        http-request set-header X-Ja4 %[var(txn.fingerprint_ja4)]

        # route
        default_backend apache

backend apache
        server apache_server_443 127.0.0.1:443 ssl verify none check

Output of haproxy -vv

HAProxy version 3.4.6-1~bpo13+1 2026/09/30 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2031.
Known bugs: http://www.haproxy.org/bugs/bugs-3.4.6.html
Running on: Linux 6.12.107+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.107-1 (2026-08-29) x86_64
Build options : 
  TARGET  = linux-glibc
  CC      = x86_64-linux-gnu-gcc
  CFLAGS  = -O2 -g -fwrapv -fvect-cost-model=very-cheap -g -O2 -Werror=implicit-function-declaration -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2
  OPTIONS = USE_OPENSSL=1 USE_LUA=1 USE_SLZ=1 USE_OT=1 USE_QUIC=1 USE_PROMEX=1 USE_PCRE2=1 USE_PCRE2_JIT=1
  DEBUG   = 

Feature list : -51DEGREES +ACCEPT4 +ACME +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL -ECH -ENGINE +EPOLL -EVPORTS +GETADDRINFO +HAVE_TCP_MD5SIG -KQUEUE +KTLS -LIBATOMIC +LIBCRYPT +LINUX_CAP +LINUX_SPLICE +LINUX_TPROXY +LUA +MATH -MEMORY_PROFILING +NETFILTER +NS -OBSOLETE_LINKER +OPENSSL -OPENSSL_AWSLC -OPENSSL_WOLFSSL +OT -PCRE +PCRE2 +PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PROCCTL +PROMEX -PTHREAD_EMULATION +QUIC -QUIC_OPENSSL_COMPAT +RT +SHM_OPEN +SLZ +SSL -STATIC_PCRE -STATIC_PCRE2 +TFO +THREAD +THREAD_DUMP +TPROXY +TRACE -WURFL -ZLIB
Detected feature list : +HAVE_WORKING_TCP_MD5SIG

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_TGROUPS=32, MAX_THREADS=1024, default=8).
Built with SSL library version : OpenSSL 3.5.7 9 Jun 2026
Running on SSL library version : OpenSSL 3.5.7 9 Jun 2026
SSL library supports TLS extensions : yes
SSL library supports SNI : yes
SSL library default verify directory : /usr/lib/ssl/certs
SSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
OpenSSL providers loaded : default
QUIC: connection sock-per-conn mode support : yes
QUIC: GSO emission support : yes
Built with Lua version : Lua 5.4.7
Built with the Prometheus exporter as a service
Built with network namespace support.
Built with OpenTracing support.
Built with libslz for stateless compression.
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.46 2025-08-27
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with gcc compiler version 14.2.0

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
       qmux : mode=HTTP  side=FE|BE  mux=QMUX  flags=HTX|NO_UPG
       quic : mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
         h2 : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
  <default> : mode=HTTP  side=FE|BE  mux=H1    flags=HTX
         h1 : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
       fcgi : mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
  <default> : mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG
       spop : mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG
  <default> : mode=TCP   side=FE|BE  mux=PASS  flags=
       none : mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG

Available services : prometheus-exporter
Available filters :
	[BWLIM] bwlim-in
	[BWLIM] bwlim-out
	[CACHE] cache
	[COMP] comp-req
	[COMP] comp-res
	[COMP] compression
	[FCGI] fcgi-app
	[  OT] opentracing
	[SPOE] spoe
	[TRACE] trace

Last Outputs and Backtraces


Additional Information

No response

Activity

  1. self-assigned this
    on Oct 13, 2026
  2. haproxyFred commented on Oct 13, 2026

    @haproxyFred
    Contributor

    I've started working on this issue, but it's not a easy one to fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

status: needs-triageThis issue needs to be triaged.type: bugThis issue describes a bug.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions