DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
proxy_protocol.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file proxy_protocol.h
6 * @brief HAProxy PROXY protocol codec (DETWS_ENABLE_PROXY_PROTOCOL) - zero-heap parser +
7 * builder for the v1 (text) and v2 (binary) headers a load balancer / proxy prepends,
8 * so the server can recover the real client IPv4 when it sits behind one.
9 *
10 * The header is sent once, before the proxied stream:
11 * - v1 (text): `PROXY TCP4 <src-ip> <dst-ip> <src-port> <dst-port>\r\n` (space-separated,
12 * CRLF-terminated; also `PROXY TCP6 ...` and `PROXY UNKNOWN\r\n`).
13 * - v2 (binary): a 12-octet signature, then ver_cmd (high nibble version 2, low nibble
14 * command - 0x1 PROXY / 0x0 LOCAL), fam (high nibble address family - 0x1 AF_INET, low
15 * nibble transport - 0x1 STREAM), a 2-octet big-endian address-block length, then the
16 * address block (for TCP/IPv4: src(4) dst(4) src-port(2) dst-port(2), network order).
17 *
18 * This codec handles TCP/IPv4 (the library's address family); IPv6 / UNIX / LOCAL headers
19 * parse to their length but yield no addresses. Format per the HAProxy PROXY protocol spec.
20 *
21 * @author Douglas Quigg (dstroy0)
22 * @date 2026
23 */
24
25#ifndef DETERMINISTICESPASYNCWEBSERVER_PROXY_PROTOCOL_H
26#define DETERMINISTICESPASYNCWEBSERVER_PROXY_PROTOCOL_H
27
28#include "ServerConfig.h"
29
30#if DETWS_ENABLE_PROXY_PROTOCOL
31
32#include <stddef.h>
33#include <stdint.h>
34
35#define PROXY_V2_SIG_LEN 12 ///< v2 signature length
36#define PROXY_V2_VER_CMD_PROXY 0x21 ///< version 2 | PROXY command
37#define PROXY_V2_VER_CMD_LOCAL 0x20 ///< version 2 | LOCAL command
38#define PROXY_V2_FAM_TCP4 0x11 ///< AF_INET | STREAM (TCP over IPv4)
39
40/** @brief The decoded proxied connection endpoints (IPv4, host byte order). */
41struct ProxyInfo
42{
43 uint8_t version; ///< 1 or 2
44 bool has_addr; ///< true when TCP/IPv4 addresses were decoded
45 uint32_t src_addr; ///< real client IPv4 (host order)
46 uint32_t dst_addr; ///< proxied destination IPv4
47 uint16_t src_port;
48 uint16_t dst_port;
49};
50
51/**
52 * @brief Detect + parse a PROXY header (v1 or v2) at the head of [buf, buf+len).
53 * @param consumed receives the header length so the caller can skip it before the stream.
54 * @return true if a complete v1/v2 header was parsed; false if absent or not fully buffered.
55 */
56bool proxy_parse(const uint8_t *buf, size_t len, ProxyInfo *out, size_t *consumed);
57
58/** @brief Build a v1 (text) TCP4 header. Returns bytes written (excluding NUL), or 0. */
59size_t proxy_v1_build(char *buf, size_t cap, uint32_t src_addr, uint32_t dst_addr, uint16_t src_port,
60 uint16_t dst_port);
61
62/** @brief Build a v2 (binary) TCP/IPv4 PROXY header. Returns 28, or 0 on overflow. */
63size_t proxy_v2_build(uint8_t *buf, size_t cap, uint32_t src_addr, uint32_t dst_addr, uint16_t src_port,
64 uint16_t dst_port);
65
66#endif // DETWS_ENABLE_PROXY_PROTOCOL
67
68#endif // DETERMINISTICESPASYNCWEBSERVER_PROXY_PROTOCOL_H
User-facing configuration for DeterministicESPAsyncWebServer.