comparison src/core/ngx_proxy_protocol.c @ 5605:3a72b1805c52

Added server-side support for PROXY protocol v1 (ticket #355). Client address specified in the PROXY protocol header is now saved in the $proxy_protocol_addr variable and can be used in the realip module. This is currently not implemented for mail.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 17 Mar 2014 17:41:24 +0400
parents
children fa663739e115
comparison
equal deleted inserted replaced
5604:22d485944c20 5605:3a72b1805c52
1
2 /*
3 * Copyright (C) Roman Arutyunyan
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10
11
12 u_char *
13 ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
14 {
15 size_t len;
16 u_char ch, *p, *addr;
17
18 p = buf;
19 len = last - buf;
20
21 if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
22 goto invalid;
23 }
24
25 p += 6;
26 len -= 6;
27
28 if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
29 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
30 "PROXY protocol unknown protocol");
31 p += 7;
32 goto skip;
33 }
34
35 if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
36 || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
37 {
38 goto invalid;
39 }
40
41 p += 5;
42 addr = p;
43
44 for ( ;; ) {
45 if (p == last) {
46 goto invalid;
47 }
48
49 ch = *p++;
50
51 if (ch == ' ') {
52 break;
53 }
54
55 if (ch != ':' && ch != '.'
56 && (ch < 'a' || ch > 'f')
57 && (ch < 'A' || ch > 'F')
58 && (ch < '0' || ch > '9'))
59 {
60 goto invalid;
61 }
62 }
63
64 len = p - addr - 1;
65 c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
66
67 if (c->proxy_protocol_addr.data == NULL) {
68 return NULL;
69 }
70
71 ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
72 c->proxy_protocol_addr.len = len;
73
74 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
75 "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
76
77 skip:
78
79 for ( /* void */ ; p < last - 1; p++) {
80 if (p[0] == CR && p[1] == LF) {
81 return p + 2;
82 }
83 }
84
85 invalid:
86
87 ngx_log_error(NGX_LOG_ERR, c->log, 0,
88 "broken header: \"%*s\"", (size_t) (last - buf), buf);
89
90 return NULL;
91 }