comparison src/core/ngx_proxy_protocol.c @ 7253:63e91f263a49

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
author Ruslan Ermilov <ru@nginx.com>
date Mon, 02 Apr 2018 18:40:04 +0300
parents 7bdab16c55f1
children 1fd992589ffe
comparison
equal deleted inserted replaced
7252:7bdab16c55f1 7253:63e91f263a49
7 7
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 10
11 11
12 #define NGX_PP_V2_SIGLEN 12 12 #define NGX_PROXY_PROTOCOL_AF_INET 1
13 #define NGX_PP_V2_CMD_PROXY 1 13 #define NGX_PROXY_PROTOCOL_AF_INET6 2
14 #define NGX_PP_V2_STREAM 1 14
15 15
16 #define NGX_PP_V2_AF_UNSPEC 0 16 #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
17 #define NGX_PP_V2_AF_INET 1
18 #define NGX_PP_V2_AF_INET6 2
19
20
21 #define ngx_pp_v2_get_u16(p) ((p)[0] << 8 | (p)[1])
22 17
23 18
24 typedef struct { 19 typedef struct {
25 u_char signature[NGX_PP_V2_SIGLEN]; 20 u_char signature[12];
26 u_char ver_cmd; 21 u_char version_command;
27 u_char family_transport; 22 u_char family_transport;
28 u_char len[2]; 23 u_char len[2];
29 } ngx_pp_v2_header_t; 24 } ngx_proxy_protocol_header_t;
30 25
31 26
32 typedef struct { 27 typedef struct {
33 u_char src[4]; 28 u_char s_addr[4];
34 u_char dst[4]; 29 u_char d_addr[4];
35 u_char sport[2]; 30 u_char s_port[2];
36 u_char dport[2]; 31 u_char d_port[2];
37 } ngx_pp_v2_inet_addrs_t; 32 } ngx_proxy_protocol_inet_addrs_t;
38 33
39 34
40 typedef struct { 35 typedef struct {
41 u_char src[16]; 36 u_char s_addr[16];
42 u_char dst[16]; 37 u_char d_addr[16];
43 u_char sport[2]; 38 u_char s_port[2];
44 u_char dport[2]; 39 u_char d_port[2];
45 } ngx_pp_v2_inet6_addrs_t; 40 } ngx_proxy_protocol_inet6_addrs_t;
46
47
48 typedef union {
49 ngx_pp_v2_inet_addrs_t inet;
50 ngx_pp_v2_inet6_addrs_t inet6;
51 } ngx_pp_v2_addrs_t;
52 41
53 42
54 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, 43 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
55 u_char *last); 44 u_char *last);
56
57 static const u_char ngx_pp_v2_signature[NGX_PP_V2_SIGLEN] =
58 { 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x0d, 0x0a, 0x51, 0x55, 0x49, 0x54, 0x0a };
59 45
60 46
61 u_char * 47 u_char *
62 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) 48 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
63 { 49 {
64 size_t len; 50 size_t len;
65 u_char ch, *p, *addr, *port; 51 u_char ch, *p, *addr, *port;
66 ngx_int_t n; 52 ngx_int_t n;
67 53
54 static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
55
68 p = buf; 56 p = buf;
69 len = last - buf; 57 len = last - buf;
70 58
71 if (len >= sizeof(ngx_pp_v2_header_t) 59 if (len >= sizeof(ngx_proxy_protocol_header_t)
72 && memcmp(p, ngx_pp_v2_signature, NGX_PP_V2_SIGLEN) == 0) 60 && memcmp(p, signature, sizeof(signature) - 1) == 0)
73 { 61 {
74 return ngx_proxy_protocol_v2_read(c, buf, last); 62 return ngx_proxy_protocol_v2_read(c, buf, last);
75 } 63 }
76 64
77 if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) { 65 if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
225 213
226 214
227 static u_char * 215 static u_char *
228 ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last) 216 ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
229 { 217 {
230 u_char *end; 218 u_char *end;
231 size_t len; 219 size_t len;
232 socklen_t socklen; 220 socklen_t socklen;
233 ngx_str_t *name; 221 ngx_uint_t version, command, family, transport;
234 ngx_uint_t ver, cmd, family, transport; 222 ngx_sockaddr_t sockaddr;
235 ngx_sockaddr_t sockaddr; 223 ngx_proxy_protocol_header_t *header;
236 ngx_pp_v2_addrs_t *addrs; 224 ngx_proxy_protocol_inet_addrs_t *inet;
237 ngx_pp_v2_header_t *hdr; 225 #if (NGX_HAVE_INET6)
238 226 ngx_proxy_protocol_inet6_addrs_t *inet6;
239 hdr = (ngx_pp_v2_header_t *) buf; 227 #endif
240 228
241 buf += sizeof(ngx_pp_v2_header_t); 229 header = (ngx_proxy_protocol_header_t *) buf;
242 230
243 ver = hdr->ver_cmd >> 4; 231 buf += sizeof(ngx_proxy_protocol_header_t);
244 232
245 if (ver != 2) { 233 version = header->version_command >> 4;
234
235 if (version != 2) {
246 ngx_log_error(NGX_LOG_ERR, c->log, 0, 236 ngx_log_error(NGX_LOG_ERR, c->log, 0,
247 "unsupported PROXY protocol version: %ui", ver); 237 "unknown PROXY protocol version: %ui", version);
248 return NULL; 238 return NULL;
249 } 239 }
250 240
251 len = ngx_pp_v2_get_u16(hdr->len); 241 len = ngx_proxy_protocol_parse_uint16(header->len);
252 242
253 if ((size_t) (last - buf) < len) { 243 if ((size_t) (last - buf) < len) {
254 ngx_log_error(NGX_LOG_ERR, c->log, 0, "header is too large"); 244 ngx_log_error(NGX_LOG_ERR, c->log, 0, "header is too large");
255 return NULL; 245 return NULL;
256 } 246 }
257 247
258 end = buf + len; 248 end = buf + len;
259 249
260 cmd = hdr->ver_cmd & 0x0f; 250 command = header->version_command & 0x0f;
261 251
262 if (cmd != NGX_PP_V2_CMD_PROXY) { 252 /* only PROXY is supported */
253 if (command != 1) {
263 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, 254 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
264 "PROXY protocol v2 unsupported command 0x%xi", cmd); 255 "PROXY protocol v2 unsupported command %ui", command);
265 return end; 256 return end;
266 } 257 }
267 258
268 transport = hdr->family_transport & 0x0f; 259 transport = header->family_transport & 0x0f;
269 260
270 if (transport != NGX_PP_V2_STREAM) { 261 /* only STREAM is supported */
262 if (transport != 1) {
271 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, 263 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
272 "PROXY protocol v2 unsupported transport 0x%xi", 264 "PROXY protocol v2 unsupported transport %ui",
273 transport); 265 transport);
274 return end; 266 return end;
275 } 267 }
276 268
277 family = hdr->family_transport >> 4; 269 family = header->family_transport >> 4;
278
279 addrs = (ngx_pp_v2_addrs_t *) buf;
280 270
281 switch (family) { 271 switch (family) {
282 272
283 case NGX_PP_V2_AF_UNSPEC: 273 case NGX_PROXY_PROTOCOL_AF_INET:
284 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, 274
285 "PROXY protocol v2 AF_UNSPEC ignored"); 275 if ((size_t) (end - buf) < sizeof(ngx_proxy_protocol_inet_addrs_t)) {
286 return end;
287
288 case NGX_PP_V2_AF_INET:
289
290 if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet_addrs_t)) {
291 return NULL; 276 return NULL;
292 } 277 }
278
279 inet = (ngx_proxy_protocol_inet_addrs_t *) buf;
293 280
294 sockaddr.sockaddr_in.sin_family = AF_INET; 281 sockaddr.sockaddr_in.sin_family = AF_INET;
295 sockaddr.sockaddr_in.sin_port = 0; 282 sockaddr.sockaddr_in.sin_port = 0;
296 memcpy(&sockaddr.sockaddr_in.sin_addr, addrs->inet.src, 4); 283 memcpy(&sockaddr.sockaddr_in.sin_addr, inet->s_addr, 4);
297 284
298 c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet.sport); 285 c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(inet->s_port);
299 286
300 socklen = sizeof(struct sockaddr_in); 287 socklen = sizeof(struct sockaddr_in);
301 288
302 buf += sizeof(ngx_pp_v2_inet_addrs_t); 289 buf += sizeof(ngx_proxy_protocol_inet_addrs_t);
303 290
304 break; 291 break;
305 292
306 #if (NGX_HAVE_INET6) 293 #if (NGX_HAVE_INET6)
307 294
308 case NGX_PP_V2_AF_INET6: 295 case NGX_PROXY_PROTOCOL_AF_INET6:
309 296
310 if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet6_addrs_t)) { 297 if ((size_t) (end - buf) < sizeof(ngx_proxy_protocol_inet6_addrs_t)) {
311 return NULL; 298 return NULL;
312 } 299 }
300
301 inet6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
313 302
314 sockaddr.sockaddr_in6.sin6_family = AF_INET6; 303 sockaddr.sockaddr_in6.sin6_family = AF_INET6;
315 sockaddr.sockaddr_in6.sin6_port = 0; 304 sockaddr.sockaddr_in6.sin6_port = 0;
316 memcpy(&sockaddr.sockaddr_in6.sin6_addr, addrs->inet6.src, 16); 305 memcpy(&sockaddr.sockaddr_in6.sin6_addr, inet6->s_addr, 16);
317 306
318 c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet6.sport); 307 c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(inet6->s_port);
319 308
320 socklen = sizeof(struct sockaddr_in6); 309 socklen = sizeof(struct sockaddr_in6);
321 310
322 buf += sizeof(ngx_pp_v2_inet6_addrs_t); 311 buf += sizeof(ngx_proxy_protocol_inet6_addrs_t);
323 312
324 break; 313 break;
325 314
326 #endif 315 #endif
327 316
328 default: 317 default:
329
330 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, 318 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
331 "PROXY protocol v2 unsupported address family 0x%xi", 319 "PROXY protocol v2 unsupported address family %ui",
332 family); 320 family);
333 return end; 321 return end;
334 } 322 }
335 323
336 name = &c->proxy_protocol_addr; 324 c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
337 325 if (c->proxy_protocol_addr.data == NULL) {
338 name->data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); 326 return NULL;
339 if (name->data == NULL) { 327 }
340 return NULL; 328
341 } 329 c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
342 330 c->proxy_protocol_addr.data,
343 name->len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, name->data, 331 NGX_SOCKADDR_STRLEN, 0);
344 NGX_SOCKADDR_STRLEN, 0);
345 if (name->len == 0) {
346 return NULL;
347 }
348 332
349 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, 333 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
350 "PROXY protocol v2 address: %V %d", name, 334 "PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr,
351 c->proxy_protocol_port); 335 c->proxy_protocol_port);
352 336
353 if (buf < end) { 337 if (buf < end) {
354 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, 338 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
355 "PROXY protocol v2 %z bytes tlv ignored", end - buf); 339 "PROXY protocol v2 %z bytes of tlv ignored", end - buf);
356 } 340 }
357 341
358 return end; 342 return end;
359 } 343 }