Blame


1 80347df3 2026-02-18 kirill /*
2 80347df3 2026-02-18 kirill * Copyright (c) 2026 Christoph Liebender <christoph@liebender.dev>
3 80347df3 2026-02-18 kirill *
4 80347df3 2026-02-18 kirill * Permission to use, copy, modify, and distribute this software for any
5 80347df3 2026-02-18 kirill * purpose with or without fee is hereby granted, provided that the above
6 80347df3 2026-02-18 kirill * copyright notice and this permission notice appear in all copies.
7 80347df3 2026-02-18 kirill *
8 80347df3 2026-02-18 kirill * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 80347df3 2026-02-18 kirill * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 80347df3 2026-02-18 kirill * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 80347df3 2026-02-18 kirill * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 80347df3 2026-02-18 kirill * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 80347df3 2026-02-18 kirill * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 80347df3 2026-02-18 kirill * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 80347df3 2026-02-18 kirill */
16 80347df3 2026-02-18 kirill
17 80347df3 2026-02-18 kirill #include "relayd.h"
18 80347df3 2026-02-18 kirill
19 80347df3 2026-02-18 kirill #define PROXY_V2_CMD_PROXY 0x01
20 80347df3 2026-02-18 kirill
21 80347df3 2026-02-18 kirill #define PROXY_V2_FAM_UNSPEC 0x00
22 80347df3 2026-02-18 kirill #define PROXY_V2_FAM_TCP4 0x11
23 80347df3 2026-02-18 kirill #define PROXY_V2_FAM_UDP4 0x12
24 80347df3 2026-02-18 kirill #define PROXY_V2_FAM_TCP6 0x21
25 80347df3 2026-02-18 kirill #define PROXY_V2_FAM_UDP6 0x22
26 80347df3 2026-02-18 kirill
27 80347df3 2026-02-18 kirill static const u_int8_t PROXY_V2_SIG[12] = {
28 80347df3 2026-02-18 kirill 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A
29 80347df3 2026-02-18 kirill };
30 80347df3 2026-02-18 kirill
31 80347df3 2026-02-18 kirill struct proxy_v2_hdr {
32 80347df3 2026-02-18 kirill u_int8_t sig[12];
33 80347df3 2026-02-18 kirill u_int8_t ver_cmd;
34 80347df3 2026-02-18 kirill u_int8_t fam;
35 80347df3 2026-02-18 kirill u_int16_t len;
36 80347df3 2026-02-18 kirill };
37 80347df3 2026-02-18 kirill
38 80347df3 2026-02-18 kirill union proxy_v2_addr {
39 80347df3 2026-02-18 kirill struct {
40 80347df3 2026-02-18 kirill u_int32_t src_addr;
41 80347df3 2026-02-18 kirill u_int32_t dst_addr;
42 80347df3 2026-02-18 kirill in_port_t src_port;
43 80347df3 2026-02-18 kirill in_port_t dst_port;
44 80347df3 2026-02-18 kirill } ipv4_addr;
45 80347df3 2026-02-18 kirill struct {
46 80347df3 2026-02-18 kirill u_int8_t src_addr[16];
47 80347df3 2026-02-18 kirill u_int8_t dst_addr[16];
48 80347df3 2026-02-18 kirill in_port_t src_port;
49 80347df3 2026-02-18 kirill in_port_t dst_port;
50 80347df3 2026-02-18 kirill } ipv6_addr;
51 80347df3 2026-02-18 kirill };
52 80347df3 2026-02-18 kirill
53 80347df3 2026-02-18 kirill int
54 80347df3 2026-02-18 kirill proxy_protocol_v1(struct rsession *con, struct evbuffer *dstout)
55 80347df3 2026-02-18 kirill {
56 80347df3 2026-02-18 kirill char ibuf[128], obuf[128];
57 80347df3 2026-02-18 kirill const char *proxyproto;
58 80347df3 2026-02-18 kirill int ret;
59 80347df3 2026-02-18 kirill
60 80347df3 2026-02-18 kirill bzero(&ibuf, sizeof(ibuf));
61 80347df3 2026-02-18 kirill bzero(&obuf, sizeof(obuf));
62 80347df3 2026-02-18 kirill
63 80347df3 2026-02-18 kirill if (print_host(&con->se_in.ss, ibuf, sizeof(ibuf)) == NULL ||
64 80347df3 2026-02-18 kirill print_host(&con->se_sockname, obuf, sizeof(obuf)) == NULL)
65 80347df3 2026-02-18 kirill return -1;
66 80347df3 2026-02-18 kirill
67 80347df3 2026-02-18 kirill if (con->se_relay->rl_conf.flags & F_UDP)
68 80347df3 2026-02-18 kirill proxyproto = "UNKNOWN";
69 80347df3 2026-02-18 kirill else {
70 80347df3 2026-02-18 kirill switch (con->se_in.ss.ss_family) {
71 80347df3 2026-02-18 kirill case AF_INET:
72 80347df3 2026-02-18 kirill proxyproto = "TCP4";
73 80347df3 2026-02-18 kirill break;
74 80347df3 2026-02-18 kirill case AF_INET6:
75 80347df3 2026-02-18 kirill proxyproto = "TCP6";
76 80347df3 2026-02-18 kirill break;
77 80347df3 2026-02-18 kirill default:
78 80347df3 2026-02-18 kirill proxyproto = "UNKNOWN";
79 80347df3 2026-02-18 kirill break;
80 80347df3 2026-02-18 kirill }
81 80347df3 2026-02-18 kirill }
82 80347df3 2026-02-18 kirill
83 80347df3 2026-02-18 kirill ret = evbuffer_add_printf(dstout,
84 80347df3 2026-02-18 kirill "PROXY %s %s %s %d %d\r\n", proxyproto, ibuf, obuf,
85 80347df3 2026-02-18 kirill ntohs(con->se_in.port), ntohs(con->se_relay->rl_conf.port));
86 80347df3 2026-02-18 kirill
87 80347df3 2026-02-18 kirill return ret == -1 ? -1 : 0;
88 80347df3 2026-02-18 kirill }
89 80347df3 2026-02-18 kirill
90 80347df3 2026-02-18 kirill int
91 80347df3 2026-02-18 kirill proxy_protocol_v2(struct rsession *con, struct evbuffer *dstout)
92 80347df3 2026-02-18 kirill {
93 80347df3 2026-02-18 kirill union proxy_v2_addr addr;
94 80347df3 2026-02-18 kirill struct proxy_v2_hdr hdr;
95 80347df3 2026-02-18 kirill const struct relay_config *conf = &con->se_relay->rl_conf;
96 80347df3 2026-02-18 kirill const struct sockaddr_storage *srcss = &con->se_in.ss;
97 80347df3 2026-02-18 kirill const struct sockaddr_storage *dstss = &con->se_sockname;
98 80347df3 2026-02-18 kirill int error;
99 80347df3 2026-02-18 kirill in_port_t srcport = con->se_in.port;
100 80347df3 2026-02-18 kirill in_port_t dstport = conf->port;
101 80347df3 2026-02-18 kirill u_int16_t len;
102 80347df3 2026-02-18 kirill
103 80347df3 2026-02-18 kirill bcopy(PROXY_V2_SIG, hdr.sig, sizeof(hdr.sig));
104 80347df3 2026-02-18 kirill hdr.ver_cmd = 0x20 | PROXY_V2_CMD_PROXY;
105 80347df3 2026-02-18 kirill
106 80347df3 2026-02-18 kirill switch (dstss->ss_family) {
107 80347df3 2026-02-18 kirill case AF_INET:
108 80347df3 2026-02-18 kirill hdr.fam = (conf->flags & F_UDP) ?
109 80347df3 2026-02-18 kirill PROXY_V2_FAM_UDP4 : PROXY_V2_FAM_TCP4;
110 80347df3 2026-02-18 kirill len = sizeof(addr.ipv4_addr);
111 80347df3 2026-02-18 kirill addr.ipv4_addr.src_addr =
112 80347df3 2026-02-18 kirill ((const struct sockaddr_in *)srcss)->sin_addr.s_addr;
113 80347df3 2026-02-18 kirill addr.ipv4_addr.dst_addr =
114 80347df3 2026-02-18 kirill ((const struct sockaddr_in *)dstss)->sin_addr.s_addr;
115 80347df3 2026-02-18 kirill addr.ipv4_addr.src_port = srcport;
116 80347df3 2026-02-18 kirill addr.ipv4_addr.dst_port = dstport;
117 80347df3 2026-02-18 kirill break;
118 80347df3 2026-02-18 kirill case AF_INET6:
119 80347df3 2026-02-18 kirill hdr.fam = (conf->flags & F_UDP) ?
120 80347df3 2026-02-18 kirill PROXY_V2_FAM_UDP6 : PROXY_V2_FAM_TCP6;
121 80347df3 2026-02-18 kirill len = sizeof(addr.ipv6_addr);
122 80347df3 2026-02-18 kirill bcopy(&((const struct sockaddr_in6 *)srcss)->sin6_addr,
123 80347df3 2026-02-18 kirill addr.ipv6_addr.src_addr, sizeof(addr.ipv6_addr.src_addr));
124 80347df3 2026-02-18 kirill bcopy(&((const struct sockaddr_in6 *)dstss)->sin6_addr,
125 80347df3 2026-02-18 kirill addr.ipv6_addr.dst_addr, sizeof(addr.ipv6_addr.dst_addr));
126 80347df3 2026-02-18 kirill addr.ipv6_addr.src_port = srcport;
127 80347df3 2026-02-18 kirill addr.ipv6_addr.dst_port = dstport;
128 80347df3 2026-02-18 kirill break;
129 80347df3 2026-02-18 kirill default:
130 80347df3 2026-02-18 kirill hdr.fam = 0x00;
131 80347df3 2026-02-18 kirill len = 0;
132 80347df3 2026-02-18 kirill break;
133 80347df3 2026-02-18 kirill }
134 80347df3 2026-02-18 kirill
135 80347df3 2026-02-18 kirill hdr.len = htons(len);
136 80347df3 2026-02-18 kirill
137 80347df3 2026-02-18 kirill if ((error = evbuffer_add(dstout, &hdr, sizeof(hdr))) != 0)
138 80347df3 2026-02-18 kirill return error;
139 80347df3 2026-02-18 kirill
140 80347df3 2026-02-18 kirill if (len > 0 && (error = evbuffer_add(dstout, &addr, len)) != 0)
141 80347df3 2026-02-18 kirill return error;
142 80347df3 2026-02-18 kirill
143 80347df3 2026-02-18 kirill return 0;
144 80347df3 2026-02-18 kirill }