You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1183 lines
34 KiB

Index: nginx-1.4.7/auto/modules
===================================================================
--- nginx-1.4.7.orig/auto/modules
+++ nginx-1.4.7/auto/modules
@@ -297,6 +297,10 @@ if [ $HTTP_SSL = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_SSL_SRCS"
fi
+if [ $PROXY_PROTOCOL = YES ]; then
+ have=NGX_PROXY_PROTOCOL . auto/have
+fi
+
if [ $HTTP_PROXY = YES ]; then
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
#USE_MD5=YES
Index: nginx-1.4.7/auto/options
===================================================================
--- nginx-1.4.7.orig/auto/options
+++ nginx-1.4.7/auto/options
@@ -47,6 +47,8 @@ USE_THREADS=NO
NGX_FILE_AIO=NO
NGX_IPV6=NO
+PROXY_PROTOCOL=NO
+
HTTP=YES
NGX_HTTP_LOG_PATH=
@@ -192,6 +194,8 @@ do
--with-file-aio) NGX_FILE_AIO=YES ;;
--with-ipv6) NGX_IPV6=YES ;;
+ --with-proxy-protocol) PROXY_PROTOCOL=YES ;;
+
--without-http) HTTP=NO ;;
--without-http-cache) HTTP_CACHE=NO ;;
@@ -350,6 +354,8 @@ cat << END
--with-file-aio enable file AIO support
--with-ipv6 enable IPv6 support
+ --with-proxy-protocol enable proxy protocol support
+
--with-http_ssl_module enable ngx_http_ssl_module
--with-http_spdy_module enable ngx_http_spdy_module
--with-http_realip_module enable ngx_http_realip_module
Index: nginx-1.4.7/auto/sources
===================================================================
--- nginx-1.4.7.orig/auto/sources
+++ nginx-1.4.7/auto/sources
@@ -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
Index: nginx-1.4.7/src/core/ngx_connection.h
===================================================================
--- nginx-1.4.7.orig/src/core/ngx_connection.h
+++ nginx-1.4.7/src/core/ngx_connection.h
@@ -63,6 +63,10 @@ struct ngx_listening_s {
unsigned shared:1; /* shared between threads or processes */
unsigned addr_ntop:1;
+#if (NGX_PROXY_PROTOCOL)
+ unsigned accept_proxy_protocol:2; /* proxy_protocol flag */
+#endif
+
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:1;
#endif
@@ -148,6 +152,10 @@ struct ngx_connection_s {
ngx_uint_t requests;
+#if (NGX_PROXY_PROTOCOL)
+ ngx_uint_t proxy_protocol;
+#endif
+
unsigned buffered:8;
unsigned log_error:3; /* ngx_connection_log_error_e */
Index: nginx-1.4.7/src/core/ngx_core.h
===================================================================
--- nginx-1.4.7.orig/src/core/ngx_core.h
+++ nginx-1.4.7/src/core/ngx_core.h
@@ -77,6 +77,9 @@ typedef void (*ngx_connection_handler_pt
#include <ngx_open_file_cache.h>
#include <ngx_os.h>
#include <ngx_connection.h>
+#if (NGX_PROXY_PROTOCOL)
+#include <ngx_proxy_protocol.h>
+#endif
#define LF (u_char) 10
Index: nginx-1.4.7/src/core/ngx_proxy_protocol.c
===================================================================
--- /dev/null
+++ nginx-1.4.7/src/core/ngx_proxy_protocol.c
@@ -0,0 +1,430 @@
+
+/*
+ * Copyright (C) Baptiste Assmann
+ * Copyright (C) Exceliance
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+#if (NGX_PROXY_PROTOCOL)
+
+int
+ngx_recv_proxy_protocol(ngx_connection_t *c, u_char *buf, ssize_t n)
+{
+ u_char *end, *p, *t;
+ size_t len;
+ ssize_t s;
+ int step = 0;
+ ngx_proxy_protocol_t pp;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "processing proxy protocol");
+
+ /* 16 is the minimal length of the proxy protocol string */
+ if (n < 18) {
+ step = 1;
+ goto fail;
+ }
+
+ s = n;
+ end = memchr(buf, '\n', n);
+ if (end == NULL) {
+ step = 2;
+ goto fail;
+ }
+
+ p = buf;
+ if (memcmp(p, "PROXY ", 6) != 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "incorrect proxy protocol header string");
+ step = 3;
+ goto fail;
+ }
+ p += 6;
+ s -= 6;
+ if (s <= 0) {
+ step = 4;
+ goto fail;
+ }
+
+ ngx_memzero(&pp, sizeof(ngx_proxy_protocol_t));
+
+ if (memcmp(p, "TCP4 ", 5) == 0) {
+ struct sockaddr_in *sin_src;
+ struct sockaddr_in *sin_dst;
+
+ pp.pp_proto = NGX_PP_PROTO_TCP4;
+ pp.pp_src3.ss_family = AF_INET;
+ pp.pp_dst3.ss_family = AF_INET;
+ sin_src = (struct sockaddr_in *) &pp.pp_src3;
+ sin_dst = (struct sockaddr_in *) &pp.pp_dst3;
+
+ p += 5;
+ s -= 5;
+ if (s <= 0) {
+ step = 5;
+ goto fail;
+ }
+
+ /* l3 source address */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 6;
+ goto fail;
+ }
+ len = t - p;
+ if ((sin_src->sin_addr.s_addr = ngx_inet_addr(p, len)) == INADDR_NONE) {
+ step = 7;
+ goto fail;
+ }
+ pp.pp_src3_text.data = ngx_pcalloc(c->pool, len + 1);
+ ngx_memcpy(pp.pp_src3_text.data, p, len);
+ pp.pp_src3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 8;
+ goto fail;
+ }
+
+ /* l3 destination address */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 9;
+ goto fail;
+ }
+ len = t - p;
+ if ((sin_dst->sin_addr.s_addr = ngx_inet_addr(p, len)) == INADDR_NONE) {
+ step = 10;
+ goto fail;
+ }
+// FIXME pointer shift ???
+ pp.pp_dst3_text.data = ngx_pcalloc(c->pool, len + 1);
+ ngx_memcpy(pp.pp_dst3_text.data, p, len);
+ pp.pp_dst3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 11;
+ goto fail;
+ }
+
+ /* l4 source port */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 12;
+ goto fail;
+ }
+ len = t - p;
+ pp.pp_src4 = ngx_atoi(p, len);
+ if ((pp.pp_src4 < 1024)
+ || (pp.pp_src4 > 65535)) {
+ step = 13;
+ goto fail;
+ }
+ sin_src->sin_port = htons(pp.pp_src4);
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 14;
+ goto fail;
+ }
+
+ /* l4 destination port */
+ if ( (t = (u_char *)memchr(p, '\r', s)) == NULL ) {
+ step = 15;
+ goto fail;
+ }
+ len = t - p;
+ pp.pp_dst4 = ngx_atoi(p, len);
+ if (pp.pp_dst4 > 65535) {
+ step = 16;
+ goto fail;
+ }
+ sin_dst->sin_port = htons(pp.pp_dst4);
+
+ if (p[len + 1] != '\n') {
+ step = 17;
+ goto fail;
+ }
+
+ p += (len + 2);
+ s -= (len + 2);
+
+
+ /* if we managed to get there, then we can safely replace the
+ * information in the connection structure
+ */
+
+ /* updating connection with source information provided by proxy protocol */
+ if (pp.pp_src3_text.len > c->addr_text.len) {
+ ngx_pfree(c->pool, c->addr_text.data);
+ c->addr_text.data = ngx_pcalloc(c->pool, pp.pp_src3_text.len);
+ } else {
+ ngx_memzero(c->addr_text.data, c->addr_text.len);
+ }
+ ngx_memcpy(c->addr_text.data, pp.pp_src3_text.data, pp.pp_src3_text.len);
+ c->addr_text.len = pp.pp_src3_text.len;
+
+ ngx_pfree(c->pool, c->sockaddr);
+ c->socklen = NGX_SOCKADDRLEN;
+ c->sockaddr = ngx_pcalloc(c->pool, c->socklen);
+ ngx_memcpy(c->sockaddr, sin_src, c->socklen);
+
+ if (c->sockaddr->sa_family != AF_INET) {
+ ngx_pfree(c->pool, c->sockaddr);
+ c->socklen = NGX_SOCKADDRLEN;
+ c->sockaddr = ngx_pcalloc(c->pool, c->socklen);
+ } else {
+ ngx_memzero(c->sockaddr, sizeof(struct sockaddr_in));
+ c->socklen = NGX_SOCKADDRLEN;
+ }
+ ngx_memcpy(c->sockaddr, sin_src, c->socklen);
+
+ /* updating connection with destination information provided by proxy protocol */
+ ngx_pfree(c->pool, c->local_sockaddr);
+ c->local_sockaddr = ngx_pcalloc(c->pool, NGX_SOCKADDRLEN);
+ ngx_memcpy(c->local_sockaddr, sin_dst, NGX_SOCKADDRLEN);
+
+ }
+
+#if (NGX_HAVE_INET6)
+
+ else if (memcmp(p, "TCP6 ", 5) == 0) {
+
+ struct sockaddr_in6 *sin6_src;
+ struct sockaddr_in6 *sin6_dst;
+
+ pp.pp_proto = NGX_PP_PROTO_TCP6;
+ pp.pp_src3.ss_family = AF_INET6;
+ pp.pp_dst3.ss_family = AF_INET6;
+ sin6_src = (struct sockaddr_in6 *) &pp.pp_src3;
+ sin6_dst = (struct sockaddr_in6 *) &pp.pp_dst3;
+
+ p += 5;
+ s -= 5;
+ if (s <= 0) {
+ step = 18;
+ goto fail;
+ }
+
+ /* l3 source address */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 19;
+ goto fail;
+ }
+ len = t - p;
+ if (ngx_inet6_addr(p, len, sin6_src->sin6_addr.s6_addr) != NGX_OK) {
+ step = 20;
+ goto fail;
+ }
+ pp.pp_src3_text.data = ngx_pcalloc(c->pool, len + 1);
+ ngx_memcpy(pp.pp_src3_text.data, p, len);
+ pp.pp_src3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 21;
+ goto fail;
+ }
+
+ /* l3 destination address */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 22;
+ goto fail;
+ }
+ len = t - p;
+ if (ngx_inet6_addr(p, len, sin6_dst->sin6_addr.s6_addr) != NGX_OK) {
+ step = 23;
+ goto fail;
+ }
+ pp.pp_dst3_text.data = ngx_pcalloc(c->pool, len + 1);
+ ngx_memcpy(pp.pp_dst3_text.data, p, len);
+ pp.pp_dst3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 24;
+ goto fail;
+ }
+
+ /* l4 source port */
+ if ( (t = (u_char *)memchr(p, ' ', s)) == NULL ) {
+ step = 25;
+ goto fail;
+ }
+ len = t - p;
+ pp.pp_src4 = ngx_atoi(p, len);
+ if ((pp.pp_src4 < 1024)
+ || (pp.pp_src4 > 65535)) {
+ step = 26;
+ goto fail;
+ }
+ sin6_src->sin6_port = htons(pp.pp_src4);
+
+ p += (len + 1);
+ s -= (len + 1);
+ if (s <= 0) {
+ step = 27;
+ goto fail;
+ }
+
+ /* l4 destination port */
+ if ( (t = (u_char *)memchr(p, '\r', s)) == NULL ) {
+ step = 28;
+ goto fail;
+ }
+ len = t - p;
+ pp.pp_dst4 = ngx_atoi(p, len);
+ if (pp.pp_dst4 > 65535) {
+ step = 29;
+ goto fail;
+ }
+ sin6_dst->sin6_port = htons(pp.pp_dst4);
+
+ if (p[len + 1] != '\n') {
+ step = 30;
+ goto fail;
+ }
+
+ p += (len + 2);
+ s -= (len + 2);
+
+ /* if we managed to get there, then we can safely replace the
+ * information in the connection structure
+ */
+
+ /* updating connection with source provided by proxy protocol */
+ if (pp.pp_src3_text.len > c->addr_text.len) {
+ ngx_pfree(c->pool, c->addr_text.data);
+ c->addr_text.data = ngx_pcalloc(c->pool, pp.pp_src3_text.len);
+ } else {
+ ngx_memzero(c->addr_text.data, c->addr_text.len);
+ }
+ ngx_memcpy(c->addr_text.data, pp.pp_src3_text.data, pp.pp_src3_text.len);
+ c->addr_text.len = pp.pp_src3_text.len;
+
+ ngx_pfree(c->pool, c->sockaddr);
+ c->socklen = NGX_SOCKADDRLEN;
+ c->sockaddr = ngx_pcalloc(c->pool, c->socklen);
+ ngx_memcpy(c->sockaddr, sin6_src, c->socklen);
+
+ /* updating connection with destination provided by proxy protocol */
+ if (c->sockaddr->sa_family != AF_INET6) {
+ ngx_pfree(c->pool, c->local_sockaddr);
+ c->local_sockaddr = ngx_pcalloc(c->pool, NGX_SOCKADDRLEN);
+ } else {
+ ngx_memzero(c->sockaddr, sizeof(struct sockaddr_in6));
+ c->socklen = NGX_SOCKADDRLEN;
+ }
+// ngx_memcpy(c->local_sockaddr, sin6_dst, NGX_SOCKADDRLEN);
+//FIXME must be finished here
+
+ }
+
+#endif
+
+ else {
+ step = 31;
+ goto fail;
+ }
+
+ ngx_print_proxy_protocol(&pp, c->log);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "proxy_protocol, asking to remove %z chars",
+ end + 1 - buf);
+
+ return (end + 1 - buf);
+
+fail:
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "proxy_protocol error at step: %d", step);
+
+ return 0;
+
+}
+
+
+void
+ngx_print_proxy_protocol(ngx_proxy_protocol_t *p, ngx_log_t *log)
+{
+ switch (p->pp_proto) {
+ case NGX_PP_PROTO_TCP4:
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, proto: TCP4");
+ break;
+ case NGX_PP_PROTO_TCP6:
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, proto: TCP6");
+ break;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, string length: %d", ngx_proxy_protocol_string_length(p));
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, src3: %s, %d", p->pp_src3_text.data, p->pp_src3_text.len);
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, dst3: %s, %d", p->pp_dst3_text.data, p->pp_dst3_text.len);
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, src4: %d", p->pp_src4);
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+ "proxy_protocol, dst4: %d", p->pp_dst4);
+}
+
+
+int
+ngx_proxy_protocol_string_length(ngx_proxy_protocol_t *p)
+{
+ int len = 0;
+
+ /* 'PROXY ' */
+ len += (sizeof("PROXY ") - 1);
+
+ /* protocol version (TCP4 or TCP6) + space */
+ len += (sizeof("TCP0 ") - 1);
+
+ /* src3 + space */
+ len += p->pp_src3_text.len;
+ len += 1;
+
+ /* dst3 + space */
+ len += p->pp_dst3_text.len;
+ len += 1;
+
+ /* src4 */
+ if (p->pp_src4 < 10000)
+ /* 4 digits + 1 space */
+ len += (sizeof("0000 ") - 1);
+ else
+ /* 5 digits + 1 space */
+ len += (sizeof("00000 ") - 1);
+
+ /* dst4 */
+ if (p->pp_dst4 >= 10000)
+ /* 5 digits */
+ len += (sizeof("00000 ") - 1);
+ else if (p->pp_dst4 >= 1000)
+ /* 4 digits */
+ len += (sizeof("0000 ") - 1);
+ else if (p->pp_dst4 >= 100)
+ /* 3 digits */
+ len += (sizeof("000 ") - 1);
+ else if (p->pp_dst4 >= 10)
+ /* 2 digits */
+ len += (sizeof("00 ") - 1);
+ else
+ /* 1 digit */
+ len += (sizeof("0 ") - 1);
+
+ /* CRLF */
+ len += (sizeof(CRLF) - 1);
+
+ return len - 1;
+}
+
+#endif
Index: nginx-1.4.7/src/core/ngx_proxy_protocol.h
===================================================================
--- /dev/null
+++ nginx-1.4.7/src/core/ngx_proxy_protocol.h
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (C) Baptiste Assmann
+ * Copyright (C) Exceliance
+ */
+
+
+#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
+#define _NGX_PROXY_PROTOCOL_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#if (NGX_PROXY_PROTOCOL)
+
+typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t;
+
+typedef enum {
+ NGX_PP_PROTO_TCP4 = 1,
+ NGX_PP_PROTO_TCP6
+} ngx_pp_proto;
+
+
+struct ngx_proxy_protocol_s {
+ unsigned int pp_proto; /* proxy protocol related information */
+ struct sockaddr_storage pp_src3;
+ ngx_str_t pp_src3_text;
+ struct sockaddr_storage pp_dst3;
+ ngx_str_t pp_dst3_text;
+ unsigned int pp_src4;
+ unsigned int pp_dst4;
+};
+
+
+int ngx_recv_proxy_protocol(ngx_connection_t *, u_char *, ssize_t);
+void ngx_print_proxy_protocol(ngx_proxy_protocol_t *, ngx_log_t *);
+int ngx_proxy_protocol_string_length(ngx_proxy_protocol_t *);
+
+
+#endif
+
+#endif /* _NGX_CONNECTION_H_INCLUDED_ */
+
Index: nginx-1.4.7/src/http/modules/ngx_http_proxy_module.c
===================================================================
--- nginx-1.4.7.orig/src/http/modules/ngx_http_proxy_module.c
+++ nginx-1.4.7/src/http/modules/ngx_http_proxy_module.c
@@ -8,7 +8,9 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
-
+#if (NGX_PROXY_PROTOCOL)
+#include <ngx_proxy_protocol.h>
+#endif
typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
@@ -365,6 +367,17 @@ static ngx_command_t ngx_http_proxy_com
offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
NULL },
+#if (NGX_PROXY_PROTOCOL)
+
+ { ngx_string("send_proxy_protocol"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.send_proxy_protocol),
+ NULL },
+
+#endif
+
#if (NGX_HTTP_CACHE)
{ ngx_string("proxy_cache"),
@@ -2420,6 +2433,11 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
conf->upstream.intercept_errors = NGX_CONF_UNSET;
+
+#if (NGX_PROXY_PROTOCOL)
+ conf->upstream.send_proxy_protocol = NGX_CONF_UNSET;
+#endif
+
#if (NGX_HTTP_SSL)
conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
#endif
@@ -2695,6 +2713,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
ngx_conf_merge_value(conf->upstream.intercept_errors,
prev->upstream.intercept_errors, 0);
+#if (NGX_PROXY_PROTOCOL)
+ ngx_conf_merge_value(conf->upstream.send_proxy_protocol,
+ prev->upstream.send_proxy_protocol, 0);
+#endif
+
#if (NGX_HTTP_SSL)
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
prev->upstream.ssl_session_reuse, 1);
Index: nginx-1.4.7/src/http/ngx_http.c
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http.c
+++ nginx-1.4.7/src/http/ngx_http.c
@@ -1228,6 +1228,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, n
#if (NGX_HTTP_SPDY)
ngx_uint_t spdy;
#endif
+#if (NGX_PROXY_PROTOCOL)
+ ngx_uint_t accept_proxy_protocol;
+#endif
/*
* we cannot compare whole sockaddr struct's as kernel
@@ -1283,6 +1286,10 @@ ngx_http_add_addresses(ngx_conf_t *cf, n
#if (NGX_HTTP_SPDY)
spdy = lsopt->spdy || addr[i].opt.spdy;
#endif
+#if (NGX_PROXY_PROTOCOL)
+ accept_proxy_protocol = lsopt->accept_proxy_protocol
+ || addr[i].opt.accept_proxy_protocol;
+#endif
if (lsopt->set) {
@@ -1316,6 +1323,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, n
#if (NGX_HTTP_SPDY)
addr[i].opt.spdy = spdy;
#endif
+#if (NGX_PROXY_PROTOCOL)
+ addr[i].opt.accept_proxy_protocol = accept_proxy_protocol;
+#endif
return NGX_OK;
}
@@ -1762,6 +1772,11 @@ ngx_http_add_listening(ngx_conf_t *cf, n
ls->pool_size = cscf->connection_pool_size;
ls->post_accept_timeout = cscf->client_header_timeout;
+#if (NGX_PROXY_PROTOCOL)
+// CLEANUP: ls->accept_proxy_protocol = cscf->accept_proxy_protocol;
+ ls->accept_proxy_protocol = addr->opt.accept_proxy_protocol;
+#endif
+
clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
ls->logp = clcf->error_log;
@@ -1840,6 +1855,9 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h
#if (NGX_HTTP_SPDY)
addrs[i].conf.spdy = addr[i].opt.spdy;
#endif
+#if (NGX_PROXY_PROTOCOL)
+ addrs[i].conf.accept_proxy_protocol = addr[i].opt.accept_proxy_protocol;
+#endif
if (addr[i].hash.buckets == NULL
&& (addr[i].wc_head == NULL
@@ -1904,6 +1922,9 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_
#if (NGX_HTTP_SPDY)
addrs6[i].conf.spdy = addr[i].opt.spdy;
#endif
+#if (NGX_PROXY_PROTOCOL)
+ addrs6[i].conf.accept_proxy_protocol = addr[i].opt.accept_proxy_protocol;
+#endif
if (addr[i].hash.buckets == NULL
&& (addr[i].wc_head == NULL
Index: nginx-1.4.7/src/http/ngx_http_core_module.c
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_core_module.c
+++ nginx-1.4.7/src/http/ngx_http_core_module.c
@@ -4090,6 +4090,15 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
continue;
}
+#if (NGX_PROXY_PROTOCOL)
+ if (ngx_strncmp(value[n].data, "accept_proxy_protocol=on", 24) == 0) {
+ lsopt.accept_proxy_protocol = 1;
+ lsopt.set = 1;
+ lsopt.bind = 1;
+ continue;
+ }
+#endif
+
if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
struct sockaddr *sa;
Index: nginx-1.4.7/src/http/ngx_http_core_module.h
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_core_module.h
+++ nginx-1.4.7/src/http/ngx_http_core_module.h
@@ -78,6 +78,11 @@ typedef struct {
#if (NGX_HTTP_SPDY)
unsigned spdy:1;
#endif
+
+#if (NGX_PROXY_PROTOCOL)
+ unsigned accept_proxy_protocol:2;
+#endif
+
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:1;
#endif
@@ -234,6 +239,10 @@ struct ngx_http_addr_conf_s {
ngx_http_virtual_names_t *virtual_names;
+#if (NGX_PROXY_PROTOCOL)
+ ngx_flag_t accept_proxy_protocol;
+#endif
+
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
Index: nginx-1.4.7/src/http/ngx_http_request.c
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_request.c
+++ nginx-1.4.7/src/http/ngx_http_request.c
@@ -63,6 +63,9 @@ static void ngx_http_ssl_handshake(ngx_e
static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
#endif
+#if (NGX_PROXY_PROTOCOL)
+static void ngx_http_proxy_protocol(ngx_event_t *rev);
+#endif
static char *ngx_http_client_errors[] = {
@@ -343,6 +346,14 @@ ngx_http_init_connection(ngx_connection_
}
#endif
+#if (NGX_PROXY_PROTOCOL)
+ {
+ if (hc->addr_conf->accept_proxy_protocol) {
+ rev->handler = ngx_http_proxy_protocol;
+ }
+ }
+#endif
+
if (rev->ready) {
/* the deferred accept(), rtsig, aio, iocp */
@@ -364,7 +375,6 @@ ngx_http_init_connection(ngx_connection_
}
}
-
static void
ngx_http_wait_request_handler(ngx_event_t *rev)
{
@@ -469,6 +479,12 @@ ngx_http_wait_request_handler(ngx_event_
}
rev->handler = ngx_http_process_request_line;
+
+#if (NGX_PROXY_PROTOCOL)
+ if (hc->addr_conf->accept_proxy_protocol)
+ rev->handler = ngx_http_proxy_protocol;
+#endif
+
ngx_http_process_request_line(rev);
}
@@ -582,6 +598,67 @@ ngx_http_create_request(ngx_connection_t
return r;
}
+#if (NGX_PROXY_PROTOCOL)
+
+static void
+ngx_http_proxy_protocol(ngx_event_t *rev)
+{
+ ssize_t n;
+ size_t size = 1024;
+ u_char tmpbuf[size];
+ ngx_connection_t *c;
+ ngx_http_connection_t *hc;
+
+ c = rev->data;
+ hc = c->data;
+ rev->handler = ngx_http_wait_request_handler;
+
+#if (NGX_HTTP_SPDY)
+ {
+ if (hc->addr_conf->spdy) {
+ rev->handler = ngx_http_spdy_init;
+ }
+ }
+#endif
+
+#if (NGX_HTTP_SSL)
+ {
+ if (hc->addr_conf->ssl) {
+ rev->handler = ngx_http_ssl_handshake;
+ }
+ }
+#endif
+
+ n = recv(c->fd, tmpbuf, size, MSG_PEEK);
+
+ if ((n <= 0) && (c->listening)
+ && (hc->addr_conf->accept_proxy_protocol)
+ && (!c->proxy_protocol)) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_http_proxy_protocol: pp required but not found");
+ return;
+ }
+ if ((n > 0) && (c->listening)
+ && (hc->addr_conf->accept_proxy_protocol)
+ && (!c->proxy_protocol)) {
+ ssize_t m;
+ if (!(m = ngx_recv_proxy_protocol(c, tmpbuf, n))) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_http_proxy_protocol: pp required but not found");
+ ngx_http_close_connection(c);
+ return;
+ }
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_http_proxy_protocol: pp required and found");
+
+ c->proxy_protocol = 1;
+
+ /* strip the proxy protocol string from the buffer */
+ recv(c->fd, tmpbuf, m, 0);
+ }
+
+ rev->handler(rev);
+}
+
+#endif
+
#if (NGX_HTTP_SSL)
Index: nginx-1.4.7/src/http/ngx_http_upstream.c
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_upstream.c
+++ nginx-1.4.7/src/http/ngx_http_upstream.c
@@ -31,6 +31,10 @@ static ngx_int_t ngx_http_upstream_reini
ngx_http_upstream_t *u);
static void ngx_http_upstream_send_request(ngx_http_request_t *r,
ngx_http_upstream_t *u);
+#if (NGX_PROXY_PROTOCOL)
+static void ngx_http_upstream_send_proxy_protocol(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
+#endif
static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static void ngx_http_upstream_process_header(ngx_http_request_t *r,
@@ -1255,6 +1259,13 @@ ngx_http_upstream_connect(ngx_http_reque
u->request_sent = 0;
+#if (NGX_PROXY_PROTOCOL)
+ if (u->conf->send_proxy_protocol && !(u->ssl && c->ssl == NULL)) {
+ ngx_http_upstream_send_proxy_protocol(r, u);
+ return;
+ }
+#endif
+
if (rc == NGX_AGAIN) {
ngx_add_timer(c->write, u->conf->connect_timeout);
return;
@@ -1498,6 +1509,228 @@ ngx_http_upstream_send_request(ngx_http_
}
+#if (NGX_PROXY_PROTOCOL)
+
+static void
+ngx_http_upstream_send_proxy_protocol(ngx_http_request_t *r, ngx_http_upstream_t *u)
+{
+ size_t len;
+ ngx_int_t rc;
+ ngx_connection_t *uc;
+ ngx_connection_t *cc;
+ ngx_chain_t *pp_string;
+ ngx_proxy_protocol_t pp;
+ ngx_buf_t *b;
+ char port[6];
+ u_char *addr;
+ struct sockaddr_storage sa_src;
+ struct sockaddr_storage sa_dst;
+ socklen_t addrlen = NGX_SOCKADDRLEN;
+ struct sockaddr_in *sin_src;
+ struct sockaddr_in *sin_dst;
+
+#if (NGX_HAVE_INET6)
+
+ struct sockaddr_in6 *sin6_src;
+ struct sockaddr_in6 *sin6_dst;
+
+#endif
+
+
+ uc = u->peer.connection;
+ cc = r->connection;
+
+ if ( !(u->conf->send_proxy_protocol) ) {
+ return;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, uc->log, 0,
+ "http upstream send proxy protocol");
+
+ if (!u->request_sent && ngx_http_upstream_test_connect(uc) != NGX_OK) {
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ return;
+ }
+
+ uc->log->action = "sending proxy protocol to upstream";
+
+ len = 0;
+
+ if (r->connection->proxy_protocol) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, uc->log, 0,
+ "PP: got proxy-protocol from client connection");
+
+ switch (cc->sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+ pp.pp_proto = NGX_PP_PROTO_TCP6;
+ sin6_dst = (struct sockaddr_in6 *) cc->local_sockaddr;
+ sin6_src = (struct sockaddr_in6 *) cc->sockaddr;
+
+ break;
+
+#endif
+
+ default:
+ pp.pp_proto = NGX_PP_PROTO_TCP4;
+ sin_dst = (struct sockaddr_in *) cc->local_sockaddr;
+ sin_src = (struct sockaddr_in *) cc->sockaddr;
+
+ }
+
+ } else {
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, uc->log, 0,
+ "PP: collecting information from socket fd");
+
+ getsockname(cc->fd, (struct sockaddr *) &sa_dst, &addrlen);
+
+ switch (sa_dst.ss_family) {
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+ pp.pp_proto = NGX_PP_PROTO_TCP6;
+ sin6_dst = (struct sockaddr_in6 *) &sa_dst;
+
+ getpeername(cc->fd, (struct sockaddr *) &sa_src, &addrlen);
+ sin6_src = (struct sockaddr_in6 *) &sa_src;
+
+ break;
+
+#endif
+
+ default:
+
+ pp.pp_proto = NGX_PP_PROTO_TCP4;
+ sin_dst = (struct sockaddr_in *) &sa_dst;
+ getpeername(cc->fd, (struct sockaddr *) &sa_src, &addrlen);
+ sin_src = (struct sockaddr_in *) &sa_src;
+ }
+
+
+ }
+
+ switch (pp.pp_proto) {
+
+#if (NGX_HAVE_INET6)
+
+ case NGX_PP_PROTO_TCP6:
+
+ /* dst3 and dst4 */
+ addr = ngx_pcalloc(r->pool, NGX_INET6_ADDRSTRLEN);
+ ngx_inet_ntop(AF_INET6, &sin6_dst->sin6_addr, addr, NGX_INET6_ADDRSTRLEN);
+ pp.pp_dst3_text.data = ngx_pcalloc(r->pool, NGX_INET6_ADDRSTRLEN);
+ pp.pp_dst3_text.len = ngx_strlen(addr);
+ ngx_memcpy(pp.pp_dst3_text.data, addr, pp.pp_dst3_text.len);
+ pp.pp_dst4 = htons(sin6_dst->sin6_port);
+
+ ngx_memzero(addr, NGX_INET6_ADDRSTRLEN);
+
+ /* src3 and src4 */
+ ngx_inet_ntop(AF_INET6, &sin6_src->sin6_addr, addr, NGX_INET6_ADDRSTRLEN);
+ pp.pp_src3_text.data = ngx_pcalloc(r->pool, NGX_INET6_ADDRSTRLEN);
+ pp.pp_src3_text.len = ngx_strlen(addr);
+ ngx_memcpy(pp.pp_src3_text.data, addr, pp.pp_src3_text.len);
+ pp.pp_src4 = htons(sin6_src->sin6_port);
+
+ break;
+
+#endif
+
+ default:
+
+ /* dst3 and dst4 */
+ addr = ngx_pcalloc(r->pool, NGX_INET_ADDRSTRLEN);
+ ngx_inet_ntop(AF_INET, &sin_dst->sin_addr, addr, NGX_INET_ADDRSTRLEN);
+ pp.pp_dst3_text.data = ngx_pcalloc(r->pool, NGX_INET_ADDRSTRLEN);
+ pp.pp_dst3_text.len = ngx_strlen(addr);
+ ngx_memcpy(pp.pp_dst3_text.data, addr, pp.pp_dst3_text.len);
+ pp.pp_dst4 = htons(sin_dst->sin_port);
+
+ ngx_memzero(addr, NGX_INET_ADDRSTRLEN);
+
+ /* src3 and src4 */
+ ngx_inet_ntop(AF_INET, &sin_src->sin_addr, addr, NGX_INET_ADDRSTRLEN);
+ pp.pp_src3_text.data = ngx_pcalloc(r->pool, NGX_INET_ADDRSTRLEN);
+ pp.pp_src3_text.len = ngx_strlen(addr);
+ ngx_memcpy(pp.pp_src3_text.data, addr, pp.pp_src3_text.len);
+ pp.pp_src4 = htons(sin_src->sin_port);
+
+ }
+
+ len += ngx_proxy_protocol_string_length(&pp);
+
+ ngx_print_proxy_protocol(&pp, uc->log);
+
+ b = ngx_create_temp_buf(uc->pool, len);
+ if (b == NULL) {
+ return;
+ }
+
+ pp_string = ngx_alloc_chain_link(uc->pool);
+ if (pp_string == NULL) {
+ return;
+ }
+
+ pp_string->buf = b;
+ pp_string->next = NULL;
+
+ b->last = ngx_cpymem(b->last, "PROXY ", sizeof("PROXY ") - 1);
+
+ switch (pp.pp_proto) {
+ case NGX_PP_PROTO_TCP4:
+ b->last = ngx_cpymem(b->last, "TCP4 ", sizeof("TCP4 ") - 1);
+ break;
+ case NGX_PP_PROTO_TCP6:
+ b->last = ngx_cpymem(b->last, "TCP6 ", sizeof("TCP6 ") - 1);
+ break;
+ }
+
+ /* src3 */
+ b->last = ngx_cpymem(b->last, pp.pp_src3_text.data, pp.pp_src3_text.len);
+ b->last = ngx_cpymem(b->last, " ", 1);
+
+ /* dst3 */
+ b->last = ngx_cpymem(b->last, pp.pp_dst3_text.data, pp.pp_dst3_text.len);
+ b->last = ngx_cpymem(b->last, " ", 1);
+
+ /* src4 */
+ ngx_memzero(port, 6);
+ sprintf(port,"%d", pp.pp_src4);
+ b->last = ngx_cpymem(b->last, port, strlen(port));
+ b->last = ngx_cpymem(b->last, " ", 1);
+
+ /* dst4 */
+ ngx_memzero(port, 6);
+ sprintf(port,"%d", pp.pp_dst4);
+ b->last = ngx_cpymem(b->last, port, strlen(port));
+
+ /* CRLF */
+ b->last = ngx_cpymem(b->last, CRLF, sizeof(CRLF) - 1);
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, uc->log, 0,
+ "http upstream send proxy protocol: %d -%*s-",
+ ngx_proxy_protocol_string_length(&pp),
+ ngx_proxy_protocol_string_length(&pp) - 2,
+ b->start);
+
+ rc = ngx_output_chain(&u->output, pp_string);
+
+ if (rc == NGX_ERROR) {
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ return;
+ }
+
+}
+
+#endif
+
+
static void
ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
ngx_http_upstream_t *u)
Index: nginx-1.4.7/src/http/ngx_http_upstream.h
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_upstream.h
+++ nginx-1.4.7/src/http/ngx_http_upstream.h
@@ -188,6 +188,10 @@ typedef struct {
unsigned intercept_404:1;
unsigned change_buffering:1;
+#if (NGX_PROXY_PROTOCOL)
+ ngx_flag_t send_proxy_protocol;
+#endif
+
#if (NGX_HTTP_SSL)
ngx_ssl_t *ssl;
ngx_flag_t ssl_session_reuse;
Index: nginx-1.4.7/auto/cc/gcc
===================================================================
--- nginx-1.4.7.orig/auto/cc/gcc
+++ nginx-1.4.7/auto/cc/gcc
@@ -168,7 +168,7 @@ esac
# stop on warning
-CFLAGS="$CFLAGS -Werror"
+CFLAGS="$CFLAGS"
# debug
CFLAGS="$CFLAGS -g"
Index: nginx-1.4.7/auto/cc/icc
===================================================================
--- nginx-1.4.7.orig/auto/cc/icc
+++ nginx-1.4.7/auto/cc/icc
@@ -115,7 +115,7 @@ case "$NGX_ICC_VER" in
esac
# stop on warning
-CFLAGS="$CFLAGS -Werror"
+CFLAGS="$CFLAGS "
# debug
CFLAGS="$CFLAGS -g"