Core: preserve received PROXY protocol tuple

When a connection was accepted with PROXY protocol, pass its parsed source and destination addresses and ports to the next proxy hop.  This keeps the original end-to-end tuple instead of rebuilding it from the listener sockets after realip processing.
This commit is contained in:
Video Wheel Control 2026-07-31 05:51:16 +09:00
parent 20dd49b743
commit 314f463407
2 changed files with 41 additions and 1 deletions

View file

@ -101,6 +101,7 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{
size_t len;
u_char *p;
ngx_uint_t family;
ngx_proxy_protocol_t *pp;
static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
@ -134,6 +135,9 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
goto invalid;
}
family = (p[3] == '4') ? NGX_PROXY_PROTOCOL_AF_INET
: NGX_PROXY_PROTOCOL_AF_INET6;
p += 5;
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
@ -141,6 +145,8 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
return NULL;
}
pp->family = family;
p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
if (p == NULL) {
goto invalid;
@ -279,7 +285,8 @@ ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
u_char *
ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
{
ngx_uint_t port, lport;
ngx_uint_t port, lport;
ngx_proxy_protocol_t *pp;
if (last - buf < NGX_PROXY_PROTOCOL_V1_MAX_HEADER) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
@ -287,6 +294,36 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
return NULL;
}
pp = c->proxy_protocol;
if (pp) {
switch (pp->family) {
case NGX_PROXY_PROTOCOL_AF_INET:
buf = ngx_cpymem(buf, "PROXY TCP4 ",
sizeof("PROXY TCP4 ") - 1);
break;
case NGX_PROXY_PROTOCOL_AF_INET6:
buf = ngx_cpymem(buf, "PROXY TCP6 ",
sizeof("PROXY TCP6 ") - 1);
break;
default:
return ngx_cpymem(buf, "PROXY UNKNOWN" CRLF,
sizeof("PROXY UNKNOWN" CRLF) - 1);
}
buf = ngx_cpymem(buf, pp->src_addr.data, pp->src_addr.len);
*buf++ = ' ';
buf = ngx_cpymem(buf, pp->dst_addr.data, pp->dst_addr.len);
return ngx_slprintf(buf, last, " %ui %ui" CRLF, pp->src_port,
pp->dst_port);
}
if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
return NULL;
}
@ -409,6 +446,7 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
pp->family = family;
socklen = sizeof(struct sockaddr_in);
@ -436,6 +474,7 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
pp->family = family;
socklen = sizeof(struct sockaddr_in6);

View file

@ -22,6 +22,7 @@ struct ngx_proxy_protocol_s {
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
ngx_uint_t family;
ngx_str_t tlvs;
};