Klaus Demo nginx / 2038985
Parsing server PROXY protocol address and port (ticket #1206). New variables $proxy_protocol_server_addr and $proxy_protocol_server_port are added both to HTTP and Stream. Roman Arutyunyan 23 days ago
4 changed file(s) with 186 addition(s) and 94 deletion(s). Raw diff Collapse all Expand all
3939 } ngx_proxy_protocol_inet6_addrs_t;
4040
4141
42 static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
43 u_char *last, ngx_str_t *addr);
44 static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
45 in_port_t *port, u_char sep);
4246 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
4347 u_char *last);
4448
4751 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
4852 {
4953 size_t len;
50 u_char ch, *p, *addr, *port;
51 ngx_int_t n;
54 u_char *p;
5255 ngx_proxy_protocol_t *pp;
5356
5457 static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
8386 }
8487
8588 p += 5;
86 addr = p;
89
90 pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
91 if (pp == NULL) {
92 return NULL;
93 }
94
95 p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
96 if (p == NULL) {
97 goto invalid;
98 }
99
100 p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
101 if (p == NULL) {
102 goto invalid;
103 }
104
105 p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
106 if (p == NULL) {
107 goto invalid;
108 }
109
110 p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
111 if (p == NULL) {
112 goto invalid;
113 }
114
115 if (p == last) {
116 goto invalid;
117 }
118
119 if (*p++ != LF) {
120 goto invalid;
121 }
122
123 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
124 "PROXY protocol src: %V %d, dst: %V %d",
125 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
126
127 c->proxy_protocol = pp;
128
129 return p;
130
131 skip:
132
133 for ( /* void */ ; p < last - 1; p++) {
134 if (p[0] == CR && p[1] == LF) {
135 return p + 2;
136 }
137 }
138
139 invalid:
140
141 ngx_log_error(NGX_LOG_ERR, c->log, 0,
142 "broken header: \"%*s\"", (size_t) (last - buf), buf);
143
144 return NULL;
145 }
146
147
148 static u_char *
149 ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last,
150 ngx_str_t *addr)
151 {
152 size_t len;
153 u_char ch, *pos;
154
155 pos = p;
87156
88157 for ( ;; ) {
89158 if (p == last) {
90 goto invalid;
159 return NULL;
91160 }
92161
93162 ch = *p++;
101170 && (ch < 'A' || ch > 'F')
102171 && (ch < '0' || ch > '9'))
103172 {
104 goto invalid;
105 }
106 }
107
108 pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
109 if (pp == NULL) {
110 return NULL;
111 }
112
113 len = p - addr - 1;
114
115 pp->src_addr.data = ngx_pnalloc(c->pool, len);
116 if (pp->src_addr.data == NULL) {
117 return NULL;
118 }
119
120 ngx_memcpy(pp->src_addr.data, addr, len);
121 pp->src_addr.len = len;
173 return NULL;
174 }
175 }
176
177 len = p - pos - 1;
178
179 addr->data = ngx_pnalloc(c->pool, len);
180 if (addr->data == NULL) {
181 return NULL;
182 }
183
184 ngx_memcpy(addr->data, pos, len);
185 addr->len = len;
186
187 return p;
188 }
189
190
191 static u_char *
192 ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
193 u_char sep)
194 {
195 size_t len;
196 u_char *pos;
197 ngx_int_t n;
198
199 pos = p;
122200
123201 for ( ;; ) {
124202 if (p == last) {
125 goto invalid;
126 }
127
128 if (*p++ == ' ') {
203 return NULL;
204 }
205
206 if (*p++ == sep) {
129207 break;
130208 }
131209 }
132210
133 port = p;
134
135 for ( ;; ) {
136 if (p == last) {
137 goto invalid;
138 }
139
140 if (*p++ == ' ') {
141 break;
142 }
143 }
144
145 len = p - port - 1;
146
147 n = ngx_atoi(port, len);
148
211 len = p - pos - 1;
212
213 n = ngx_atoi(pos, len);
149214 if (n < 0 || n > 65535) {
150 goto invalid;
151 }
152
153 pp->src_port = (in_port_t) n;
154
155 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
156 "PROXY protocol address: %V %d", &pp->src_addr,
157 pp->src_port);
158
159 c->proxy_protocol = pp;
160
161 skip:
162
163 for ( /* void */ ; p < last - 1; p++) {
164 if (p[0] == CR && p[1] == LF) {
165 return p + 2;
166 }
167 }
168
169 invalid:
170
171 ngx_log_error(NGX_LOG_ERR, c->log, 0,
172 "broken header: \"%*s\"", (size_t) (last - buf), buf);
173
174 return NULL;
215 return NULL;
216 }
217
218 *port = (in_port_t) n;
219
220 return p;
175221 }
176222
177223
226272 size_t len;
227273 socklen_t socklen;
228274 ngx_uint_t version, command, family, transport;
229 ngx_sockaddr_t sockaddr;
275 ngx_sockaddr_t src_sockaddr, dst_sockaddr;
230276 ngx_proxy_protocol_t *pp;
231277 ngx_proxy_protocol_header_t *header;
232278 ngx_proxy_protocol_inet_addrs_t *in;
291337
292338 in = (ngx_proxy_protocol_inet_addrs_t *) buf;
293339
294 sockaddr.sockaddr_in.sin_family = AF_INET;
295 sockaddr.sockaddr_in.sin_port = 0;
296 memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
340 src_sockaddr.sockaddr_in.sin_family = AF_INET;
341 src_sockaddr.sockaddr_in.sin_port = 0;
342 memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
343
344 dst_sockaddr.sockaddr_in.sin_family = AF_INET;
345 dst_sockaddr.sockaddr_in.sin_port = 0;
346 memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
297347
298348 pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
349 pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
299350
300351 socklen = sizeof(struct sockaddr_in);
301352
313364
314365 in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
315366
316 sockaddr.sockaddr_in6.sin6_family = AF_INET6;
317 sockaddr.sockaddr_in6.sin6_port = 0;
318 memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
367 src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
368 src_sockaddr.sockaddr_in6.sin6_port = 0;
369 memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
370
371 dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
372 dst_sockaddr.sockaddr_in6.sin6_port = 0;
373 memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
319374
320375 pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
376 pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
321377
322378 socklen = sizeof(struct sockaddr_in6);
323379
339395 return NULL;
340396 }
341397
342 pp->src_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
398 pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
343399 pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);
344400
345 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
346 "PROXY protocol v2 address: %V %d", &pp->src_addr,
347 pp->src_port);
401 pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
402 if (pp->dst_addr.data == NULL) {
403 return NULL;
404 }
405
406 pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen,
407 pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 0);
408
409 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
410 "PROXY protocol v2 src: %V %d, dst: %V %d",
411 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
348412
349413 if (buf < end) {
350414 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
1717
1818 struct ngx_proxy_protocol_s {
1919 ngx_str_t src_addr;
20 ngx_str_t dst_addr;
2021 in_port_t src_port;
22 in_port_t dst_port;
2123 };
2224
2325
198198 { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
199199
200200 { ngx_string("proxy_protocol_addr"), NULL,
201 ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
201 ngx_http_variable_proxy_protocol_addr,
202 offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },
202203
203204 { ngx_string("proxy_protocol_port"), NULL,
204 ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
205 ngx_http_variable_proxy_protocol_port,
206 offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },
207
208 { ngx_string("proxy_protocol_server_addr"), NULL,
209 ngx_http_variable_proxy_protocol_addr,
210 offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },
211
212 { ngx_string("proxy_protocol_server_port"), NULL,
213 ngx_http_variable_proxy_protocol_port,
214 offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
205215
206216 { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
207217
12921302 ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
12931303 ngx_http_variable_value_t *v, uintptr_t data)
12941304 {
1305 ngx_str_t *addr;
12951306 ngx_proxy_protocol_t *pp;
12961307
12971308 pp = r->connection->proxy_protocol;
13001311 return NGX_OK;
13011312 }
13021313
1303 v->len = pp->src_addr.len;
1304 v->valid = 1;
1305 v->no_cacheable = 0;
1306 v->not_found = 0;
1307 v->data = pp->src_addr.data;
1314 addr = (ngx_str_t *) ((char *) pp + data);
1315
1316 v->len = addr->len;
1317 v->valid = 1;
1318 v->no_cacheable = 0;
1319 v->not_found = 0;
1320 v->data = addr->data;
13081321
13091322 return NGX_OK;
13101323 }
13331346 return NGX_ERROR;
13341347 }
13351348
1336 port = pp->src_port;
1349 port = *(in_port_t *) ((char *) pp + data);
13371350
13381351 if (port > 0 && port < 65536) {
13391352 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
6363 ngx_stream_variable_remote_port, 0, 0, 0 },
6464
6565 { ngx_string("proxy_protocol_addr"), NULL,
66 ngx_stream_variable_proxy_protocol_addr, 0, 0, 0 },
66 ngx_stream_variable_proxy_protocol_addr,
67 offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },
6768
6869 { ngx_string("proxy_protocol_port"), NULL,
69 ngx_stream_variable_proxy_protocol_port, 0, 0, 0 },
70 ngx_stream_variable_proxy_protocol_port,
71 offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },
72
73 { ngx_string("proxy_protocol_server_addr"), NULL,
74 ngx_stream_variable_proxy_protocol_addr,
75 offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },
76
77 { ngx_string("proxy_protocol_server_port"), NULL,
78 ngx_stream_variable_proxy_protocol_port,
79 offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
7080
7181 { ngx_string("server_addr"), NULL,
7282 ngx_stream_variable_server_addr, 0, 0, 0 },
556566 ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s,
557567 ngx_stream_variable_value_t *v, uintptr_t data)
558568 {
569 ngx_str_t *addr;
559570 ngx_proxy_protocol_t *pp;
560571
561572 pp = s->connection->proxy_protocol;
564575 return NGX_OK;
565576 }
566577
567 v->len = pp->src_addr.len;
568 v->valid = 1;
569 v->no_cacheable = 0;
570 v->not_found = 0;
571 v->data = pp->src_addr.data;
578 addr = (ngx_str_t *) ((char *) pp + data);
579
580 v->len = addr->len;
581 v->valid = 1;
582 v->no_cacheable = 0;
583 v->not_found = 0;
584 v->data = addr->data;
572585
573586 return NGX_OK;
574587 }
597610 return NGX_ERROR;
598611 }
599612
600 port = pp->src_port;
613 port = *(in_port_t *) ((char *) pp + data);
601614
602615 if (port > 0 && port < 65536) {
603616 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;