Mercurial > hg > nginx
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 } |