[nginx] Added server-side support for PROXY protocol v1 (ticket ...

Roman Arutyunyan arut at nginx.com
Mon Mar 17 13:43:21 UTC 2014


details:   http://hg.nginx.org/nginx/rev/3a72b1805c52
branches:  
changeset: 5605:3a72b1805c52
user:      Roman Arutyunyan <arut at nginx.com>
date:      Mon Mar 17 17:41:24 2014 +0400
description:
Added server-side support for PROXY protocol v1 (ticket #355).

Client address specified in the PROXY protocol header is now
saved in the $proxy_protocol_addr variable and can be used in
the realip module.

This is currently not implemented for mail.

diffstat:

 auto/sources                              |   6 +-
 src/core/ngx_connection.h                 |   2 +
 src/core/ngx_core.h                       |   1 +
 src/core/ngx_proxy_protocol.c             |  91 +++++++++++++++++++++++++++++++
 src/core/ngx_proxy_protocol.h             |  23 +++++++
 src/http/modules/ngx_http_realip_module.c |  18 ++++++
 src/http/ngx_http.c                       |   1 +
 src/http/ngx_http_core_module.c           |   5 +
 src/http/ngx_http_core_module.h           |   2 +
 src/http/ngx_http_request.c               |  64 ++++++++++++++++++++-
 src/http/ngx_http_request.h               |   3 +-
 src/http/ngx_http_spdy.c                  |  23 +++++++
 src/http/ngx_http_variables.c             |  19 ++++++
 13 files changed, 252 insertions(+), 6 deletions(-)

diffs (truncated from 480 to 300 lines):

diff -r 22d485944c20 -r 3a72b1805c52 auto/sources
--- a/auto/sources	Mon Mar 17 15:34:36 2014 +0400
+++ b/auto/sources	Mon Mar 17 17:41:24 2014 +0400
@@ -36,7 +36,8 @@ CORE_DEPS="src/core/nginx.h \
            src/core/ngx_conf_file.h \
            src/core/ngx_resolver.h \
            src/core/ngx_open_file_cache.h \
-           src/core/ngx_crypt.h"
+           src/core/ngx_crypt.h \
+           src/core/ngx_proxy_protocol.h"
 
 
 CORE_SRCS="src/core/nginx.c \
@@ -67,7 +68,8 @@ CORE_SRCS="src/core/nginx.c \
            src/core/ngx_conf_file.c \
            src/core/ngx_resolver.c \
            src/core/ngx_open_file_cache.c \
-           src/core/ngx_crypt.c"
+           src/core/ngx_crypt.c \
+           src/core/ngx_proxy_protocol.c"
 
 
 REGEX_MODULE=ngx_regex_module
diff -r 22d485944c20 -r 3a72b1805c52 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/core/ngx_connection.h	Mon Mar 17 17:41:24 2014 +0400
@@ -139,6 +139,8 @@ struct ngx_connection_s {
     socklen_t           socklen;
     ngx_str_t           addr_text;
 
+    ngx_str_t           proxy_protocol_addr;
+
 #if (NGX_SSL)
     ngx_ssl_connection_t  *ssl;
 #endif
diff -r 22d485944c20 -r 3a72b1805c52 src/core/ngx_core.h
--- a/src/core/ngx_core.h	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/core/ngx_core.h	Mon Mar 17 17:41:24 2014 +0400
@@ -77,6 +77,7 @@ typedef void (*ngx_connection_handler_pt
 #include <ngx_open_file_cache.h>
 #include <ngx_os.h>
 #include <ngx_connection.h>
+#include <ngx_proxy_protocol.h>
 
 
 #define LF     (u_char) 10
diff -r 22d485944c20 -r 3a72b1805c52 src/core/ngx_proxy_protocol.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/ngx_proxy_protocol.c	Mon Mar 17 17:41:24 2014 +0400
@@ -0,0 +1,91 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+u_char *
+ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
+{
+    size_t  len;
+    u_char  ch, *p, *addr;
+
+    p = buf;
+    len = last - buf;
+
+    if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
+        goto invalid;
+    }
+
+    p += 6;
+    len -= 6;
+
+    if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
+        ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
+                       "PROXY protocol unknown protocol");
+        p += 7;
+        goto skip;
+    }
+
+    if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
+        || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
+    {
+        goto invalid;
+    }
+
+    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) {
+        return NULL;
+    }
+
+    ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
+    c->proxy_protocol_addr.len = len;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+                   "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
+
+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;
+}
diff -r 22d485944c20 -r 3a72b1805c52 src/core/ngx_proxy_protocol.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/ngx_proxy_protocol.h	Mon Mar 17 17:41:24 2014 +0400
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
+#define _NGX_PROXY_PROTOCOL_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#define NGX_PROXY_PROTOCOL_MAX_HEADER  107
+
+
+u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
+    u_char *last);
+
+
+#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
diff -r 22d485944c20 -r 3a72b1805c52 src/http/modules/ngx_http_realip_module.c
--- a/src/http/modules/ngx_http_realip_module.c	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/http/modules/ngx_http_realip_module.c	Mon Mar 17 17:41:24 2014 +0400
@@ -13,6 +13,7 @@
 #define NGX_HTTP_REALIP_XREALIP  0
 #define NGX_HTTP_REALIP_XFWD     1
 #define NGX_HTTP_REALIP_HEADER   2
