Latest update - 7251
This commit is contained in:
@@ -9,6 +9,57 @@
|
|||||||
#include <ngx_core.h>
|
#include <ngx_core.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_PP_V2_SIGLEN 12
|
||||||
|
#define NGX_PP_V2_CMD_PROXY 1
|
||||||
|
#define NGX_PP_V2_STREAM 1
|
||||||
|
|
||||||
|
#define NGX_PP_V2_AF_UNSPEC 0
|
||||||
|
#define NGX_PP_V2_AF_INET 1
|
||||||
|
#define NGX_PP_V2_AF_INET6 2
|
||||||
|
|
||||||
|
|
||||||
|
#define ngx_pp_v2_get_u16(p) \
|
||||||
|
( ((uint16_t) ((u_char *) (p))[0] << 8) \
|
||||||
|
+ ( ((u_char *) (p))[1]) )
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char signature[NGX_PP_V2_SIGLEN];
|
||||||
|
u_char ver_cmd;
|
||||||
|
u_char fam_transp;
|
||||||
|
u_char len[2];
|
||||||
|
} ngx_pp_v2_header_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char src[4];
|
||||||
|
u_char dst[4];
|
||||||
|
u_char sport[2];
|
||||||
|
u_char dport[2];
|
||||||
|
} ngx_pp_v2_inet_addrs_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char src[16];
|
||||||
|
u_char dst[16];
|
||||||
|
u_char sport[2];
|
||||||
|
u_char dport[2];
|
||||||
|
} ngx_pp_v2_inet6_addrs_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
ngx_pp_v2_inet_addrs_t inet;
|
||||||
|
ngx_pp_v2_inet6_addrs_t inet6;
|
||||||
|
} ngx_pp_v2_addrs_t;
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
|
||||||
|
u_char *last);
|
||||||
|
|
||||||
|
static const u_char ngx_pp_v2_signature[NGX_PP_V2_SIGLEN] =
|
||||||
|
{ 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A };
|
||||||
|
|
||||||
|
|
||||||
u_char *
|
u_char *
|
||||||
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
||||||
{
|
{
|
||||||
@@ -19,6 +70,12 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
p = buf;
|
p = buf;
|
||||||
len = last - buf;
|
len = last - buf;
|
||||||
|
|
||||||
|
if (len >= sizeof(ngx_pp_v2_header_t)
|
||||||
|
&& memcmp(p, ngx_pp_v2_signature, NGX_PP_V2_SIGLEN) == 0)
|
||||||
|
{
|
||||||
|
return ngx_proxy_protocol_v2_read(c, buf, last);
|
||||||
|
}
|
||||||
|
|
||||||
if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
|
if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
@@ -166,3 +223,138 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
|
|
||||||
return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
|
return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *
|
||||||
|
ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
||||||
|
{
|
||||||
|
u_char *end;
|
||||||
|
size_t len;
|
||||||
|
socklen_t socklen;
|
||||||
|
ngx_str_t *name;
|
||||||
|
ngx_uint_t ver, cmd, family, transport;
|
||||||
|
ngx_sockaddr_t sockaddr;
|
||||||
|
ngx_pp_v2_addrs_t *addrs;
|
||||||
|
ngx_pp_v2_header_t *hdr;
|
||||||
|
|
||||||
|
hdr = (ngx_pp_v2_header_t *) buf;
|
||||||
|
|
||||||
|
buf += sizeof(ngx_pp_v2_header_t);
|
||||||
|
|
||||||
|
ver = hdr->ver_cmd >> 4;
|
||||||
|
|
||||||
|
if (ver != 2) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"unsupported PROXY protocol version: %ui", ver);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ngx_pp_v2_get_u16(hdr->len);
|
||||||
|
|
||||||
|
if ((size_t) (last - buf) < len) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "header is too large");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = buf + len;
|
||||||
|
|
||||||
|
cmd = hdr->ver_cmd & 0x0F;
|
||||||
|
|
||||||
|
if (cmd != NGX_PP_V2_CMD_PROXY) {
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 unsupported cmd 0x%xi", cmd);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
transport = hdr->fam_transp & 0x0F;
|
||||||
|
|
||||||
|
if (transport != NGX_PP_V2_STREAM) {
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 unsupported transport 0x%xi",
|
||||||
|
transport);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
family = hdr->fam_transp >> 4;
|
||||||
|
|
||||||
|
addrs = (ngx_pp_v2_addrs_t *) buf;
|
||||||
|
|
||||||
|
switch (family) {
|
||||||
|
|
||||||
|
case NGX_PP_V2_AF_UNSPEC:
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 AF_UNSPEC ignored");
|
||||||
|
return end;
|
||||||
|
|
||||||
|
case NGX_PP_V2_AF_INET:
|
||||||
|
|
||||||
|
if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet_addrs_t)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr.sockaddr_in.sin_family = AF_INET;
|
||||||
|
sockaddr.sockaddr_in.sin_port = 0;
|
||||||
|
memcpy(&sockaddr.sockaddr_in.sin_addr, addrs->inet.src, 4);
|
||||||
|
|
||||||
|
c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet.sport);
|
||||||
|
|
||||||
|
socklen = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
buf += sizeof(ngx_pp_v2_inet_addrs_t);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
case NGX_PP_V2_AF_INET6:
|
||||||
|
|
||||||
|
if ((size_t) (end - buf) < sizeof(ngx_pp_v2_inet6_addrs_t)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
||||||
|
sockaddr.sockaddr_in6.sin6_port = 0;
|
||||||
|
memcpy(&sockaddr.sockaddr_in6.sin6_addr, addrs->inet6.src, 16);
|
||||||
|
|
||||||
|
c->proxy_protocol_port = ngx_pp_v2_get_u16(addrs->inet6.sport);
|
||||||
|
|
||||||
|
socklen = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
|
buf += sizeof(ngx_pp_v2_inet6_addrs_t);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY_protocol v2 unsupported address family "
|
||||||
|
"0x%xi", family);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = &c->proxy_protocol_addr;
|
||||||
|
|
||||||
|
name->data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
|
||||||
|
if (name->data == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
name->len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, name->data,
|
||||||
|
NGX_SOCKADDR_STRLEN, 0);
|
||||||
|
if (name->len == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 address: %V %i", name,
|
||||||
|
(ngx_int_t) c->proxy_protocol_port);
|
||||||
|
|
||||||
|
if (buf < end) {
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 %z bytes tlv ignored", end - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user