Core: moved PROXY protocol fields out of ngx_connection_t.
Now a new structure ngx_proxy_protocol_t holds these fields. This allows
to add more PROXY protocol fields in the future without modifying the
connection structure.
Roman Arutyunyan
2 years ago
146 | 146 | socklen_t socklen; |
147 | 147 | ngx_str_t addr_text; |
148 | 148 | |
149 | ngx_str_t proxy_protocol_addr; | |
150 | in_port_t proxy_protocol_port; | |
149 | ngx_proxy_protocol_t *proxy_protocol; | |
151 | 150 | |
152 | 151 | #if (NGX_SSL || NGX_COMPAT) |
153 | 152 | ngx_ssl_connection_t *ssl; |
25 | 25 | typedef struct ngx_connection_s ngx_connection_t; |
26 | 26 | typedef struct ngx_thread_task_s ngx_thread_task_t; |
27 | 27 | typedef struct ngx_ssl_s ngx_ssl_t; |
28 | typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t; | |
28 | 29 | typedef struct ngx_ssl_connection_s ngx_ssl_connection_t; |
29 | 30 | typedef struct ngx_udp_connection_s ngx_udp_connection_t; |
30 | 31 |
46 | 46 | u_char * |
47 | 47 | ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) |
48 | 48 | { |
49 | size_t len; | |
50 | u_char ch, *p, *addr, *port; | |
51 | ngx_int_t n; | |
49 | size_t len; | |
50 | u_char ch, *p, *addr, *port; | |
51 | ngx_int_t n; | |
52 | ngx_proxy_protocol_t *pp; | |
52 | 53 | |
53 | 54 | static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n"; |
54 | 55 | |
104 | 105 | } |
105 | 106 | } |
106 | 107 | |
108 | pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); | |
109 | if (pp == NULL) { | |
110 | return NULL; | |
111 | } | |
112 | ||
107 | 113 | len = p - addr - 1; |
108 | c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len); | |
109 | ||
110 | if (c->proxy_protocol_addr.data == NULL) { | |
111 | return NULL; | |
112 | } | |
113 | ||
114 | ngx_memcpy(c->proxy_protocol_addr.data, addr, len); | |
115 | c->proxy_protocol_addr.len = len; | |
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; | |
116 | 122 | |
117 | 123 | for ( ;; ) { |
118 | 124 | if (p == last) { |
144 | 150 | goto invalid; |
145 | 151 | } |
146 | 152 | |
147 | c->proxy_protocol_port = (in_port_t) n; | |
153 | pp->src_port = (in_port_t) n; | |
148 | 154 | |
149 | 155 | ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, |
150 | "PROXY protocol address: %V %d", &c->proxy_protocol_addr, | |
151 | c->proxy_protocol_port); | |
156 | "PROXY protocol address: %V %d", &pp->src_addr, | |
157 | pp->src_port); | |
158 | ||
159 | c->proxy_protocol = pp; | |
152 | 160 | |
153 | 161 | skip: |
154 | 162 | |
219 | 227 | socklen_t socklen; |
220 | 228 | ngx_uint_t version, command, family, transport; |
221 | 229 | ngx_sockaddr_t sockaddr; |
230 | ngx_proxy_protocol_t *pp; | |
222 | 231 | ngx_proxy_protocol_header_t *header; |
223 | 232 | ngx_proxy_protocol_inet_addrs_t *in; |
224 | 233 | #if (NGX_HAVE_INET6) |
265 | 274 | return end; |
266 | 275 | } |
267 | 276 | |
277 | pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); | |
278 | if (pp == NULL) { | |
279 | return NULL; | |
280 | } | |
281 | ||
268 | 282 | family = header->family_transport >> 4; |
269 | 283 | |
270 | 284 | switch (family) { |
281 | 295 | sockaddr.sockaddr_in.sin_port = 0; |
282 | 296 | memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4); |
283 | 297 | |
284 | c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in->src_port); | |
298 | pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port); | |
285 | 299 | |
286 | 300 | socklen = sizeof(struct sockaddr_in); |
287 | 301 | |
303 | 317 | sockaddr.sockaddr_in6.sin6_port = 0; |
304 | 318 | memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16); |
305 | 319 | |
306 | c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in6->src_port); | |
320 | pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port); | |
307 | 321 | |
308 | 322 | socklen = sizeof(struct sockaddr_in6); |
309 | 323 | |
320 | 334 | return end; |
321 | 335 | } |
322 | 336 | |
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); | |
337 | pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); | |
338 | if (pp->src_addr.data == NULL) { | |
339 | return NULL; | |
340 | } | |
341 | ||
342 | pp->src_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, | |
343 | pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0); | |
331 | 344 | |
332 | 345 | ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, |
333 | "PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr, | |
334 | c->proxy_protocol_port); | |
346 | "PROXY protocol v2 address: %V %d", &pp->src_addr, | |
347 | pp->src_port); | |
335 | 348 | |
336 | 349 | if (buf < end) { |
337 | 350 | ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, |
338 | 351 | "PROXY protocol v2 %z bytes of tlv ignored", end - buf); |
339 | 352 | } |
340 | 353 | |
354 | c->proxy_protocol = pp; | |
355 | ||
341 | 356 | return end; |
342 | 357 | } |
15 | 15 | #define NGX_PROXY_PROTOCOL_MAX_HEADER 107 |
16 | 16 | |
17 | 17 | |
18 | struct ngx_proxy_protocol_s { | |
19 | ngx_str_t src_addr; | |
20 | in_port_t src_port; | |
21 | }; | |
22 | ||
23 | ||
18 | 24 | u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, |
19 | 25 | u_char *last); |
20 | 26 | u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, |
179 | 179 | |
180 | 180 | case NGX_HTTP_REALIP_PROXY: |
181 | 181 | |
182 | value = &r->connection->proxy_protocol_addr; | |
183 | ||
184 | if (value->len == 0) { | |
182 | if (r->connection->proxy_protocol == NULL) { | |
185 | 183 | return NGX_DECLINED; |
186 | 184 | } |
187 | 185 | |
186 | value = &r->connection->proxy_protocol->src_addr; | |
188 | 187 | xfwd = NULL; |
189 | 188 | |
190 | 189 | break; |
237 | 236 | != NGX_DECLINED) |
238 | 237 | { |
239 | 238 | if (rlcf->type == NGX_HTTP_REALIP_PROXY) { |
240 | ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); | |
239 | ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); | |
241 | 240 | } |
242 | 241 | |
243 | 242 | return ngx_http_realip_set_addr(r, &addr); |
1292 | 1292 | ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, |
1293 | 1293 | ngx_http_variable_value_t *v, uintptr_t data) |
1294 | 1294 | { |
1295 | v->len = r->connection->proxy_protocol_addr.len; | |
1296 | v->valid = 1; | |
1297 | v->no_cacheable = 0; | |
1298 | v->not_found = 0; | |
1299 | v->data = r->connection->proxy_protocol_addr.data; | |
1295 | ngx_proxy_protocol_t *pp; | |
1296 | ||
1297 | pp = r->connection->proxy_protocol; | |
1298 | if (pp == NULL) { | |
1299 | v->not_found = 1; | |
1300 | return NGX_OK; | |
1301 | } | |
1302 | ||
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; | |
1300 | 1308 | |
1301 | 1309 | return NGX_OK; |
1302 | 1310 | } |
1306 | 1314 | ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, |
1307 | 1315 | ngx_http_variable_value_t *v, uintptr_t data) |
1308 | 1316 | { |
1309 | ngx_uint_t port; | |
1317 | ngx_uint_t port; | |
1318 | ngx_proxy_protocol_t *pp; | |
1319 | ||
1320 | pp = r->connection->proxy_protocol; | |
1321 | if (pp == NULL) { | |
1322 | v->not_found = 1; | |
1323 | return NGX_OK; | |
1324 | } | |
1310 | 1325 | |
1311 | 1326 | v->len = 0; |
1312 | 1327 | v->valid = 1; |
1318 | 1333 | return NGX_ERROR; |
1319 | 1334 | } |
1320 | 1335 | |
1321 | port = r->connection->proxy_protocol_port; | |
1336 | port = pp->src_port; | |
1322 | 1337 | |
1323 | 1338 | if (port > 0 && port < 65536) { |
1324 | 1339 | v->len = ngx_sprintf(v->data, "%ui", port) - v->data; |
107 | 107 | |
108 | 108 | c = s->connection; |
109 | 109 | |
110 | if (c->proxy_protocol_addr.len == 0) { | |
110 | if (c->proxy_protocol == NULL) { | |
111 | 111 | return NGX_DECLINED; |
112 | 112 | } |
113 | 113 | |
115 | 115 | return NGX_DECLINED; |
116 | 116 | } |
117 | 117 | |
118 | if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data, | |
119 | c->proxy_protocol_addr.len) | |
118 | if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data, | |
119 | c->proxy_protocol->src_addr.len) | |
120 | 120 | != NGX_OK) |
121 | 121 | { |
122 | 122 | return NGX_DECLINED; |
123 | 123 | } |
124 | 124 | |
125 | ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); | |
125 | ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); | |
126 | 126 | |
127 | 127 | return ngx_stream_realip_set_addr(s, &addr); |
128 | 128 | } |
556 | 556 | ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s, |
557 | 557 | ngx_stream_variable_value_t *v, uintptr_t data) |
558 | 558 | { |
559 | v->len = s->connection->proxy_protocol_addr.len; | |
560 | v->valid = 1; | |
561 | v->no_cacheable = 0; | |
562 | v->not_found = 0; | |
563 | v->data = s->connection->proxy_protocol_addr.data; | |
559 | ngx_proxy_protocol_t *pp; | |
560 | ||
561 | pp = s->connection->proxy_protocol; | |
562 | if (pp == NULL) { | |
563 | v->not_found = 1; | |
564 | return NGX_OK; | |
565 | } | |
566 | ||
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; | |
564 | 572 | |
565 | 573 | return NGX_OK; |
566 | 574 | } |
570 | 578 | ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s, |
571 | 579 | ngx_stream_variable_value_t *v, uintptr_t data) |
572 | 580 | { |
573 | ngx_uint_t port; | |
581 | ngx_uint_t port; | |
582 | ngx_proxy_protocol_t *pp; | |
583 | ||
584 | pp = s->connection->proxy_protocol; | |
585 | if (pp == NULL) { | |
586 | v->not_found = 1; | |
587 | return NGX_OK; | |
588 | } | |
574 | 589 | |
575 | 590 | v->len = 0; |
576 | 591 | v->valid = 1; |
582 | 597 | return NGX_ERROR; |
583 | 598 | } |
584 | 599 | |
585 | port = s->connection->proxy_protocol_port; | |
600 | port = pp->src_port; | |
586 | 601 | |
587 | 602 | if (port > 0 && port < 65536) { |
588 | 603 | v->len = ngx_sprintf(v->data, "%ui", port) - v->data; |