+#define NGX_HTTP_REALIP_PROXY    3
 
 
 typedef struct {
@@ -156,6 +157,18 @@ ngx_http_realip_handler(ngx_http_request
 
         break;
 
+    case NGX_HTTP_REALIP_PROXY:
+
+        value = &r->connection->proxy_protocol_addr;
+
+        if (value->len == 0) {
+            return NGX_DECLINED;
+        }
+
+        xfwd = NULL;
+
+        break;
+
     default: /* NGX_HTTP_REALIP_HEADER */
 
         part = &r->headers_in.headers.part;
@@ -343,6 +356,11 @@ ngx_http_realip(ngx_conf_t *cf, ngx_comm
         return NGX_CONF_OK;
     }
 
+    if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) {
+        rlcf->type = NGX_HTTP_REALIP_PROXY;
+        return NGX_CONF_OK;
+    }
+
     rlcf->type = NGX_HTTP_REALIP_HEADER;
     rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len);
     rlcf->header = value[1];
diff -r 22d485944c20 -r 3a72b1805c52 src/http/ngx_http.c
--- a/src/http/ngx_http.c	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/http/ngx_http.c	Mon Mar 17 17:41:24 2014 +0400
@@ -1849,6 +1849,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h
 #if (NGX_HTTP_SPDY)
         addrs[i].conf.spdy = addr[i].opt.spdy;
 #endif
+        addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
 
         if (addr[i].hash.buckets == NULL
             && (addr[i].wc_head == NULL
diff -r 22d485944c20 -r 3a72b1805c52 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/http/ngx_http_core_module.c	Mon Mar 17 17:41:24 2014 +0400
@@ -4287,6 +4287,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
 #endif
         }
 
+        if (ngx_strcmp(value[n].data, "proxy_protocol") == 0) {
+            lsopt.proxy_protocol = 1;
+            continue;
+        }
+
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid parameter \"%V\"", &value[n]);
         return NGX_CONF_ERROR;
diff -r 22d485944c20 -r 3a72b1805c52 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/http/ngx_http_core_module.h	Mon Mar 17 17:41:24 2014 +0400
@@ -82,6 +82,7 @@ typedef struct {
     unsigned                   ipv6only:1;
 #endif
     unsigned                   so_keepalive:2;
+    unsigned                   proxy_protocol:1;
 
     int                        backlog;
     int                        rcvbuf;
@@ -243,6 +244,7 @@ struct ngx_http_addr_conf_s {
 #if (NGX_HTTP_SPDY)
     unsigned                   spdy:1;
 #endif
+    unsigned                   proxy_protocol:1;
 };
 
 
diff -r 22d485944c20 -r 3a72b1805c52 src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c	Mon Mar 17 15:34:36 2014 +0400
+++ b/src/http/ngx_http_request.c	Mon Mar 17 17:41:24 2014 +0400
@@ -343,6 +343,11 @@ ngx_http_init_connection(ngx_connection_
     }
 #endif
 
+    if (hc->addr_conf->proxy_protocol) {
+        hc->proxy_protocol = 1;
+        c->log->action = "reading PROXY protocol";
+    }
+
     if (rev->ready) {
         /* the deferred accept(), rtsig, aio, iocp */
 
@@ -368,6 +373,7 @@ ngx_http_init_connection(ngx_connection_
 static void
 ngx_http_wait_request_handler(ngx_event_t *rev)
 {
+    u_char                    *p;
     size_t                     size;
     ssize_t                    n;
     ngx_buf_t                 *b;
@@ -458,6 +464,27 @@ ngx_http_wait_request_handler(ngx_event_
 
     b->last += n;
 
+    if (hc->proxy_protocol) {
+        hc->proxy_protocol = 0;
+
+        p = ngx_proxy_protocol_parse(c, b->pos, b->last);
+
+        if (p == NULL) {
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        b->pos = p;
+
+        if (b->pos == b->last) {
+            c->log->action = "waiting for request";
+            b->pos = b->start;
+            b->last = b->start;
+            ngx_post_event(rev, &ngx_posted_events);
+            return;



More information about the nginx-devel mailing list