Mercurial > hg > nginx-quic
comparison src/core/ngx_proxy_protocol.c @ 7591:89adf49fe76a
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 21 Oct 2019 20:22:30 +0300 |
parents | 06b01840bd42 |
children | 017fd847f4f7 |
comparison
equal
deleted
inserted
replaced
7590:06b01840bd42 | 7591:89adf49fe76a |
---|---|
38 u_char src_port[2]; | 38 u_char src_port[2]; |
39 u_char dst_port[2]; | 39 u_char dst_port[2]; |
40 } ngx_proxy_protocol_inet6_addrs_t; | 40 } ngx_proxy_protocol_inet6_addrs_t; |
41 | 41 |
42 | 42 |
43 static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, | |
44 u_char *last, ngx_str_t *addr); | |
45 static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last, | |
46 in_port_t *port, u_char sep); | |
43 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, | 47 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, |
44 u_char *last); | 48 u_char *last); |
45 | 49 |
46 | 50 |
47 u_char * | 51 u_char * |
48 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) | 52 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) |
49 { | 53 { |
50 size_t len; | 54 size_t len; |
51 u_char ch, *p, *addr, *port; | 55 u_char *p; |
52 ngx_int_t n; | |
53 ngx_proxy_protocol_t *pp; | 56 ngx_proxy_protocol_t *pp; |
54 | 57 |
55 static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n"; | 58 static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n"; |
56 | 59 |
57 p = buf; | 60 p = buf; |
82 { | 85 { |
83 goto invalid; | 86 goto invalid; |
84 } | 87 } |
85 | 88 |
86 p += 5; | 89 p += 5; |
87 addr = p; | 90 |
91 pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); | |
92 if (pp == NULL) { | |
93 return NULL; | |
94 } | |
95 | |
96 p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr); | |
97 if (p == NULL) { | |
98 goto invalid; | |
99 } | |
100 | |
101 p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr); | |
102 if (p == NULL) { | |
103 goto invalid; | |
104 } | |
105 | |
106 p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' '); | |
107 if (p == NULL) { | |
108 goto invalid; | |
109 } | |
110 | |
111 p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR); | |
112 if (p == NULL) { | |
113 goto invalid; | |
114 } | |
115 | |
116 if (p == last) { | |
117 goto invalid; | |
118 } | |
119 | |
120 if (*p++ != LF) { | |
121 goto invalid; | |
122 } | |
123 | |
124 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0, | |
125 "PROXY protocol src: %V %d, dst: %V %d", | |
126 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port); | |
127 | |
128 c->proxy_protocol = pp; | |
129 | |
130 return p; | |
131 | |
132 skip: | |
133 | |
134 for ( /* void */ ; p < last - 1; p++) { | |
135 if (p[0] == CR && p[1] == LF) { | |
136 return p + 2; | |
137 } | |
138 } | |
139 | |
140 invalid: | |
141 | |
142 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
143 "broken header: \"%*s\"", (size_t) (last - buf), buf); | |
144 | |
145 return NULL; | |
146 } | |
147 | |
148 | |
149 static u_char * | |
150 ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last, | |
151 ngx_str_t *addr) | |
152 { | |
153 size_t len; | |
154 u_char ch, *pos; | |
155 | |
156 pos = p; | |
88 | 157 |
89 for ( ;; ) { | 158 for ( ;; ) { |
90 if (p == last) { | 159 if (p == last) { |
91 goto invalid; | 160 return NULL; |
92 } | 161 } |
93 | 162 |
94 ch = *p++; | 163 ch = *p++; |
95 | 164 |
96 if (ch == ' ') { | 165 if (ch == ' ') { |
100 if (ch != ':' && ch != '.' | 169 if (ch != ':' && ch != '.' |
101 && (ch < 'a' || ch > 'f') | 170 && (ch < 'a' || ch > 'f') |
102 && (ch < 'A' || ch > 'F') | 171 && (ch < 'A' || ch > 'F') |
103 && (ch < '0' || ch > '9')) | 172 && (ch < '0' || ch > '9')) |
104 { | 173 { |
105 goto invalid; | 174 return NULL; |
106 } | 175 } |
107 } | 176 } |
108 | 177 |
109 pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); | 178 len = p - pos - 1; |
110 if (pp == NULL) { | 179 |
111 return NULL; | 180 addr->data = ngx_pnalloc(c->pool, len); |
112 } | 181 if (addr->data == NULL) { |
113 | 182 return NULL; |
114 len = p - addr - 1; | 183 } |
115 | 184 |
116 pp->src_addr.data = ngx_pnalloc(c->pool, len); | 185 ngx_memcpy(addr->data, pos, len); |
117 if (pp->src_addr.data == NULL) { | 186 addr->len = len; |
118 return NULL; | 187 |
119 } | 188 return p; |
120 | 189 } |
121 ngx_memcpy(pp->src_addr.data, addr, len); | 190 |
122 pp->src_addr.len = len; | 191 |
192 static u_char * | |
193 ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port, | |
194 u_char sep) | |
195 { | |
196 size_t len; | |
197 u_char *pos; | |
198 ngx_int_t n; | |
199 | |
200 pos = p; | |
123 | 201 |
124 for ( ;; ) { | 202 for ( ;; ) { |
125 if (p == last) { | 203 if (p == last) { |
126 goto invalid; | 204 return NULL; |
127 } | 205 } |
128 | 206 |
129 if (*p++ == ' ') { | 207 if (*p++ == sep) { |
130 break; | 208 break; |
131 } | 209 } |
132 } | 210 } |
133 | 211 |
134 port = p; | 212 len = p - pos - 1; |
135 | 213 |
136 for ( ;; ) { | 214 n = ngx_atoi(pos, len); |
137 if (p == last) { | |
138 goto invalid; | |
139 } | |
140 | |
141 if (*p++ == ' ') { | |
142 break; | |
143 } | |
144 } | |
145 | |
146 len = p - port - 1; | |
147 | |
148 n = ngx_atoi(port, len); | |
149 | |
150 if (n < 0 || n > 65535) { | 215 if (n < 0 || n > 65535) { |
151 goto invalid; | 216 return NULL; |
152 } | 217 } |
153 | 218 |
154 pp->src_port = (in_port_t) n; | 219 *port = (in_port_t) n; |
155 | 220 |
156 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, | 221 return p; |
157 "PROXY protocol address: %V %d", &pp->src_addr, | |
158 pp->src_port); | |
159 | |
160 c->proxy_protocol = pp; | |
161 | |
162 skip: | |
163 | |
164 for ( /* void */ ; p < last - 1; p++) { | |
165 if (p[0] == CR && p[1] == LF) { | |
166 return p + 2; | |
167 } | |
168 } | |
169 | |
170 invalid: | |
171 | |
172 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
173 "broken header: \"%*s\"", (size_t) (last - buf), buf); | |
174 | |
175 return NULL; | |
176 } | 222 } |
177 | 223 |
178 | 224 |
179 u_char * | 225 u_char * |
180 ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) | 226 ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) |
225 { | 271 { |
226 u_char *end; | 272 u_char *end; |
227 size_t len; | 273 size_t len; |
228 socklen_t socklen; | 274 socklen_t socklen; |
229 ngx_uint_t version, command, family, transport; | 275 ngx_uint_t version, command, family, transport; |
230 ngx_sockaddr_t sockaddr; | 276 ngx_sockaddr_t src_sockaddr, dst_sockaddr; |
231 ngx_proxy_protocol_t *pp; | 277 ngx_proxy_protocol_t *pp; |
232 ngx_proxy_protocol_header_t *header; | 278 ngx_proxy_protocol_header_t *header; |
233 ngx_proxy_protocol_inet_addrs_t *in; | 279 ngx_proxy_protocol_inet_addrs_t *in; |
234 #if (NGX_HAVE_INET6) | 280 #if (NGX_HAVE_INET6) |
235 ngx_proxy_protocol_inet6_addrs_t *in6; | 281 ngx_proxy_protocol_inet6_addrs_t *in6; |
290 return NULL; | 336 return NULL; |
291 } | 337 } |
292 | 338 |
293 in = (ngx_proxy_protocol_inet_addrs_t *) buf; | 339 in = (ngx_proxy_protocol_inet_addrs_t *) buf; |
294 | 340 |
295 sockaddr.sockaddr_in.sin_family = AF_INET; | 341 src_sockaddr.sockaddr_in.sin_family = AF_INET; |
296 sockaddr.sockaddr_in.sin_port = 0; | 342 src_sockaddr.sockaddr_in.sin_port = 0; |
297 memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4); | 343 memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4); |
344 | |
345 dst_sockaddr.sockaddr_in.sin_family = AF_INET; | |
346 dst_sockaddr.sockaddr_in.sin_port = 0; | |
347 memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4); | |
298 | 348 |
299 pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port); | 349 pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port); |
350 pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port); | |
300 | 351 |
301 socklen = sizeof(struct sockaddr_in); | 352 socklen = sizeof(struct sockaddr_in); |
302 | 353 |
303 buf += sizeof(ngx_proxy_protocol_inet_addrs_t); | 354 buf += sizeof(ngx_proxy_protocol_inet_addrs_t); |
304 | 355 |
312 return NULL; | 363 return NULL; |
313 } | 364 } |
314 | 365 |
315 in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf; | 366 in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf; |
316 | 367 |
317 sockaddr.sockaddr_in6.sin6_family = AF_INET6; | 368 src_sockaddr.sockaddr_in6.sin6_family = AF_INET6; |
318 sockaddr.sockaddr_in6.sin6_port = 0; | 369 src_sockaddr.sockaddr_in6.sin6_port = 0; |
319 memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16); | 370 memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16); |
371 | |
372 dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6; | |
373 dst_sockaddr.sockaddr_in6.sin6_port = 0; | |
374 memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16); | |
320 | 375 |
321 pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port); | 376 pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port); |
377 pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port); | |
322 | 378 |
323 socklen = sizeof(struct sockaddr_in6); | 379 socklen = sizeof(struct sockaddr_in6); |
324 | 380 |
325 buf += sizeof(ngx_proxy_protocol_inet6_addrs_t); | 381 buf += sizeof(ngx_proxy_protocol_inet6_addrs_t); |
326 | 382 |
338 pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); | 394 pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); |
339 if (pp->src_addr.data == NULL) { | 395 if (pp->src_addr.data == NULL) { |
340 return NULL; | 396 return NULL; |
341 } | 397 } |
342 | 398 |
343 pp->src_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, | 399 pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen, |
344 pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0); | 400 pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0); |
345 | 401 |
346 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, | 402 pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); |
347 "PROXY protocol v2 address: %V %d", &pp->src_addr, | 403 if (pp->dst_addr.data == NULL) { |
348 pp->src_port); | 404 return NULL; |
405 } | |
406 | |
407 pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen, | |
408 pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 0); | |
409 | |
410 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0, | |
411 "PROXY protocol v2 src: %V %d, dst: %V %d", | |
412 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port); | |
349 | 413 |
350 if (buf < end) { | 414 if (buf < end) { |
351 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, | 415 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, |
352 "PROXY protocol v2 %z bytes of tlv ignored", end - buf); | 416 "PROXY protocol v2 %z bytes of tlv ignored", end - buf); |
353 } | 417 } |