Skip to content

Commit

Permalink
Parsing server PROXY protocol address and port (ticket #1206).
Browse files Browse the repository at this point in the history
New variables $proxy_protocol_server_addr and $proxy_protocol_server_port are
added both to HTTP and Stream.
  • Loading branch information
arut committed Oct 21, 2019
1 parent be932e8 commit 2038985
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 72 deletions.
188 changes: 126 additions & 62 deletions src/core/ngx_proxy_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ typedef struct {
} ngx_proxy_protocol_inet6_addrs_t;


static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
u_char *last, ngx_str_t *addr);
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
in_port_t *port, u_char sep);
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
u_char *last);

Expand All @@ -48,8 +52,7 @@ u_char *
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{
size_t len;
u_char ch, *p, *addr, *port;
ngx_int_t n;
u_char *p;
ngx_proxy_protocol_t *pp;

static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
Expand Down Expand Up @@ -84,11 +87,77 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
}

p += 5;
addr = p;

pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (pp == NULL) {
return NULL;
}

p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
if (p == NULL) {
goto invalid;
}

p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
if (p == NULL) {
goto invalid;
}

p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
if (p == NULL) {
goto invalid;
}

p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
if (p == NULL) {
goto invalid;
}

if (p == last) {
goto invalid;
}

if (*p++ != LF) {
goto invalid;
}

ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol src: %V %d, dst: %V %d",
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);

c->proxy_protocol = pp;

return p;

skip:

for ( /* void */ ; p < last - 1; p++) {
if (p[0] == CR && p[1] == LF) {
return p + 2;
}
}

invalid:

ngx_log_error(NGX_LOG_ERR, c->log, 0,
"broken header: \"%*s\"", (size_t) (last - buf), buf);

return NULL;
}


static u_char *
ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last,
ngx_str_t *addr)
{
size_t len;
u_char ch, *pos;

pos = p;

for ( ;; ) {
if (p == last) {
goto invalid;
return NULL;
}

ch = *p++;
Expand All @@ -102,77 +171,54 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
&& (ch < 'A' || ch > 'F')
&& (ch < '0' || ch > '9'))
{
goto invalid;
return NULL;
}
}

pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (pp == NULL) {
return NULL;
}

len = p - addr - 1;
len = p - pos - 1;

pp->src_addr.data = ngx_pnalloc(c->pool, len);
if (pp->src_addr.data == NULL) {
addr->data = ngx_pnalloc(c->pool, len);
if (addr->data == NULL) {
return NULL;
}

ngx_memcpy(pp->src_addr.data, addr, len);
pp->src_addr.len = len;
ngx_memcpy(addr->data, pos, len);
addr->len = len;

for ( ;; ) {
if (p == last) {
goto invalid;
}
return p;
}

if (*p++ == ' ') {
break;
}
}

port = p;
static u_char *
ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
u_char sep)
{
size_t len;
u_char *pos;
ngx_int_t n;

pos = p;

for ( ;; ) {
if (p == last) {
goto invalid;
return NULL;
}

if (*p++ == ' ') {
if (*p++ == sep) {
break;
}
}

len = p - port - 1;

n = ngx_atoi(port, len);
len = p - pos - 1;

n = ngx_atoi(pos, len);
if (n < 0 || n > 65535) {
goto invalid;
}

pp->src_port = (in_port_t) n;

ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol address: %V %d", &pp->src_addr,
pp->src_port);

c->proxy_protocol = pp;

skip:

for ( /* void */ ; p < last - 1; p++) {
if (p[0] == CR && p[1] == LF) {
return p + 2;
}
return NULL;
}

invalid:

ngx_log_error(NGX_LOG_ERR, c->log, 0,
"broken header: \"%*s\"", (size_t) (last - buf), buf);
*port = (in_port_t) n;

return NULL;
return p;
}


Expand Down Expand Up @@ -227,7 +273,7 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
size_t len;
socklen_t socklen;
ngx_uint_t version, command, family, transport;
ngx_sockaddr_t sockaddr;
ngx_sockaddr_t src_sockaddr, dst_sockaddr;
ngx_proxy_protocol_t *pp;
ngx_proxy_protocol_header_t *header;
ngx_proxy_protocol_inet_addrs_t *in;
Expand Down Expand Up @@ -292,11 +338,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)

