From d12bc8b6564519740c2065600d956a4946ff0587 Mon Sep 17 00:00:00 2001 From: Hakase Date: Thu, 24 Oct 2019 21:00:01 +0900 Subject: [PATCH] Latest update - 7591 --- src/core/ngx_connection.h | 3 +- src/core/ngx_core.h | 1 + src/core/ngx_proxy_protocol.c | 237 ++++++++++++++-------- src/core/ngx_proxy_protocol.h | 8 + src/http/modules/ngx_http_realip_module.c | 7 +- src/http/ngx_http_variables.c | 40 +++- src/stream/ngx_stream_realip_module.c | 8 +- src/stream/ngx_stream_variables.c | 40 +++- 8 files changed, 243 insertions(+), 101 deletions(-) diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 5405962..ad6556d 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -147,8 +147,7 @@ struct ngx_connection_s { socklen_t socklen; ngx_str_t addr_text; - ngx_str_t proxy_protocol_addr; - in_port_t proxy_protocol_port; + ngx_proxy_protocol_t *proxy_protocol; #if (NGX_SSL || NGX_COMPAT) ngx_ssl_connection_t *ssl; diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 93ca917..7ecdca0 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -26,6 +26,7 @@ typedef struct ngx_event_aio_s ngx_event_aio_t; typedef struct ngx_connection_s ngx_connection_t; typedef struct ngx_thread_task_s ngx_thread_task_t; typedef struct ngx_ssl_s ngx_ssl_t; +typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t; typedef struct ngx_ssl_connection_s ngx_ssl_connection_t; typedef struct ngx_udp_connection_s ngx_udp_connection_t; diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c index c3d7fd3..7a9e7f9 100644 --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -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); @@ -47,9 +51,9 @@ static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, 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; + size_t len; + u_char *p; + ngx_proxy_protocol_t *pp; static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n"; @@ -83,73 +87,47 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) } p += 5; - addr = p; - for ( ;; ) { - if (p == last) { - goto invalid; - } - - ch = *p++; - - if (ch == ' ') { - break; - } - - if (ch != ':' && ch != '.' - && (ch < 'a' || ch > 'f') - && (ch < 'A' || ch > 'F') - && (ch < '0' || ch > '9')) - { - goto invalid; - } - } - - len = p - addr - 1; - c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len); - - if (c->proxy_protocol_addr.data == NULL) { + pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); + if (pp == NULL) { return NULL; } - ngx_memcpy(c->proxy_protocol_addr.data, addr, len); - c->proxy_protocol_addr.len = len; - - for ( ;; ) { - if (p == last) { - goto invalid; - } - - if (*p++ == ' ') { - break; - } - } - - port = p; - - for ( ;; ) { - if (p == last) { - goto invalid; - } - - if (*p++ == ' ') { - break; - } - } - - len = p - port - 1; - - n = ngx_atoi(port, len); - - if (n < 0 || n > 65535) { + p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr); + if (p == NULL) { goto invalid; } - c->proxy_protocol_port = (in_port_t) n; + p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr); + if (p == NULL) { + goto invalid; + } - ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol address: %V %d", &c->proxy_protocol_addr, - c->proxy_protocol_port); + 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: @@ -168,6 +146,82 @@ invalid: } +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) { + return NULL; + } + + ch = *p++; + + if (ch == ' ') { + break; + } + + if (ch != ':' && ch != '.' + && (ch < 'a' || ch > 'f') + && (ch < 'A' || ch > 'F') + && (ch < '0' || ch > '9')) + { + return NULL; + } + } + + len = p - pos - 1; + + addr->data = ngx_pnalloc(c->pool, len); + if (addr->data == NULL) { + return NULL; + } + + ngx_memcpy(addr->data, pos, len); + addr->len = len; + + return 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) { + return NULL; + } + + if (*p++ == sep) { + break; + } + } + + len = p - pos - 1; + + n = ngx_atoi(pos, len); + if (n < 0 || n > 65535) { + return NULL; + } + + *port = (in_port_t) n; + + return p; +} + + u_char * ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) { @@ -219,7 +273,8 @@ 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; #if (NGX_HAVE_INET6) @@ -266,6 +321,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last) return end; } + pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t)); + if (pp == NULL) { + return NULL; + } + family = header->family_transport >> 4; switch (family) { @@ -278,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); - c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in->src_port); + 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); @@ -300,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); - c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in6->src_port); + 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); @@ -321,23 +391,32 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last) return end; } - c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); - if (c->proxy_protocol_addr.data == NULL) { + pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); + if (pp->src_addr.data == NULL) { return NULL; } - c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, - c->proxy_protocol_addr.data, - NGX_SOCKADDR_STRLEN, 0); + 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", &c->proxy_protocol_addr, - c->proxy_protocol_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, "PROXY protocol v2 %z bytes of tlv ignored", end - buf); } + c->proxy_protocol = pp; + return end; } diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h index fb848f6..b716220 100644 --- a/src/core/ngx_proxy_protocol.h +++ b/src/core/ngx_proxy_protocol.h @@ -16,6 +16,14 @@ #define NGX_PROXY_PROTOCOL_MAX_HEADER 107 +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; +}; + + u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last); u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index 7d3f2a9..9586ebe 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -180,12 +180,11 @@ ngx_http_realip_handler(ngx_http_request_t *r) case NGX_HTTP_REALIP_PROXY: - value = &r->connection->proxy_protocol_addr; - - if (value->len == 0) { + if (r->connection->proxy_protocol == NULL) { return NGX_DECLINED; } + value = &r->connection->proxy_protocol->src_addr; xfwd = NULL; break; @@ -238,7 +237,7 @@ found: != NGX_DECLINED) { if (rlcf->type == NGX_HTTP_REALIP_PROXY) { - ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); + ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); } return ngx_http_realip_set_addr(r, &addr); diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index aa38ab3..e067cf0 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -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 }, @@ -1293,11 +1303,22 @@ static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - v->len = r->connection->proxy_protocol_addr.len; + ngx_str_t *addr; + ngx_proxy_protocol_t *pp; + + pp = r->connection->proxy_protocol; + if (pp == NULL) { + v->not_found = 1; + return NGX_OK; + } + + addr = (ngx_str_t *) ((char *) pp + data); + + v->len = addr->len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - v->data = r->connection->proxy_protocol_addr.data; + v->data = addr->data; return NGX_OK; } @@ -1307,7 +1328,14 @@ static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; + ngx_uint_t port; + ngx_proxy_protocol_t *pp; + + pp = r->connection->proxy_protocol; + if (pp == NULL) { + v->not_found = 1; + return NGX_OK; + } v->len = 0; v->valid = 1; @@ -1319,7 +1347,7 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, return NGX_ERROR; } - port = r->connection->proxy_protocol_port; + port = *(in_port_t *) ((char *) pp + data); if (port > 0 && port < 65536) { v->len = ngx_sprintf(v->data, "%ui", port) - v->data; diff --git a/src/stream/ngx_stream_realip_module.c b/src/stream/ngx_stream_realip_module.c index 57b1ac2..603f597 100644 --- a/src/stream/ngx_stream_realip_module.c +++ b/src/stream/ngx_stream_realip_module.c @@ -108,7 +108,7 @@ ngx_stream_realip_handler(ngx_stream_session_t *s) c = s->connection; - if (c->proxy_protocol_addr.len == 0) { + if (c->proxy_protocol == NULL) { return NGX_DECLINED; } @@ -116,14 +116,14 @@ ngx_stream_realip_handler(ngx_stream_session_t *s) return NGX_DECLINED; } - if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data, - c->proxy_protocol_addr.len) + if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data, + c->proxy_protocol->src_addr.len) != NGX_OK) { return NGX_DECLINED; } - ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); + ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); return ngx_stream_realip_set_addr(s, &addr); } diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c index d1526a9..8b59668 100644 --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -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 }, @@ -557,11 +567,22 @@ static ngx_int_t ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { - v->len = s->connection->proxy_protocol_addr.len; + ngx_str_t *addr; + ngx_proxy_protocol_t *pp; + + pp = s->connection->proxy_protocol; + if (pp == NULL) { + v->not_found = 1; + return NGX_OK; + } + + addr = (ngx_str_t *) ((char *) pp + data); + + v->len = addr->len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - v->data = s->connection->proxy_protocol_addr.data; + v->data = addr->data; return NGX_OK; } @@ -571,7 +592,14 @@ static ngx_int_t ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; + ngx_uint_t port; + ngx_proxy_protocol_t *pp; + + pp = s->connection->proxy_protocol; + if (pp == NULL) { + v->not_found = 1; + return NGX_OK; + } v->len = 0; v->valid = 1; @@ -583,7 +611,7 @@ ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s, return NGX_ERROR; } - port = s->connection->proxy_protocol_port; + port = *(in_port_t *) ((char *) pp + data); if (port > 0 && port < 65536) { v->len = ngx_sprintf(v->data, "%ui", port) - v->data;