39 | 39 |
} ngx_proxy_protocol_inet6_addrs_t;
|
40 | 40 |
|
41 | 41 |
|
|
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);
|
42 | 46 |
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
|
43 | 47 |
u_char *last);
|
44 | 48 |
|
|
47 | 51 |
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
48 | 52 |
{
|
49 | 53 |
size_t len;
|
50 | |
u_char ch, *p, *addr, *port;
|
51 | |
ngx_int_t n;
|
|
54 |
u_char *p;
|
52 | 55 |
ngx_proxy_protocol_t *pp;
|
53 | 56 |
|
54 | 57 |
static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
|
|
83 | 86 |
}
|
84 | 87 |
|
85 | 88 |
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;
|
87 | 156 |
|
88 | 157 |
for ( ;; ) {
|
89 | 158 |
if (p == last) {
|
90 | |
goto invalid;
|
|
159 |
return NULL;
|
91 | 160 |
}
|
92 | 161 |
|
93 | 162 |
ch = *p++;
|
|
101 | 170 |
&& (ch < 'A' || ch > 'F')
|
102 | 171 |
&& (ch < '0' || ch > '9'))
|
103 | 172 |
{
|
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;
|
122 | 200 |
|
123 | 201 |
for ( ;; ) {
|
124 | 202 |
if (p == last) {
|
125 | |
goto invalid;
|
126 | |
}
|
127 | |
|
128 | |
if (*p++ == ' ') {
|
|
203 |
return NULL;
|
|
204 |
}
|
|
205 |
|
|
206 |
if (*p++ == sep) {
|
129 | 207 |
break;
|
130 | 208 |
}
|
131 | 209 |
}
|
132 | 210 |
|
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);
|
149 | 214 |
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;
|
175 | 221 |
}
|
176 | 222 |
|
177 | 223 |
|
|
226 | 272 |
size_t len;
|
227 | 273 |
socklen_t socklen;
|
228 | 274 |
ngx_uint_t version, command, family, transport;
|
229 | |
ngx_sockaddr_t sockaddr;
|
|
275 |
ngx_sockaddr_t src_sockaddr, dst_sockaddr;
|
230 | 276 |
ngx_proxy_protocol_t *pp;
|
231 | 277 |
ngx_proxy_protocol_header_t *header;
|
232 | 278 |
ngx_proxy_protocol_inet_addrs_t *in;
|
|
291 | 337 |
|
292 | 338 |
in = (ngx_proxy_protocol_inet_addrs_t *) buf;
|
293 | 339 |
|
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);
|
297 | 347 |
|
298 | 348 |
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
|
|
349 |
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
|
299 | 350 |
|
300 | 351 |
socklen = sizeof(struct sockaddr_in);
|
301 | 352 |
|
|
313 | 364 |
|
314 | 365 |
in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
|
315 | 366 |
|
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);
|
319 | 374 |
|
320 | 375 |
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
|
|
376 |
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
|
321 | 377 |
|
322 | 378 |
socklen = sizeof(struct sockaddr_in6);
|
323 | 379 |
|
|
339 | 395 |
return NULL;
|
340 | 396 |
}
|
341 | 397 |
|
342 | |
pp->src_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
|
|
398 |
pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
|
343 | 399 |
pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);
|
344 | 400 |
|
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);
|
348 | 412 |
|
349 | 413 |
if (buf < end) {
|
350 | 414 |
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|