[PATCH] proxy-protocol dst variables and proxy-proxy-protocol

Bjørnar Ness bjornar.ness at gmail.com
Sun Sep 18 12:11:14 UTC 2016


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



More information about the nginx-devel mailing list