Skip to content

(feat) Add PROXY protocol v2 (PPv2) header support#115

Open
zongqi-wang wants to merge 1 commit intoDNS-OARC:mainfrom
zongqi-wang:cedric/ppv2
Open

(feat) Add PROXY protocol v2 (PPv2) header support#115
zongqi-wang wants to merge 1 commit intoDNS-OARC:mainfrom
zongqi-wang:cedric/ppv2

Conversation

@zongqi-wang
Copy link
Copy Markdown

@zongqi-wang zongqi-wang commented Apr 9, 2026

Summary

  • Add --proxy SRC_ADDR[#SRC_PORT]-DST_ADDR[#DST_PORT] CLI option to prepend PROXY protocol v2 headers to DNS queries
  • Supports IPv4/IPv6, UDP (per-datagram), TCP/DoT/DoH (per-connection), with address family auto-detection
  • Extract Protocol enum into protocol.h to break circular dependency with new proxy.h/proxy.cpp module
  • Cache the generated PPv2 header in TrafGen to avoid per-packet reconstruction
  • Add comprehensive test suite (30+ tests) covering all protocol/family combinations, address encoding, port boundaries, round-trips, and error cases
  • Update README with usage examples and detailed feature documentation

Test plan

  • meson test passes (all 30+ proxy protocol tests)
  • ninja builds cleanly with warning_level=3
  • Manual test: flame --proxy 127.0.0.1#4321-127.0.0.2#53 <target> over UDP
  • Manual test: flame -P tcp --proxy 127.0.0.1#4321-127.0.0.2#53 <target> over TCP
  • Manual test: IPv6 variant with [::1] bracket syntax
  • Verify PPv2 header with packet capture — signature, ver/cmd, family/proto, addresses, ports all byte-correct

Testing notes

UDP + IPv4 proxy

$ ./build/flame --proxy 127.0.0.1#4321-127.0.0.2#53 -l 2 -c 1 -q 1 -v 2 8.8.8.8
PROXY v2 header enabled
avg pkt: 65 bytes  (28 PPv2 IPv4 header + 37 DNS query)

TCP + IPv4 proxy

$ ./build/flame --proxy 127.0.0.1#4321-127.0.0.2#53 -P tcp -l 2 -c 1 -q 1 -v 2 8.8.8.8
PROXY v2 header enabled
tcp conn.: 1  (header sent once at connection establishment)

UDP + IPv6 proxy

$ ./build/flame -F inet6 --proxy '[::1]#4321-[::1]#53' -l 2 -c 1 -q 1 -v 2 '[2001:4860:4860::8888]'
PROXY v2 header enabled
avg pkt: 89 bytes  (52 PPv2 IPv6 header + 37 DNS query)

Wire capture verification

Captured a UDP packet sent to a local listener and verified every field:

PPv2 signature valid: True
Ver/cmd byte: 0x21 (version 2, PROXY command)
Family/proto byte: 0x12 (IPv4 + DGRAM)
Address length: 12
Src: 192.168.1.100:4321
Dst: 10.0.0.1:53
DNS payload starts at byte 28, remaining 37 bytes

Design notes

  • PPv2 header is generated once at TrafGen::start() and cached in _cached_proxy_header to avoid per-packet allocation overhead.
  • For TCP/DoT/DoH, the header is written on the raw TCP stream before on_connect_event() (TLS handshake). libuv guarantees FIFO write ordering, so the header precedes the ClientHello.
  • The --proxy flag uses AF_UNSPEC for address family auto-detection, since the PPv2 header describes the original client's addresses, not the flamethrower transport.

@zongqi-wang zongqi-wang changed the title Add PROXY protocol v2 (PPv2) header support (feat) Add PROXY protocol v2 (PPv2) header support Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant