FEATURE/MEDIUM: mux: add H2 fingerprint sample fetches with USE_MUX_FINGERPRINT compile flag
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 18/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bien especificado
- Estado de actividad
- Tranquilo
- Stack tecnológico
- c
- Área
- networking
Línea de trabajo
Read h2c_handle_settings(), h2c_handle_window_update(), h2c_handle_priority() and the HPACK decode path in src/mux_h2.c to see where the raw frame data is currently discarded. Then follow the MUX_CTL_* enum in include/haproxy/connection-t.h, the stub handlers in src/mux_pt.c, and the fetch registration pattern in src/connection.c. Build both with and without USE_MUX_FINGERPRINT from the Makefile use_opts; done means the four fc_h2_*/bc_h2_* fetches return the captured data for H2 connections, empty for H1, and the documentation entries in doc/configuration.txt match.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
This adds four new sample fetches that expose H2 connection-level frame data needed for HTTP/2 protocol fingerprinting:
fc_h2_settings_bin/bc_h2_settings_bin(binary) — raw SETTINGS payload in wire orderfc_h2_window_update/bc_h2_window_update(integer) — connection-level WINDOW_UPDATE incrementfc_h2_priority/bc_h2_priority(string) — PRIORITY frames assid:exclusive:dep:weighttuplesfc_h2_pseudo_order/bc_h2_pseudo_order(string) — pseudo-header order (e.g.m,a,s,p)
The feature is gated behind a new opt-in USE_MUX_FINGERPRINT compile flag (~80 bytes per H2 connection overhead, off by default). The flag is generic enough to also cover a future H3/QUIC fingerprinting patch (same #ifdef USE_MUX_FINGERPRINT guards in src/h3.c and src/mux_quic.c).
Motivation
HTTP/2 fingerprinting is increasingly used for bot detection, client identification, and security analytics. The H2 mux (src/mux_h2.c) already parses SETTINGS, WINDOW_UPDATE, and PRIORITY frames but discards most of the data after applying the settings. Pseudo-header order is lost entirely when HPACK-decoded headers are converted to HTX.
Currently there is no way to access this data from HAProxy configuration — the only existing H2-related fetches are fc_http_major, fc_nb_streams, and fc_settings_streams_limit, which don't expose enough information for fingerprinting.
The USE_MUX_FINGERPRINT compile flag makes the feature opt-in so deployments that don't need fingerprinting pay no memory overhead. When the flag is off, no storage is allocated, no data is captured, and the fetches are not registered (config referencing them fails to parse with "unknown fetch method").
Implementation
A 10-patch series is available on the feat/mux-fingerprint branch of my fork. The patches are split per CONTRIBUTING guidelines:
| # | Patch | Description |
|---|---|---|
| 1 | BUILD: add USE_MUX_FINGERPRINT compile option |
Add opt-in flag to Makefile use_opts |
| 2 | MEDIUM: mux: add MUX_CTL fingerprint commands to mux ctl interface |
4 new MUX_CTL_* enum values + mux_pt stubs |
| 3 | MEDIUM: mux/h2: add fingerprint storage fields to struct h2c |
#ifdef-guarded fields (~80 bytes) |
| 4 | MEDIUM: mux/h2: save raw SETTINGS payload for fingerprinting |
Capture in h2c_handle_settings() |
| 5 | MEDIUM: mux/h2: save connection WINDOW_UPDATE increment for fingerprinting |
Capture in h2c_handle_window_update() |
| 6 | MEDIUM: mux/h2: save PRIORITY frame data for fingerprinting |
Capture in h2c_handle_priority() |
| 7 | MEDIUM: mux/h2: save pseudo-header order for fingerprinting |
Capture after hpack_decode_frame(), before h2_make_htx_request() |
| 8 | MEDIUM: mux/h2: handle fingerprint MUX_CTL commands in h2_ctl() |
Return stored data via mux ctl interface |
| 9 | MEDIUM: connection: add H2 fingerprint sample fetches |
4 fetch functions + 8 keyword registrations |
| 10 | DOC: add fc_h2_*/bc_h2_* fingerprint sample fetches documentation |
doc/configuration.txt entries |
Design notes
- Storage:
struct h2cgains ~80 bytes of#ifdef-guarded fields (fp_settings_raw[64],fp_conn_wu,fp_pseudo_order[8],fp_prio[4], counters). Allocated viapool_zallocso zero-initialized. - Only first frames saved: Fingerprinting uses the first SETTINGS, first connection WINDOW_UPDATE, and first HEADERS frame. Subsequent frames are not saved.
- PRIORITY cap: Up to 4 PRIORITY frames stored. Most modern clients send 0 (they use
SETTINGS_NO_RFC7540_PRIORITIES=9). - Pseudo-header capture: Both indexed pseudo-headers (
n.name == NULL,n.len = H2_PHDR_IDX_*) and literal ones (name starting with:) are handled. Capture stops at the first regular header since pseudo-headers always appear first in the HPACK list. - Frontend only: Pseudo-header order is captured for request HEADERS only (
!H2_CF_IS_BACK), not responses or trailers. MUX_CTL_*enum not guarded: The enum values are zero-cost; the mux handler cases are#ifdef-guarded.mux_ptreturns 0 for all four commands unconditionally.
Files changed
Makefile—USE_MUX_FINGERPRINTinuse_opts+ doc commentinclude/haproxy/connection-t.h— 4 newMUX_CTL_*enum valuessrc/mux_h2.c—struct h2cfields, frame capture,h2_ctl()handlerssrc/mux_pt.c— stub handlers (return 0)src/connection.c— 4 sample fetch functions + 8 keyword registrationsdoc/configuration.txt— 8 new fetch entries (4fc_+ 4bc_)
Verification
Build
make TARGET=osx USE_OPENSSL=1— compiles cleanly (feature off,-MUX_FINGERPRINTinhaproxy -vv)make TARGET=osx USE_OPENSSL=1 USE_MUX_FINGERPRINT=1— compiles cleanly (feature on,+MUX_FINGERPRINT)- Config referencing
fc_h2_settings_binfails to parse when feature is off ("unknown fetch method") - Config with all 4 fetches parses OK when feature is on
Functional tests
Tested with a 3-frontend config (h2c on :8080, H2-over-TLS on :8443, HTTP/1.1 on :8081) with fetches in log-format:
curl --http2-prior-knowledge (h2c):
h2c settings=000300000064000400010000000200000000 wu=1048510465 prio=- phdr=m,s,a major=2
SETTINGS decoded: MAX_CONCURRENT_STREAMS=100, INITIAL_WINDOW_SIZE=65536, ENABLE_PUSH=0
curl --http2 (H2-over-TLS):
h2tls settings=000300000064000400010000000200000000 wu=1048510465 prio=- phdr=m,s,a major=2
Same as h2c (same curl client).
curl --http1.1:
h1 settings=- wu=-1 prio=- phdr=- major=1
All fetches return empty/0 for HTTP/1.1.
Python h2 client with PRIORITY frames:
h2c settings=00010000100000020000000100040000FFFF000500004000000800000000000300000064000600010000 wu=0 prio=3:1:0:201 phdr=m,p,a major=2
SETTINGS: 7 entries (HEADER_TABLE_SIZE=4096, ENABLE_PUSH=1, INITIAL_WINDOW_SIZE=65535, MAX_FRAME_SIZE=17408, ENABLE_CONNECT_PROTOCOL=0, MAX_CONCURRENT_STREAMS=100, MAX_HEADER_LIST_SIZE=65536). PRIORITY: stream=3, exclusive=1, dep=0, weight=201. Pseudo-header order: method, path, authority.
Test plan
-
makecompiles cleanly withoutUSE_MUX_FINGERPRINT -
make USE_MUX_FINGERPRINT=1compiles cleanly -
haproxy -vvshows-MUX_FINGERPRINTwhen off,+MUX_FINGERPRINTwhen on - Config with
fc_h2_settings_binfails to parse when feature is off - Config with all 4 fetches parses OK when feature is on
- h2c test:
curl --http2-prior-knowledge— fetches return correct H2 frame data - H2-over-TLS test:
curl --http2— fetches return correct H2 frame data - HTTP/1.1 test: all fetches return empty/0
- PRIORITY frame test: Python h2 client with PRIORITY frames —
fc_h2_priorityreturns correct data - Pseudo-header order: different clients (curl vs Python h2) produce different orders (
m,s,avsm,p,a)
- Lenguaje dominante
- C
- Estrellas
- 6.9k
- Forks
- 976
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de haproxy/haproxy
-
type: feature
Dificultad 1/5 Menos de una hora Aptitud para principiantes 77/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
type: code-report
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
-
type: code-report
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
Todos los issues de haproxy/haproxy
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
libsdl-org/SDL#16530 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
FriendsofECCE/ECCE#336 · 1 comentario ·
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
fw876/helloworld#2067 ·
Los mantenedores suelen responder en 1 día
-
mediatek/filogic: OpenFi 6C (openfi,6c): func key has wrong polarity, event class and key codeAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
immortalwrt/immortalwrt#2501 ·
-
dnsmasq版本低Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
coolsnowwolf/lede#14222 ·