Skip to content

Instantly share code, notes, and snippets.

@yostinso
Last active December 23, 2015 18:49
Show Gist options
  • Save yostinso/6678367 to your computer and use it in GitHub Desktop.
Save yostinso/6678367 to your computer and use it in GitHub Desktop.
--- debian/rules 2012-07-12 11:55:28.000000000 -0700
+++ debian/rules 2013-09-23 16:20:57.885799032 -0700
@@ -84,6 +84,7 @@
--with-md5=/usr/include/openssl \
--with-mail \
--with-mail_ssl_module \
+ --with-proxy-protocol \
--add-module=$(MODULESDIR)/nginx-auth-pam \
--add-module=$(MODULESDIR)/nginx-echo \
--add-module=$(MODULESDIR)/nginx-upstream-fair \
diff -Nrpu nginx-1.2.4.orig/auto/modules nginx-1.2.4/auto/modules
--- nginx-1.2.4.orig/auto/modules 2012-07-02 19:41:52.000000000 +0200
+++ nginx-1.2.4/auto/modules 2012-11-26 22:40:37.069218221 +0100
@@ -275,6 +275,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_PROXY . auto/have
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
diff -Nrpu nginx-1.2.4.orig/auto/options nginx-1.2.4/auto/options
--- nginx-1.2.4.orig/auto/options 2012-07-02 18:41:13.000000000 +0200
+++ nginx-1.2.4/auto/options 2012-11-26 22:46:10.254651119 +0100
@@ -47,6 +47,8 @@ USE_THREADS=NO
NGX_FILE_AIO=NO
NGX_IPV6=NO
+PROXY_PROTOCOL=NO
+
HTTP=YES
NGX_HTTP_LOG_PATH=
@@ -190,6 +192,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 ;;
@@ -346,6 +350,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_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
diff -Nrpu nginx-1.2.4.orig/auto/sources nginx-1.2.4/auto/sources
--- nginx-1.2.4.orig/auto/sources 2012-07-02 18:41:13.000000000 +0200
+++ nginx-1.2.4/auto/sources 2012-10-20 09:27:22.836430795 +0200
@@ -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 -Nrpu nginx-1.2.4.orig/src/core/ngx_connection.h nginx-1.2.4/src/core/ngx_connection.h
--- nginx-1.2.4.orig/src/core/ngx_connection.h 2012-01-18 16:07:43.000000000 +0100
+++ nginx-1.2.4/src/core/ngx_connection.h 2012-11-26 21:39:17.840420536 +0100
@@ -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:1;
+#endif
+
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:2;
#endif
@@ -148,6 +152,10 @@ struct ngx_connection_s {
ngx_uint_t requests;
+#if (NGX_PROXY_PROTOCOL)
+ struct ngx_proxy_protocol_s *proxy_protocol; /* PP information */
+#endif
+
unsigned buffered:8;
unsigned log_error:3; /* ngx_connection_log_error_e */
diff -Nrpu nginx-1.2.4.orig/src/core/ngx_core.h nginx-1.2.4/src/core/ngx_core.h
--- nginx-1.2.4.orig/src/core/ngx_core.h 2012-02-13 17:29:04.000000000 +0100
+++ nginx-1.2.4/src/core/ngx_core.h 2012-11-26 21:38:36.636258441 +0100
@@ -22,6 +22,9 @@ typedef struct ngx_file_s ngx_fil
typedef struct ngx_event_s ngx_event_t;
typedef struct ngx_event_aio_s ngx_event_aio_t;
typedef struct ngx_connection_s ngx_connection_t;
+#if (NGX_PROXY_PROTOCOL)
+typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t;
+#endif
typedef void (*ngx_event_handler_pt)(ngx_event_t *ev);
typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
@@ -78,6 +81,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
diff -Nrpu nginx-1.2.4.orig/src/core/ngx_proxy_protocol.c nginx-1.2.4/src/core/ngx_proxy_protocol.c
--- nginx-1.2.4.orig/src/core/ngx_proxy_protocol.c 1970-01-01 01:00:00.000000000 +0100
+++ nginx-1.2.4/src/core/ngx_proxy_protocol.c 2012-12-13 23:58:15.080939359 +0100
@@ -0,0 +1,268 @@
+
+/*
+ * 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;
+ size_t len;
+ ssize_t s;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "processing proxy protocol");
+ s = n;
+ end = memchr(buf, '\n', n);
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "proxy_protocol: %s", buf);
+
+ p = buf;
+ if (memcmp(p, "PROXY ", 6) != 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "incorrect proxy protocol header string");
+ goto fail;
+ }
+ p += 6;
+ s -= 6;
+
+ c->proxy_protocol = ngx_pnalloc(c->pool, sizeof(ngx_proxy_protocol_t));
+ ngx_memzero(c->proxy_protocol, sizeof(ngx_proxy_protocol_t));
+
+ if (memcmp(p, "TCP4 ", 5) == 0) {
+ c->proxy_protocol->pp_proto = NGX_PP_PROTO_TCP4;
+ c->proxy_protocol->pp_src3 = ngx_pnalloc(c->pool, sizeof(struct sockaddr_in));
+ c->proxy_protocol->pp_dst3 = ngx_pnalloc(c->pool, sizeof(struct sockaddr_in));
+ ((struct sockaddr_in *)c->proxy_protocol->pp_src3)->sin_family = AF_INET;
+ ((struct sockaddr_in *)c->proxy_protocol->pp_dst3)->sin_family = AF_INET;
+
+ p += 5;
+ s -= 5;
+
+ /* l3 source address */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ if ((((struct sockaddr_in *)c->proxy_protocol->pp_src3)->sin_addr.s_addr
+ = ngx_inet_addr(p, len)) == INADDR_NONE)
+ goto fail;
+ c->proxy_protocol->pp_src3_text.data = ngx_pnalloc(c->pool, len + 1);
+ ngx_memcpy(c->proxy_protocol->pp_src3_text.data, p, len);
+ c->proxy_protocol->pp_src3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l3 destination address */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ if ((((struct sockaddr_in *)c->proxy_protocol->pp_dst3)->sin_addr.s_addr
+ = ngx_inet_addr(p,len)) == INADDR_NONE) {
+ goto fail;
+ }
+ c->proxy_protocol->pp_dst3_text.data = ngx_pnalloc(c->pool, len + 1);
+ ngx_memcpy(c->proxy_protocol->pp_dst3_text.data, p, len);
+ c->proxy_protocol->pp_dst3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l4 source port */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ c->proxy_protocol->pp_src4 = ngx_atoi(p, len);
+ if ((c->proxy_protocol->pp_src4 < 1) // avoid ICMP? -- yostinso
+ || (c->proxy_protocol->pp_src4 > 65535))
+ goto fail;
+ ((struct sockaddr_in *)c->proxy_protocol->pp_src3)->sin_port =
+ htons(c->proxy_protocol->pp_src4);
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l4 destination port */
+ len = (u_char *)memchr(p, '\r', s) - p;
+ c->proxy_protocol->pp_dst4 = ngx_atoi(p, len);
+ if ((c->proxy_protocol->pp_dst4 < 1) // avoid ICMP? -- yostinso
+ || (c->proxy_protocol->pp_dst4 > 65535)) {
+ goto fail;
+ }
+ ((struct sockaddr_in *)c->proxy_protocol->pp_dst3)->sin_port =
+ htons(c->proxy_protocol->pp_dst4);
+
+ 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 */
+ ngx_pfree(c->pool, c->addr_text.data);
+ c->addr_text = c->proxy_protocol->pp_src3_text;
+ ngx_pfree(c->pool, c->sockaddr);
+ c->sockaddr = c->proxy_protocol->pp_src3;
+ /* updating connection with destination provided by proxy protocol */
+ ngx_pfree(c->pool, c->local_sockaddr);
+ c->local_sockaddr = c->proxy_protocol->pp_dst3;
+
+#if (NGX_HAVE_INET6)
+ } else if (memcmp(p, "TCP6 ", 5) == 0) {
+ c->proxy_protocol->pp_proto = NGX_PP_PROTO_TCP6;
+ c->proxy_protocol->pp_src3 = ngx_pnalloc(c->pool, sizeof(struct sockaddr_in6));
+ c->proxy_protocol->pp_dst3 = ngx_pnalloc(c->pool, sizeof(struct sockaddr_in6));
+ ((struct sockaddr_in6 *)c->proxy_protocol->pp_src3)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)c->proxy_protocol->pp_dst3)->sin6_family = AF_INET6;
+
+ p += 5;
+ s -= 5;
+
+ /* l3 source address */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ if (ngx_inet6_addr(p, len, (((struct sockaddr_in6 *)c->proxy_protocol->pp_src3)->sin6_addr.s6_addr)) != NGX_OK)
+ goto fail;
+ c->proxy_protocol->pp_src3_text.data = ngx_pnalloc(c->pool, len + 1);
+ ngx_memcpy(c->proxy_protocol->pp_src3_text.data, p, len);
+ c->proxy_protocol->pp_src3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l3 destination address */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ if (ngx_inet6_addr(p, len, (((struct sockaddr_in6 *)c->proxy_protocol->pp_dst3)->sin6_addr.s6_addr)) != NGX_OK)
+ goto fail;
+ c->proxy_protocol->pp_dst3_text.data = ngx_pnalloc(c->pool, len + 1);
+ ngx_memcpy(c->proxy_protocol->pp_dst3_text.data, p, len);
+ c->proxy_protocol->pp_dst3_text.len = len;
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l4 source port */
+ len = (u_char *)memchr(p, ' ', s) - p;
+ c->proxy_protocol->pp_src4 = ngx_atoi(p, len);
+ if ((c->proxy_protocol->pp_src4 < 1) // avoid ICMP? -- yostinso
+ || (c->proxy_protocol->pp_src4 > 65535)) {
+ goto fail;
+ }
+ ((struct sockaddr_in6 *)c->proxy_protocol->pp_src3)->sin6_port =
+ htons(c->proxy_protocol->pp_src4);
+
+ p += (len + 1);
+ s -= (len + 1);
+
+ /* l4 destination port */
+ len = (u_char *)memchr(p, '\r', s) - p;
+ c->proxy_protocol->pp_dst4 = ngx_atoi(p, len);
+ if (c->proxy_protocol->pp_dst4 > 65535) {
+ goto fail;
+ }
+ ((struct sockaddr_in6 *)c->proxy_protocol->pp_dst3)->sin6_port =
+ htons(c->proxy_protocol->pp_dst4);
+
+ 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 */
+ ngx_pfree(c->pool, c->addr_text.data);
+ c->addr_text = c->proxy_protocol->pp_src3_text;
+ ngx_pfree(c->pool, c->sockaddr);
+ c->sockaddr = c->proxy_protocol->pp_src3;
+ /* updating connection with destination provided by proxy protocol */
+ ngx_pfree(c->pool, c->local_sockaddr);
+ c->local_sockaddr = c->proxy_protocol->pp_dst3;
+#endif
+ } else {
+ goto fail;
+ }
+
+ 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:
+ if (c->proxy_protocol)
+ ngx_pfree(c->pool, c->proxy_protocol);
+ 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)
+ /* 4 digits */
+ len += (sizeof("0000 ") - 1);
+ else
+ /* 5 digits */
+ len += (sizeof("00000 ") - 1);
+
+ /* CRLF */
+ len += (sizeof(CRLF) - 1);
+
+ return len;
+}
+
+#endif
diff -Nrpu nginx-1.2.4.orig/src/core/ngx_proxy_protocol.h nginx-1.2.4/src/core/ngx_proxy_protocol.h
--- nginx-1.2.4.orig/src/core/ngx_proxy_protocol.h 1970-01-01 01:00:00.000000000 +0100
+++ nginx-1.2.4/src/core/ngx_proxy_protocol.h 2012-11-26 21:41:57.109295151 +0100
@@ -0,0 +1,43 @@
+
+/*
+ * 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 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 *pp_src3;
+ ngx_str_t pp_src3_text;
+ struct sockaddr *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(struct ngx_proxy_protocol_s *, ngx_log_t *);
+int ngx_proxy_protocol_string_length(struct ngx_proxy_protocol_s *);
+
+
+#endif
+
+#endif /* _NGX_CONNECTION_H_INCLUDED_ */
+
diff -Nrpu nginx-1.2.4.orig/src/http/modules/ngx_http_proxy_module.c nginx-1.2.4/src/http/modules/ngx_http_proxy_module.c
--- nginx-1.2.4.orig/src/http/modules/ngx_http_proxy_module.c 2012-04-23 12:40:01.000000000 +0200
+++ nginx-1.2.4/src/http/modules/ngx_http_proxy_module.c 2012-11-26 21:48:45.596338701 +0100
@@ -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;
@@ -368,6 +370,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"),
@@ -2651,6 +2664,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
@@ -2922,6 +2940,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);
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http.c nginx-1.2.4/src/http/ngx_http.c
--- nginx-1.2.4.orig/src/http/ngx_http.c 2012-08-06 18:03:56.000000000 +0200
+++ nginx-1.2.4/src/http/ngx_http.c 2012-11-26 21:49:55.036820260 +0100
@@ -1745,6 +1745,10 @@ 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)
+ ls->accept_proxy_protocol = cscf->accept_proxy_protocol;
+#endif
+
clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
ls->logp = clcf->error_log;
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http_core_module.c nginx-1.2.4/src/http/ngx_http_core_module.c
--- nginx-1.2.4.orig/src/http/ngx_http_core_module.c 2012-09-24 21:06:48.000000000 +0200
+++ nginx-1.2.4/src/http/ngx_http_core_module.c 2012-11-26 21:52:09.249705056 +0100
@@ -291,6 +291,17 @@ static ngx_command_t ngx_http_core_comm
offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
NULL },
+#if (NGX_PROXY_PROTOCOL)
+
+ { ngx_string("accept_proxy_protocol"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_core_srv_conf_t, accept_proxy_protocol),
+ NULL },
+
+#endif
+
{ ngx_string("location"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_http_core_location,
@@ -3362,6 +3373,9 @@ ngx_http_core_create_srv_conf(ngx_conf_t
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
+#if (NGX_PROXY_PROTOCOL)
+ cscf->accept_proxy_protocol = NGX_CONF_UNSET;
+#endif
return cscf;
}
@@ -3405,6 +3419,11 @@ ngx_http_core_merge_srv_conf(ngx_conf_t
ngx_conf_merge_value(conf->underscores_in_headers,
prev->underscores_in_headers, 0);
+#if (NGX_PROXY_PROTOCOL)
+ ngx_conf_merge_value(conf->accept_proxy_protocol,
+ prev->accept_proxy_protocol, 0);
+#endif
+
if (conf->server_names.nelts == 0) {
/* the array has 4 empty preallocated elements, so push cannot fail */
sn = ngx_array_push(&conf->server_names);
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http_core_module.h nginx-1.2.4/src/http/ngx_http_core_module.h
--- nginx-1.2.4.orig/src/http/ngx_http_core_module.h 2012-06-04 13:58:12.000000000 +0200
+++ nginx-1.2.4/src/http/ngx_http_core_module.h 2012-11-26 22:21:59.909603456 +0100
@@ -195,6 +195,9 @@ typedef struct {
ngx_flag_t ignore_invalid_headers;
ngx_flag_t merge_slashes;
ngx_flag_t underscores_in_headers;
+#if (NGX_PROXY_PROTOCOL)
+ ngx_flag_t accept_proxy_protocol;
+#endif
unsigned listen:1;
#if (NGX_PCRE)
@@ -420,6 +423,10 @@ struct ngx_http_core_loc_conf_s {
ngx_flag_t open_file_cache_errors;
ngx_flag_t open_file_cache_events;
+#if (NGX_PROXY_PROTOCOL)
+ ngx_flag_t accept_proxy_protocol;
+#endif
+
ngx_log_t *error_log;
ngx_uint_t types_hash_max_size;
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http_request.c nginx-1.2.4/src/http/ngx_http_request.c
--- nginx-1.2.4.orig/src/http/ngx_http_request.c 2012-08-06 19:36:30.000000000 +0200
+++ nginx-1.2.4/src/http/ngx_http_request.c 2012-11-26 22:04:26.144997094 +0100
@@ -64,6 +64,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[] = {
@@ -516,10 +519,61 @@ ngx_http_init_request(ngx_event_t *rev)
(void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
#endif
+#if (NGX_PROXY_PROTOCOL)
+ rev->handler = ngx_http_proxy_protocol;
+#endif
+
rev->handler(rev);
}
+#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;
+
+ c = rev->data;
+ rev->handler = ngx_http_process_request_line;
+
+#if (NGX_HTTP_SSL)
+ {
+ if (c->ssl) {
+ rev->handler = ngx_http_ssl_handshake;
+ }
+
+ }
+#endif
+
+ n = recv(c->fd, tmpbuf, size, MSG_PEEK);
+
+ if ((n <= 0) && (c->listening) &&
+ (c->listening->accept_proxy_protocol == 1) && (!c->proxy_protocol)) {
+ rev->handler = ngx_http_ssl_handshake;
+ 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) &&
+ (c->listening->accept_proxy_protocol == 1) && (!c->proxy_protocol)) {
+ ssize_t m;
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_http_proxy_protocol: pp required and found");
+ if (!(m = ngx_recv_proxy_protocol(c, tmpbuf, n)))
+ return;
+ /* strip the proxy protocol string from the buffer */
+ recv(c->fd, tmpbuf, m, 0);
+ ngx_print_proxy_protocol(c->proxy_protocol, c->log);
+ }
+
+ rev->handler(rev);
+}
+
+#endif
+
+
#if (NGX_HTTP_SSL)
static void
@@ -591,6 +645,12 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
c->log->action = "reading client request line";
rev->handler = ngx_http_process_request_line;
+
+#if (NGX_PROXY_PROTOCOL)
+ if (c->listening->accept_proxy_protocol)
+ rev->handler = ngx_http_proxy_protocol;
+#endif
+
ngx_http_process_request_line(rev);
}
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http_upstream.c nginx-1.2.4/src/http/ngx_http_upstream.c
--- nginx-1.2.4.orig/src/http/ngx_http_upstream.c 2012-08-06 19:34:08.000000000 +0200
+++ nginx-1.2.4/src/http/ngx_http_upstream.c 2012-12-13 21:52:26.110603738 +0100
@@ -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,
@@ -1217,6 +1221,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;
@@ -1459,6 +1470,189 @@ 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];
+
+
+ pp = r->connection->proxy_protocol;
+ 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) {
+
+ len += ngx_proxy_protocol_string_length(pp);
+
+ } else {
+ u_char *addr;
+ struct sockaddr_storage sa;
+ socklen_t addrlen = NGX_SOCKADDRLEN;
+ struct sockaddr_in *sin;
+
+#if (NGX_HAVE_INET6)
+
+ struct sockaddr_in6 *sin6;
+
+#endif
+
+ pp = ngx_pcalloc(r->pool, sizeof(ngx_proxy_protocol_t));
+
+ getsockname(cc->fd, (struct sockaddr *) &sa, &addrlen);
+
+ switch (sa.ss_family) {
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+ /* protocol version */
+ pp->pp_proto = NGX_PP_PROTO_TCP6;
+
+ /* dst3 and dst4 */
+ sin6 = (struct sockaddr_in6 *) &sa;
+ addr = ngx_pcalloc(r->pool, NGX_INET6_ADDRSTRLEN);
+ ngx_inet_ntop(AF_INET6, &sin6->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->sin6_port);
+
+ ngx_memzero(&sa, sizeof(struct sockaddr_storage));
+ ngx_memzero(addr, NGX_INET6_ADDRSTRLEN);
+
+ /* src3 and src4 */
+ getpeername(cc->fd, (struct sockaddr *) &sa, &addrlen);
+ sin6 = (struct sockaddr_in6 *) &sa;
+ ngx_inet_ntop(AF_INET6, &sin6->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->sin6_port);
+
+ break;
+
+#endif
+
+ default:
+
+ /* protocol version */
+ pp->pp_proto = NGX_PP_PROTO_TCP4;
+
+ /* dst3 and dst4 */
+ sin = (struct sockaddr_in *) &sa;
+ addr = ngx_pcalloc(r->pool, NGX_INET_ADDRSTRLEN);
+ ngx_inet_ntop(AF_INET, &sin->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->sin_port);
+
+ ngx_memzero(&sa, sizeof(struct sockaddr));
+ ngx_memzero(addr, NGX_INET_ADDRSTRLEN);
+
+ /* src3 and src4 */
+ getpeername(cc->fd, (struct sockaddr *) &sa, &addrlen);
+ sin = (struct sockaddr_in *) &sa;
+ ngx_inet_ntop(AF_INET, &sin->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->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;
+
+ 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_debug2(NGX_LOG_DEBUG_HTTP, uc->log, 0,
+ "http upstream send proxy protocol: %d -%s-",
+ ngx_strlen(b->start) + 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)
diff -Nrpu nginx-1.2.4.orig/src/http/ngx_http_upstream.h nginx-1.2.4/src/http/ngx_http_upstream.h
--- nginx-1.2.4.orig/src/http/ngx_http_upstream.h 2012-02-13 12:01:58.000000000 +0100
+++ nginx-1.2.4/src/http/ngx_http_upstream.h 2012-11-26 22:11:20.390599787 +0100
@@ -181,6 +181,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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment