Klaus Demo nginx / 55f08fc
Core: revised the PROXY protocol v2 code. - use normal prefixes for types and macros - removed some macros and types - revised debug messages - removed useless check of ngx_sock_ntop() returning 0 - removed special processing of AF_UNSPEC Ruslan Ermilov 3 years ago
1 changed file(s) with 87 addition(s) and 103 deletion(s). Raw diff Collapse all Expand all
88 #include <ngx_core.h>
99
1010
11 #define NGX_PP_V2_SIGLEN 12
12 #define NGX_PP_V2_CMD_PROXY 1
13 #define NGX_PP_V2_STREAM 1
14
15 #define NGX_PP_V2_AF_UNSPEC 0
16 #define NGX_PP_V2_AF_INET 1
17 #define NGX_PP_V2_AF_INET6 2
18
19
20 #define ngx_pp_v2_get_u16(p) ((p)[0] << 8 | (p)[1])
11 #define NGX_PROXY_PROTOCOL_AF_INET 1
12 #define NGX_PROXY_PROTOCOL_AF_INET6 2
13
14
15 #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
2116
2217
2318 typedef struct {
24 u_char signature[NGX_PP_V2_SIGLEN];
25 u_char ver_cmd;
26 u_char family_transport;
27 u_char len[2];
28 } ngx_pp_v2_header_t;
19 u_char signature[12];
20 u_char version_command;
21 u_char family_transport;
22 u_char len[2];
23 } ngx_proxy_protocol_header_t;
2924
3025
3126 typedef struct {
32 u_char src[4];
33 u_char dst[4];
34 u_char sport[2];
35 u_char dport[2];
36 } ngx_pp_v2_inet_addrs_t;
27 u_char s_addr[4];
28 u_char d_addr[4];
29 u_char s_port[2];
30 u_char d_port[2];
31 } ngx_proxy_protocol_inet_addrs_t;
3732
3833
3934 typedef struct {
40 u_char src[16];
41 u_char dst[16];
42 u_char sport[2];
43 u_char dport[2];
44 } ngx_pp_v2_inet6_addrs_t;
45
46
47 typedef union {
48 ngx_pp_v2_inet_addrs_t inet;
49 ngx_pp_v2_inet6_addrs_t inet6;
50 } ngx_pp_v2_addrs_t;
35 u_char s_addr[16];
36 u_char d_addr[16];
37 u_char s_port[2];
38 u_char d_port[2];
39 } ngx_proxy_protocol_inet6_addrs_t;
5140
5241
5342 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
5443 u_char *last);
55
56 static const u_char ngx_pp_v2_signature[NGX_PP_V2_SIGLEN] =
57 { 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x0d, 0x0a, 0x51, 0x55, 0x49, 0x54, 0x0a };
5844
5945
6046 u_char *
6450 u_char ch, *p, *addr, *port;
6551 ngx_int_t n;
6652
53 static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
54
6755 p = buf;
6856 len = last - buf;
6957
70 if (len >= sizeof(ngx_pp_v2_header_t)
71 && memcmp(p, ngx_pp_v2_signature, NGX_PP_V2_SIGLEN) == 0)
58 if (len >= sizeof(ngx_proxy_protocol_header_t)
59 && memcmp(p, signature, sizeof(signature) - 1) == 0)
7260 {
7361 return ngx_proxy_protocol_v2_read(c, buf, last);
7462 }
226214 static u_char *
227215 ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
228216 {
229 u_char *end;
230 size_t len;
231 socklen_t socklen;
232 ngx_str_t *name;
233 ngx_uint_t ver, cmd, family, transport;
234 ngx_sockaddr_t sockaddr;
235 ngx_pp_v2_addrs_t *addrs;
236 ngx_pp_v2_header_t *hdr;
237
238 hdr = (ngx_pp_v2_header_t *) buf;
239
240 buf += sizeof(ngx_pp_v2_header_t);
241
242 ver = hdr->ver_cmd >> 4;
243
244 if (ver != 2) {
217 u_char *end;
218 size_t len;
219 socklen_t socklen;
220 ngx_uint_t version, command, family, transport;
221 ngx_sockaddr_t sockaddr;
222 ngx_proxy_protocol_header_t *header;
223 ngx_proxy_protocol_inet_addrs_t *inet;
224 #if (NGX_HAVE_INET6)
225 ngx_proxy_protocol_inet6_addrs_t *inet6;
226 #endif
227
228 header = (ngx_proxy_protocol_header_t *) buf;
229
230 buf += sizeof(ngx_proxy_protocol_header_t);
231
232 version = header->version_command >> 4;
233
234 if (version != 2) {
245235 ngx_log_error(NGX_LOG_ERR, c->log, 0,
246 "unsupported PROXY protocol version: %ui", ver);
247 return NULL;
248 }
249
250 len = ngx_pp_v2_get_u16(hdr->len);
236 "unknown PROXY protocol version: %ui", version);
237 return NULL;
238 }
239
240 len = ngx_proxy_protocol_parse_uint16(header->len);
251241
252242 if ((size_t) (last - buf) < len) {
253243 ngx_log_error(NGX_LOG_ERR, c->log, 0, "header is too large");
256246
257247 end = buf + len;
258248
259 cmd = hdr->ver_cmd & 0x0f;
260
261 if (cmd != NGX_PP_V2_CMD_PROXY) {
249 command = header->version_command & 0x0f;
250
251 /* only PROXY is supported */
252 if (command != 1) {
262253 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
263 "PROXY protocol v2 unsupported command 0x%xi", cmd);
254 "PROXY protocol v2 unsupported command %ui", command);
264255 return end;
265256 }
266257
267 transport = hdr->family_transport & 0x0f;
268
269 if (transport != NGX_PP_V2_STREAM) {
258 transport = header->family_transport & 0x0f;
259
260 /* only STREAM is supported */
261 if (transport != 1) {
270262 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
271 "PROXY protocol v2 unsupported transport 0x%xi",
263 "PROXY protocol v2 unsupported transport %ui",
272264 transport);
273265 return end;
274266 }
275267
276 family = hdr->family_transport >> 4;
277
278 addrs = (ngx_pp_v2_addrs_t *) buf;
268 family = header->family_transport >> 4;
279269
280270 switch (family) {
281271
282 case NGX_PP_V2_AF_UNSPEC:
283 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
284 "PROXY protocol v2 AF_UNSPEC ignored");
285 return end;
286
287 case NGX_PP_V2_AF_INET:
288
289 if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet_addrs_t)) {
272 case NGX_PROXY_PROTOCOL_AF_INET:
273
274 if ((size_t) (end - buf) < sizeof(ngx_proxy_protocol_inet_addrs_t)) {
290275 return NULL;
291276 }
277
278 inet = (ngx_proxy_protocol_inet_addrs_t *) buf;
292279
293280 sockaddr.sockaddr_in.sin_family = AF_INET;
294281 sockaddr.sockaddr_in.sin_port = 0;
295 memcpy(&sockaddr.sockaddr_in.sin_addr, addrs->inet.src, 4);
296
297 c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet.sport);
282 memcpy(&sockaddr.sockaddr_in.sin_addr, inet->s_addr, 4);
283
284 c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(inet->s_port);
298285
299286 socklen = sizeof(struct sockaddr_in);
300287
301 buf += sizeof(ngx_pp_v2_inet_addrs_t);
288 buf += sizeof(ngx_proxy_protocol_inet_addrs_t);
302289
303290 break;
304291
305292 #if (NGX_HAVE_INET6)
306293
307 case NGX_PP_V2_AF_INET6:
308
309 if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet6_addrs_t)) {
294 case NGX_PROXY_PROTOCOL_AF_INET6:
295
296 if ((size_t) (end - buf) < sizeof(ngx_proxy_protocol_inet6_addrs_t)) {
310297 return NULL;
311298 }
299
300 inet6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
312301
313302 sockaddr.sockaddr_in6.sin6_family = AF_INET6;
314303 sockaddr.sockaddr_in6.sin6_port = 0;
315 memcpy(&sockaddr.sockaddr_in6.sin6_addr, addrs->inet6.src, 16);
316
317 c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet6.sport);
304 memcpy(&sockaddr.sockaddr_in6.sin6_addr, inet6->s_addr, 16);
305
306 c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(inet6->s_port);
318307
319308 socklen = sizeof(struct sockaddr_in6);
320309
321 buf += sizeof(ngx_pp_v2_inet6_addrs_t);
310 buf += sizeof(ngx_proxy_protocol_inet6_addrs_t);
322311
323312 break;
324313
325314 #endif
326315
327316 default:
328
329317 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
330 "PROXY protocol v2 unsupported address family 0x%xi",
318 "PROXY protocol v2 unsupported address family %ui",
331319 family);
332320 return end;
333321 }
334322
335 name = &c->proxy_protocol_addr;
336
337 name->data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
338 if (name->data == NULL) {
339 return NULL;
340 }
341
342 name->len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, name->data,
343 NGX_SOCKADDR_STRLEN, 0);
344 if (name->len == 0) {
345 return NULL;
346 }
323 c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
324 if (c->proxy_protocol_addr.data == NULL) {
325 return NULL;
326 }
327
328 c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
329 c->proxy_protocol_addr.data,
330 NGX_SOCKADDR_STRLEN, 0);
347331
348332 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
349 "PROXY protocol v2 address: %V %d", name,
333 "PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr,
350334 c->proxy_protocol_port);
351335
352336 if (buf < end) {
353337 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
354 "PROXY protocol v2 %z bytes tlv ignored", end - buf);
338 "PROXY protocol v2 %z bytes of tlv ignored", end - buf);
355339 }
356340
357341 return end;