in = (ngx_proxy_protocol_inet_addrs_t *) buf;

sockaddr.sockaddr_in.sin_family = AF_INET;
sockaddr.sockaddr_in.sin_port = 0;
memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
src_sockaddr.sockaddr_in.sin_family = AF_INET;
src_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);

dst_sockaddr.sockaddr_in.sin_family = AF_INET;
dst_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);

pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);

socklen = sizeof(struct sockaddr_in);

Expand All @@ -314,11 +365,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)

in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;

sockaddr.sockaddr_in6.sin6_family = AF_INET6;
sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
src_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);

dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
dst_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);

pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);

socklen = sizeof(struct sockaddr_in6);

Expand All @@ -340,12 +396,20 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
return NULL;
}

pp->src_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);

ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 address: %V %d", &pp->src_addr,
pp->src_port);
pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
if (pp->dst_addr.data == NULL) {
return NULL;
}

pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen,
pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 0);

ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 src: %V %d, dst: %V %d",
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);

if (buf < end) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
Expand Down
2 changes: 2 additions & 0 deletions src/core/ngx_proxy_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

struct ngx_proxy_protocol_s {
ngx_str_t src_addr;
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
};


Expand Down
23 changes: 18 additions & 5 deletions src/http/ngx_http_variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,20 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },

{ ngx_string("proxy_protocol_addr"), NULL,
ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
ngx_http_variable_proxy_protocol_addr,
offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },

{ ngx_string("proxy_protocol_port"), NULL,
ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
ngx_http_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },

{ ngx_string("proxy_protocol_server_addr"), NULL,
ngx_http_variable_proxy_protocol_addr,
offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },

{ ngx_string("proxy_protocol_server_port"), NULL,
ngx_http_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },

{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },

Expand Down Expand Up @@ -1293,6 +1303,7 @@ static ngx_int_t
ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_str_t *addr;
ngx_proxy_protocol_t *pp;

pp = r->connection->proxy_protocol;
Expand All @@ -1301,11 +1312,13 @@ ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
return NGX_OK;
}

v->len = pp->src_addr.len;
addr = (ngx_str_t *) ((char *) pp + data);

v->len = addr->len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = pp->src_addr.data;
v->data = addr->data;

return NGX_OK;
}
Expand Down Expand Up @@ -1334,7 +1347,7 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
return NGX_ERROR;
}

port = pp->src_port;
port = *(in_port_t *) ((char *) pp + data);

if (port > 0 && port < 65536) {
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
Expand Down
23 changes: 18 additions & 5 deletions src/stream/ngx_stream_variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,20 @@ static ngx_stream_variable_t ngx_stream_core_variables[] = {
ngx_stream_variable_remote_port, 0, 0, 0 },

{ ngx_string("proxy_protocol_addr"), NULL,
ngx_stream_variable_proxy_protocol_addr, 0, 0, 0 },
ngx_stream_variable_proxy_protocol_addr,
offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },

{ ngx_string("proxy_protocol_port"), NULL,
ngx_stream_variable_proxy_protocol_port, 0, 0, 0 },
ngx_stream_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },

{ ngx_string("proxy_protocol_server_addr"), NULL,
ngx_stream_variable_proxy_protocol_addr,
offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },

{ ngx_string("proxy_protocol_server_port"), NULL,
ngx_stream_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },

{ ngx_string("server_addr"), NULL,
ngx_stream_variable_server_addr, 0, 0, 0 },
Expand Down Expand Up @@ -557,6 +567,7 @@ static ngx_int_t
ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)
{
ngx_str_t *addr;
ngx_proxy_protocol_t *pp;

pp = s->connection->proxy_protocol;
Expand All @@ -565,11 +576,13 @@ ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s,
return NGX_OK;
}

v->len = pp->src_addr.len;
addr = (ngx_str_t *) ((char *) pp + data);

v->len = addr->len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = pp->src_addr.data;
v->data = addr->data;

return NGX_OK;
}
Expand Down Expand Up @@ -598,7 +611,7 @@ ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s,
return NGX_ERROR;
}

port = pp->src_port;
port = *(in_port_t *) ((char *) pp + data);

if (port > 0 && port < 65536) {
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
Expand Down

0 comments on commit 2038985

Please sign in to comment.