From 2c7812a4f4d5d8a64bcde68700eadc15dd5ee82e Mon Sep 17 00:00:00 2001 From: Vadim Zhestikov Date: Wed, 20 May 2026 14:04:10 -0700 Subject: [PATCH] Core: add AF_UNIX address support to PROXY protocol v2 write. Add ngx_proxy_protocol_unix_addrs_t with two 108-byte path fields and an AF_UNIX case in ngx_proxy_protocol_v2_write_header(), using the family-promotion framework: when either src or dst is AF_UNIX, af is set to NGX_PROXY_PROTOCOL_AF_UNIX and both paths are extracted by ngx_proxy_protocol_v2_write_unix(). Mixed IPv4/IPv6 with Unix- domain connections emit IPv4/IPv6 headers with 127.0.0.1 or ::1 as the Unix-side substitute address via write_ipv4()/write_ipv6(). Update NGX_PROXY_PROTOCOL_V2_MAX_HEADER from 52 to 232 to cover the largest possible v2 address block (16-byte fixed header plus 216 bytes for Unix src and dst paths). --- src/core/ngx_proxy_protocol.c | 71 +++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c index 7972b1b02..d463914e9 100644 --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -12,7 +12,7 @@ #define NGX_PROXY_PROTOCOL_V2_SIGNATURE "\r\n\r\n\0\r\nQUIT\n" #define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107 -#define NGX_PROXY_PROTOCOL_V2_MAX_HEADER 52 +#define NGX_PROXY_PROTOCOL_V2_MAX_HEADER 232 #define NGX_PROXY_PROTOCOL_AF_UNSPEC 0 #define NGX_PROXY_PROTOCOL_AF_INET 1 @@ -75,6 +75,16 @@ typedef struct { } ngx_proxy_protocol_inet6_addrs_t; +#if (NGX_HAVE_UNIX_DOMAIN) + +typedef struct { + u_char src_addr[108]; + u_char dst_addr[108]; +} ngx_proxy_protocol_unix_addrs_t; + +#endif + + typedef struct { u_char type; u_char len[2]; @@ -383,7 +393,7 @@ ngx_proxy_protocol_v2_write_ipv4(struct sockaddr *sa, u_char *addr, ngx_memcpy(port, &sin->sin_port, 2); } else { - /* unknown: substitute 127.0.0.1 port 0 */ + /* AF_UNIX or unknown: substitute 127.0.0.1 port 0 */ ngx_memcpy(addr, loopback, 4); port[0] = 0; port[1] = 0; @@ -422,7 +432,7 @@ ngx_proxy_protocol_v2_write_ipv6(struct sockaddr *sa, u_char *addr, break; default: - /* unknown: substitute ::1 port 0 */ + /* AF_UNIX or unknown: substitute ::1 port 0 */ ngx_memzero(addr, 16); addr[15] = 1; port[0] = 0; @@ -434,6 +444,31 @@ ngx_proxy_protocol_v2_write_ipv6(struct sockaddr *sa, u_char *addr, #endif +#if (NGX_HAVE_UNIX_DOMAIN) + +static void +ngx_proxy_protocol_v2_write_unix(struct sockaddr *sa, socklen_t socklen, + u_char *addr) +{ + struct sockaddr_un *saun; + + if (sa->sa_family != AF_UNIX) { + *addr = '\0'; + return; + } + + saun = (struct sockaddr_un *) sa; + + if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) { + *addr = '\0'; + } else { + ngx_cpystrn(addr, (u_char *) saun->sun_path, 108); + } +} + +#endif + + static u_char * ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *last) { @@ -447,6 +482,9 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las struct in6_addr *src6, *dst6; ngx_proxy_protocol_inet6_addrs_t *in6; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + ngx_proxy_protocol_unix_addrs_t *un; +#endif if (last - buf < NGX_PROXY_PROTOCOL_V2_MAX_HEADER) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, @@ -491,6 +529,12 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las #endif if (src_fam == AF_INET || dst_fam == AF_INET) { af = NGX_PROXY_PROTOCOL_AF_INET; + +#if (NGX_HAVE_UNIX_DOMAIN) + } else if (src_fam == AF_UNIX || dst_fam == AF_UNIX) { + af = NGX_PROXY_PROTOCOL_AF_UNIX; +#endif + } else { af = NGX_PROXY_PROTOCOL_AF_UNSPEC; } @@ -562,6 +606,27 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las p += sizeof(ngx_proxy_protocol_inet6_addrs_t); break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + + case NGX_PROXY_PROTOCOL_AF_UNIX: + + header->len[0] = 0; + header->len[1] = sizeof(ngx_proxy_protocol_unix_addrs_t); + + un = (ngx_proxy_protocol_unix_addrs_t *) p; + + ngx_memzero(un, sizeof(ngx_proxy_protocol_unix_addrs_t)); + + ngx_proxy_protocol_v2_write_unix(c->sockaddr, c->socklen, + un->src_addr); + ngx_proxy_protocol_v2_write_unix(c->local_sockaddr, c->local_socklen, + un->dst_addr); + + p += sizeof(ngx_proxy_protocol_unix_addrs_t); + break; + #endif default: /* NGX_PROXY_PROTOCOL_AF_UNSPEC */