Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

FEATURE/MEDIUM: mux: add H2 fingerprint sample fetches with USE_MUX_FINGERPRINT compile flag

Abierto
#3,485 3 comentarios 0 reacciones 0 asignados Ver en GitHub

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 order
  • fc_h2_window_update / bc_h2_window_update (integer) — connection-level WINDOW_UPDATE increment
  • fc_h2_priority / bc_h2_priority (string) — PRIORITY frames as sid:exclusive:dep:weight tuples
  • fc_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 h2c gains ~80 bytes of #ifdef-guarded fields (fp_settings_raw[64], fp_conn_wu, fp_pseudo_order[8], fp_prio[4], counters). Allocated via pool_zalloc so 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_pt returns 0 for all four commands unconditionally.
Files changed
  • Makefile — USE_MUX_FINGERPRINT in use_opts + doc comment
  • include/haproxy/connection-t.h — 4 new MUX_CTL_* enum values
  • src/mux_h2.c — struct h2c fields, frame capture, h2_ctl() handlers
  • src/mux_pt.c — stub handlers (return 0)
  • src/connection.c — 4 sample fetch functions + 8 keyword registrations
  • doc/configuration.txt — 8 new fetch entries (4 fc_ + 4 bc_)

Verification

Build
  • make TARGET=osx USE_OPENSSL=1 — compiles cleanly (feature off, -MUX_FINGERPRINT in haproxy -vv)
  • make TARGET=osx USE_OPENSSL=1 USE_MUX_FINGERPRINT=1 — compiles cleanly (feature on, +MUX_FINGERPRINT)
  • Config referencing fc_h2_settings_bin fails 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
  • make compiles cleanly without USE_MUX_FINGERPRINT
  • make USE_MUX_FINGERPRINT=1 compiles cleanly
  • haproxy -vv shows -MUX_FINGERPRINT when off, +MUX_FINGERPRINT when on
  • Config with fc_h2_settings_bin fails 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_priority returns correct data
  • Pseudo-header order: different clients (curl vs Python h2) produce different orders (m,s,a vs m,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

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de haproxy/haproxy

Todos los issues de haproxy/haproxy

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.