[nginx] Parsing server PROXY protocol address and port (ticket #1206).

Roman Arutyunyan arut at nginx.com
Thu Oct 24 10:55:28 UTC 2019


details:   https://hg.nginx.org/nginx/rev/89adf49fe76a
branches:  
changeset: 7591:89adf49fe76a
user:      Roman Arutyunyan <arut at nginx.com>
date:      Mon Oct 21 20:22:30 2019 +0300
description:
Parsing server PROXY protocol address and port (ticket #1206).

New variables $proxy_protocol_server_addr and $proxy_protocol_server_port are
added both to HTTP and Stream.

diffstat:

 src/core/ngx_proxy_protocol.c     |  206 ++++++++++++++++++++++++-------------
 src/core/ngx_proxy_protocol.h     |    2 +
 src/http/ngx_http_variables.c     |   23 +++-
 src/stream/ngx_stream_variables.c |   23 +++-
 4 files changed, 173 insertions(+), 81 deletions(-)

diffs (419 lines):

diff -r 06b01840bd42 -r 89adf49fe76a src/core/ngx_proxy_protocol.c
--- a/src/core/ngx_proxy_protocol.c	Mon Oct 21 18:06:19 2019 +0300
+++ b/src/core/ngx_proxy_protocol.c	Mon Oct 21 20:22:30 2019 +0300
@@ -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);
 
@@ -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";
@@ -84,81 +87,48 @@ ngx_proxy_protocol_read(ngx_connection_t
     }
 
     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;
-        }
-    }
 
     pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
     if (pp == NULL) {
         return NULL;
     }
 
-    len = p - addr - 1;
-
-    pp->src_addr.data = ngx_pnalloc(c->pool, len);
-    if (pp->src_addr.data == NULL) {
-        return NULL;
+    p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
+    if (p == NULL) {
+        goto invalid;
     }
 
-    ngx_memcpy(pp->src_addr.data, addr, len);
-    pp->src_addr.len = len;
-
-    for ( ;; ) {
-        if (p == last) {
-            goto invalid;
-        }
-
-        if (*p++ == ' ') {
-            break;
-        }
+    p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
+    if (p == NULL) {
+        goto invalid;
     }
 
-    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_port(p, last, &pp->src_port, ' ');
+    if (p == NULL) {
         goto invalid;
     }
 
-    pp->src_port = (in_port_t) n;
+    p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
+    if (p == NULL) {
+        goto invalid;
+    }
 
-    ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
-                   "PROXY protocol address: %V %d", &pp->src_addr,
-                   pp->src_port);
+    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++) {
@@ -176,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)
 {
@@ -227,7 +273,7 @@ ngx_proxy_protocol_v2_read(ngx_connectio
     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;
@@ -292,11 +338,16 @@ ngx_proxy_protocol_v2_read(ngx_connectio
 
         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);
 
@@ -314,11 +365,16 @@ ngx_proxy_protocol_v2_read(ngx_connectio
 
         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);
 
@@ -340,12 +396,20 @@ ngx_proxy_protocol_v2_read(ngx_connectio
         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,
diff -r 06b01840bd42 -r 89adf49fe76a src/core/ngx_proxy_protocol.h
--- a/src/core/ngx_proxy_protocol.h	Mon Oct 21 18:06:19 2019 +0300
+++ b/src/core/ngx_proxy_protocol.h	Mon Oct 21 20:22:30 2019 +0300
@@ -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;
 };
 
 
diff -r 06b01840bd42 -r 89adf49fe76a src/http/ngx_http_variables.c
--- a/src/http/ngx_http_variables.c	Mon Oct 21 18:06:19 2019 +0300
+++ b/src/http/ngx_http_variables.c	Mon Oct 21 20:22:30 2019 +0300
@@ -199,10 +199,20 @@ static ngx_http_variable_t  ngx_http_cor
     { 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,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;
@@ -1301,11 +1312,13 @@ ngx_http_variable_proxy_protocol_addr(ng
         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;
 }
@@ -1334,7 +1347,7 @@ ngx_http_variable_proxy_protocol_port(ng
         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;
diff -r 06b01840bd42 -r 89adf49fe76a src/stream/ngx_stream_variables.c
--- a/src/stream/ngx_stream_variables.c	Mon Oct 21 18:06:19 2019 +0300
+++ b/src/stream/ngx_stream_variables.c	Mon Oct 21 20:22:30 2019 +0300
@@ -64,10 +64,20 @@ static ngx_stream_variable_t  ngx_stream
       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,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;
@@ -565,11 +576,13 @@ ngx_stream_variable_proxy_protocol_addr(
         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;
 }
@@ -598,7 +611,7 @@ ngx_stream_variable_proxy_protocol_port(
         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;


More information about the nginx-devel mailing list