summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2014-03-18 16:43:46 +0000
committerJon Kolb <kolbyjack@gmail.com>2014-03-18 16:43:46 +0000
commitc6e7bb24dc541324343df6e734a44aa8e75b446f (patch)
tree6d8ff6e4a56a211e7cb04578877e4c00981c6da4
parent433c60ea060aa4be99c69bde2eda030f920c97ee (diff)
downloadnginx-c6e7bb24dc541324343df6e734a44aa8e75b446f.tar.gz
Changes with nginx 1.5.12 18 Mar 2014v1.5.12
*) Security: a heap memory buffer overflow might occur in a worker process while handling a specially crafted request by ngx_http_spdy_module, potentially resulting in arbitrary code execution (CVE-2014-0133). Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr. Manuel Sadosky, Buenos Aires, Argentina. *) Feature: the "proxy_protocol" parameters of the "listen" and "real_ip_header" directives, the $proxy_protocol_addr variable. *) Bugfix: in the "fastcgi_next_upstream" directive. Thanks to Lucas Molas.
-rw-r--r--CHANGES16
-rw-r--r--CHANGES.ru16
-rw-r--r--auto/sources6
-rw-r--r--conf/mime.types3
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.h2
-rw-r--r--src/core/ngx_core.h1
-rw-r--r--src/core/ngx_cycle.c6
-rw-r--r--src/core/ngx_proxy_protocol.c91
-rw-r--r--src/core/ngx_proxy_protocol.h23
-rw-r--r--src/core/ngx_resolver.c2
-rw-r--r--src/event/ngx_event_accept.c2
-rw-r--r--src/event/ngx_event_connect.c2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c11
-rw-r--r--src/http/modules/ngx_http_realip_module.c18
-rw-r--r--src/http/ngx_http.c1
-rw-r--r--src/http/ngx_http_core_module.c5
-rw-r--r--src/http/ngx_http_core_module.h2
-rw-r--r--src/http/ngx_http_request.c64
-rw-r--r--src/http/ngx_http_request.h3
-rw-r--r--src/http/ngx_http_spdy.c25
-rw-r--r--src/http/ngx_http_variables.c19
-rw-r--r--src/mail/ngx_mail_handler.c2
-rw-r--r--src/os/unix/ngx_process_cycle.c4
24 files changed, 310 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index 365355e7d..a38f93754 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,20 @@
+Changes with nginx 1.5.12 18 Mar 2014
+
+ *) Security: a heap memory buffer overflow might occur in a worker
+ process while handling a specially crafted request by
+ ngx_http_spdy_module, potentially resulting in arbitrary code
+ execution (CVE-2014-0133).
+ Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr.
+ Manuel Sadosky, Buenos Aires, Argentina.
+
+ *) Feature: the "proxy_protocol" parameters of the "listen" and
+ "real_ip_header" directives, the $proxy_protocol_addr variable.
+
+ *) Bugfix: in the "fastcgi_next_upstream" directive.
+ Thanks to Lucas Molas.
+
+
Changes with nginx 1.5.11 04 Mar 2014
*) Security: memory corruption might occur in a worker process on 32-bit
diff --git a/CHANGES.ru b/CHANGES.ru
index 2d79bee66..139934be0 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,20 @@
+Изменения в nginx 1.5.12 18.03.2014
+
+ *) Безопасность: при обработке специально созданного запроса модулем
+ ngx_http_spdy_module могло происходить переполнение буфера в рабочем
+ процессе, что потенциально могло приводить к выполнению произвольного
+ кода (CVE-2014-0133).
+ Спасибо Lucas Molas из Programa STIC, Fundación Dr. Manuel Sadosky,
+ Buenos Aires, Argentina.
+
+ *) Добавление: параметр proxy_protocol в директивах listen и
+ real_ip_header, переменная $proxy_protocol_addr.
+
+ *) Исправление: в директиве fastcgi_next_upstream.
+ Спасибо Lucas Molas.
+
+
Изменения в nginx 1.5.11 04.03.2014
*) Безопасность: при обработке специально созданного запроса модулем
diff --git a/auto/sources b/auto/sources
index 7ae41b95f..bff0eb166 100644
--- a/auto/sources
+++ b/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
diff --git a/conf/mime.types b/conf/mime.types
index f63a77a55..89be9a4cd 100644
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -32,6 +32,7 @@ types {
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
+ application/vnd.apple.mpegurl m3u8;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
@@ -54,6 +55,7 @@ types {
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
+ application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
@@ -73,6 +75,7 @@ types {
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
+ video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 8ab0e8890..17dda595e 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1005011
-#define NGINX_VERSION "1.5.11"
+#define nginx_version 1005012
+#define NGINX_VERSION "1.5.12"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index d9bc60a77..ed14e6023 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -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 --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index dfcf2d56c..a2d417e8d 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -77,6 +77,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#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 --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 86ed9a6da..d1a89ae1a 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -494,14 +494,14 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen,
- ls[i].sockaddr, ls[n].socklen, 1)
+ ls[i].sockaddr, ls[i].socklen, 1)
== NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].previous = &ls[i];
ls[i].remain = 1;
- if (ls[n].backlog != nls[i].backlog) {
+ if (ls[i].backlog != nls[n].backlog) {
nls[n].listen = 1;
}
@@ -532,7 +532,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
- if (ls[n].deferred_accept && !nls[n].deferred_accept) {
+ if (ls[i].deferred_accept && !nls[n].deferred_accept) {
nls[n].delete_deferred = 1;
} else if (ls[i].deferred_accept != nls[n].deferred_accept)
diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c
new file mode 100644
index 000000000..59ef010fc
--- /dev/null
+++ b/src/core/ngx_proxy_protocol.c
@@ -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 --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h
new file mode 100644
index 000000000..4f3912512
--- /dev/null
+++ b/src/core/ngx_proxy_protocol.h
@@ -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 --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 7fab50abc..645738ce5 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -3062,7 +3062,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
#endif
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
- "connect to %V, fd:%d #%d", &uc->server, s, c->number);
+ "connect to %V, fd:%d #%uA", &uc->server, s, c->number);
rc = connect(s, uc->sockaddr, uc->socklen);
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index e33dce81e..bf67ecee0 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -344,7 +344,7 @@ ngx_event_accept(ngx_event_t *ev)
#endif
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
- "*%d accept: %V fd:%d", c->number, &c->addr_text, s);
+ "*%uA accept: %V fd:%d", c->number, &c->addr_text, s);
if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
if (ngx_add_conn(c) == NGX_ERROR) {
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index fddad0a92..5fcabcfd1 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -122,7 +122,7 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
}
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
- "connect to %V, fd:%d #%d", pc->name, s, c->number);
+ "connect to %V, fd:%d #%uA", pc->name, s, c->number);
rc = connect(s, pc->sockaddr, pc->socklen);
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 24dbbf663..80cd1a220 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1208,6 +1208,10 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
f->fastcgi_stdout = 0;
f->large_stderr = 0;
+ if (f->split_parts) {
+ f->split_parts->nelts = 0;
+ }
+
r->state = 0;
return NGX_OK;
@@ -1488,6 +1492,13 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
rc = ngx_http_parse_header_line(r, &buf, 1);
+ if (rc != NGX_OK) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "invalid header after joining "
+ "FastCGI records");
+ return NGX_ERROR;
+ }
+
h->key.len = r->header_name_end - r->header_name_start;
h->key.data = r->header_name_start;
h->key.data[h->key.len] = '\0';
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index b15954759..7a6211803 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -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_t *r)
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_command_t *cmd, void *conf)
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 --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index c3ac7266c..ce5adb737 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1849,6 +1849,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
#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 --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 74a448a88..b023bdbc8 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -4287,6 +4287,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#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 --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 220c94ee4..799d2fe0d 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -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 --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 5f2cf7d39..4bf9d1fcf 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -343,6 +343,11 @@ ngx_http_init_connection(ngx_connection_t *c)
}
#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_t *c)
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_t *rev)
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;
+ }
+ }
+
c->log->action = "reading client request line";
ngx_reusable_connection(c, 0);
@@ -589,7 +616,8 @@ ngx_http_create_request(ngx_connection_t *c)
static void
ngx_http_ssl_handshake(ngx_event_t *rev)
{
- u_char buf[1];
+ u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
+ size_t size;
ssize_t n;
ngx_err_t err;
ngx_int_t rc;
@@ -598,6 +626,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_http_ssl_srv_conf_t *sscf;
c = rev->data;
+ hc = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http check ssl handshake");
@@ -613,7 +642,9 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
return;
}
- n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
+ size = hc->proxy_protocol ? sizeof(buf) : 1;
+
+ n = recv(c->fd, (char *) buf, size, MSG_PEEK);
err = ngx_socket_errno;
@@ -640,12 +671,39 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
return;
}
+ if (hc->proxy_protocol) {
+ hc->proxy_protocol = 0;
+
+ p = ngx_proxy_protocol_parse(c, buf, buf + n);
+
+ if (p == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ size = p - buf;
+
+ if (c->recv(c, buf, size) != (ssize_t) size) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ c->log->action = "SSL handshaking";
+
+ if (n == (ssize_t) size) {
+ ngx_post_event(rev, &ngx_posted_events);
+ return;
+ }
+
+ n = 1;
+ buf[0] = *p;
+ }
+
if (n == 1) {
if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"https ssl handshake: 0x%02Xd", buf[0]);
- hc = c->data;
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_ssl_module);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 3b0858ace..a1295e799 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -309,8 +309,9 @@ typedef struct {
ngx_int_t nfree;
#if (NGX_HTTP_SSL)
- ngx_uint_t ssl; /* unsigned ssl:1; */
+ unsigned ssl:1;
#endif
+ unsigned proxy_protocol:1;
} ngx_http_connection_t;
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 4005bfbe7..6e45f4b46 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -95,6 +95,8 @@ static void ngx_http_spdy_read_handler(ngx_event_t *rev);
static void ngx_http_spdy_write_handler(ngx_event_t *wev);
static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc);
+static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc,
+ u_char *pos, u_char *end);
static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc,
u_char *pos, u_char *end);
static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc,
@@ -421,6 +423,11 @@ ngx_http_spdy_init(ngx_event_t *rev)
sc->handler = ngx_http_spdy_state_head;
+ if (hc->proxy_protocol) {
+ c->log->action = "reading PROXY protocol";
+ sc->handler = ngx_http_spdy_proxy_protocol;
+ }
+
sc->zstream_in.zalloc = ngx_http_spdy_zalloc;
sc->zstream_in.zfree = ngx_http_spdy_zfree;
sc->zstream_in.opaque = sc;
@@ -810,6 +817,22 @@ ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc)
static u_char *
+ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos,
+ u_char *end)
+{
+ pos = ngx_proxy_protocol_parse(sc->connection, pos, end);
+
+ if (pos == NULL) {
+ return ngx_http_spdy_state_protocol_error(sc);
+ }
+
+ sc->connection->log->action = "processing SPDY";
+
+ return ngx_http_spdy_state_complete(sc, pos, end);
+}
+
+
+static u_char *
ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
u_char *end)
{
@@ -1849,7 +1872,7 @@ static u_char *
ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler)
{
-#if (NGX_DEBUG)
+#if 1
if (end - pos > NGX_SPDY_STATE_BUFFER_SIZE) {
ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
"spdy state buffer overflow: "
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 8b86d5a9a..f61862297 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -54,6 +54,8 @@ 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_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
@@ -183,6 +185,9 @@ 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_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
{ ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
@@ -1206,6 +1211,20 @@ 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_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;
+}
+
+
+static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 7cfff1a07..9212a121c 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -127,7 +127,7 @@ ngx_mail_init_connection(ngx_connection_t *c)
c->data = s;
s->connection = c;
- ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V",
+ ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %V connected to %V",
c->number, &c->addr_text, s->addr_text);
ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t));
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 499039a7e..be55cea20 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -1046,8 +1046,8 @@ ngx_worker_process_exit(ngx_cycle_t *cycle)
&& !c[i].read->resolver)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- "open socket #%d left in connection %ui",
- c[i].fd, i);
+ "*%uA open socket #%d left in connection %ui",
+ c[i].number, c[i].fd, i);
ngx_debug_quit = 1;
}
}