Introduce proxy_protocol_src/dst_addr/port and store proxy_protocol header in ngx_connection struct. This enables proxy-proxy-protocol in stream module if proxy_protocol is enabled on both listen and outgoing, which should be the logical default.
Work in progress if/when this patch is accepted is proxy protocol support for the mail module. --- src/core/ngx_connection.h | 7 +- src/core/ngx_proxy_protocol.c | 111 ++++++++++++++++-------------- src/http/modules/ngx_http_realip_module.c | 6 +- src/http/ngx_http_variables.c | 60 ++++++++-------- src/stream/ngx_stream_realip_module.c | 10 +-- src/stream/ngx_stream_variables.c | 60 ++++++++-------- 6 files changed, 132 insertions(+), 122 deletions(-) diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index e484c81..c6e2337 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -148,8 +148,11 @@ 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_str_t proxy_protocol; + ngx_str_t proxy_protocol_src_addr; + ngx_str_t proxy_protocol_src_port; + ngx_str_t proxy_protocol_dst_addr; + ngx_str_t proxy_protocol_dst_port; #if (NGX_SSL) ngx_ssl_connection_t *ssl; diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c index 523ec35..04dae8b 100644 --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -13,8 +13,9 @@ 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; + ngx_uint_t i, n; + u_char ch, *p, *pp; + ngx_str_t addr[2], port[2]; p = buf; len = last - buf; @@ -40,77 +41,79 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) } p += 5; - addr = p; - for ( ;; ) { - if (p == last) { - goto invalid; - } + for (i=0;i<2;i++) { + addr[i].data = p; - ch = *p++; + for ( ;; ) { + if (p == last) { + goto invalid; + } - if (ch == ' ') { - break; - } + ch = *p++; - if (ch != ':' && ch != '.' - && (ch < 'a' || ch > 'f') - && (ch < 'A' || ch > 'F') - && (ch < '0' || ch > '9')) - { - goto invalid; - } - } + if (ch == ' ') { + break; + } - len = p - addr - 1; - c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len); + if (ch != ':' && ch != '.' + && (ch < 'a' || ch > 'f') + && (ch < 'A' || ch > 'F') + && (ch < '0' || ch > '9')) + { + goto invalid; + } + } - if (c->proxy_protocol_addr.data == NULL) { - return NULL; + addr[i].len = p - addr[i].data - 1; } - ngx_memcpy(c->proxy_protocol_addr.data, addr, len); - c->proxy_protocol_addr.len = len; + for (i=0;i<2;i++) { + port[i].data = p; - for ( ;; ) { - if (p == last) { - goto invalid; - } + for ( ;; ) { + if (p == last) { + goto invalid; + } - if (*p++ == ' ') { - break; + if ((*p++ == ' ' && i == 0) || (i == 1 && p != last && *p == CR)) { + break; + } } - } - port = p; + port[i].len = p - port[i].data - (1-i); + n = ngx_atoi(port[i].data, port[i].len); - for ( ;; ) { - if (p == last) { + if (n < 1 || n > 65535) { goto invalid; } - - if (*p++ == ' ') { - break; - } - } - - len = p - port - 1; - - n = ngx_atoi(port, len); - - if (n < 0 || n > 65535) { - goto invalid; } - c->proxy_protocol_port = (in_port_t) n; - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol address: %V %i", &c->proxy_protocol_addr, n); - skip: for ( /* void */ ; p < last - 1; p++) { if (p[0] == CR && p[1] == LF) { + len = p - buf - 6; + c->proxy_protocol.data = ngx_pnalloc(c->pool, len); + ngx_memcpy(c->proxy_protocol.data, buf + 6, len); + c->proxy_protocol.len = len; + + if (i) { /* not UNKNOWN */ + pp = c->proxy_protocol.data; + c->proxy_protocol_src_addr.data = pp + (addr[0].data - buf - 6); + c->proxy_protocol_src_port.data = pp + (port[0].data - buf - 6); + c->proxy_protocol_dst_addr.data = pp + (addr[1].data - buf - 6); + c->proxy_protocol_dst_port.data = pp + (port[1].data - buf - 6); + c->proxy_protocol_src_addr.len = addr[0].len; + c->proxy_protocol_src_port.len = port[0].len; + c->proxy_protocol_dst_addr.len = addr[1].len; + c->proxy_protocol_dst_port.len = port[1].len; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol address: %V %V", + &addr[0], &port[0]); + } + return p + 2; } } @@ -133,6 +136,10 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) return NULL; } + if (c->proxy_protocol.len) { + return ngx_slprintf(buf, last, "PROXY %V" CRLF, &c->proxy_protocol); + } + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { return NULL; } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index dba3c52..e2f7bdd 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -180,7 +180,7 @@ ngx_http_realip_handler(ngx_http_request_t *r) case NGX_HTTP_REALIP_PROXY: - value = &r->connection->proxy_protocol_addr; + value = &r->connection->proxy_protocol_src_addr; if (value->len == 0) { return NGX_DECLINED; @@ -238,7 +238,9 @@ 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, (in_port_t) + ngx_atoi(c->proxy_protocol_src_port.data, + c->proxy_protocol_src_port.len)); } 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 7e65b2e..6071874 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -56,9 +56,7 @@ static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, +static ngx_int_t ngx_http_variable_proxy_protocol_value(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -194,10 +192,28 @@ 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_value, + offsetof(ngx_connection_t, proxy_protocol_src_addr), 0, 0 }, + + { ngx_string("proxy_protocol_src_addr"), NULL, + ngx_http_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_addr), 0, 0 }, + + { ngx_string("proxy_protocol_dst_addr"), NULL, + ngx_http_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_dst_addr), 0, 0 }, { ngx_string("proxy_protocol_port"), NULL, - ngx_http_variable_proxy_protocol_port, 0, 0, 0 }, + ngx_http_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_port), 0, 0 }, + + { ngx_string("proxy_protocol_src_port"), NULL, + ngx_http_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_port), 0, 0 }, + + { ngx_string("proxy_protocol_dst_port"), NULL, + ngx_http_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_dst_port), 0, 0 }, { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, @@ -1224,40 +1240,22 @@ ngx_http_variable_remote_port(ngx_http_request_t *r, static ngx_int_t -ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, +ngx_http_variable_proxy_protocol_value(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - v->len = r->connection->proxy_protocol_addr.len; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = r->connection->proxy_protocol_addr.data; - - return NGX_OK; -} + ngx_str_t *a; + a = (ngx_str_t *) ((char *) r->connection + data); -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; + if (a->data == NULL) { + return NGX_ERROR; + } - v->len = 0; + v->len = a->len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - - v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - - port = r->connection->proxy_protocol_port; - - if (port > 0 && port < 65536) { - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - } + v->data = a->data; return NGX_OK; } diff --git a/src/stream/ngx_stream_realip_module.c b/src/stream/ngx_stream_realip_module.c index 0740431..3380aab 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_src_addr.len == 0) { return NGX_DECLINED; } @@ -116,14 +116,16 @@ 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, + (in_port_t) ngx_atoi(c->proxy_protocol_src_port.data, + c->proxy_protocol_src_port.len)); 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 aa5361d..0aa4f73 100644 --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -17,9 +17,7 @@ static ngx_int_t ngx_stream_variable_remote_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_remote_port(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_stream_variable_proxy_protocol_addr( - ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_stream_variable_proxy_protocol_port( +static ngx_int_t ngx_stream_variable_proxy_protocol_value( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); @@ -62,10 +60,28 @@ 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_value, + offsetof(ngx_connection_t, proxy_protocol_src_addr), 0, 0 }, + + { ngx_string("proxy_protocol_src_addr"), NULL, + ngx_stream_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_addr), 0, 0 }, + + { ngx_string("proxy_protocol_dst_addr"), NULL, + ngx_stream_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_dst_addr), 0, 0 }, { ngx_string("proxy_protocol_port"), NULL, - ngx_stream_variable_proxy_protocol_port, 0, 0, 0 }, + ngx_stream_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_port), 0, 0 }, + + { ngx_string("proxy_protocol_src_port"), NULL, + ngx_stream_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_src_port), 0, 0 }, + + { ngx_string("proxy_protocol_dst_port"), NULL, + ngx_stream_variable_proxy_protocol_value, + offsetof(ngx_connection_t, proxy_protocol_dst_port), 0, 0 }, { ngx_string("server_addr"), NULL, ngx_stream_variable_server_addr, 0, 0, 0 }, @@ -428,40 +444,22 @@ ngx_stream_variable_remote_port(ngx_stream_session_t *s, static ngx_int_t -ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s, +ngx_stream_variable_proxy_protocol_value(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { - v->len = s->connection->proxy_protocol_addr.len; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = s->connection->proxy_protocol_addr.data; - - return NGX_OK; -} + ngx_str_t *a; + a = (ngx_str_t *) ((char *) s->connection + data); -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; + if (a->data == NULL) { + return NGX_ERROR; + } - v->len = 0; + v->len = a->len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - - v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - - port = s->connection->proxy_protocol_port; - - if (port > 0 && port < 65536) { - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - } + v->data = a->data; return NGX_OK; } -- 2.7.4 _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel