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 }